diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /build | |
parent | Initial commit. (diff) | |
download | firefox-upstream/124.0.1.tar.xz firefox-upstream/124.0.1.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
637 files changed, 84029 insertions, 0 deletions
diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..82af965f00 --- /dev/null +++ b/build.gradle @@ -0,0 +1,407 @@ +import org.tomlj.Toml +import org.tomlj.TomlParseResult +import org.tomlj.TomlTable + +buildscript { + repositories { + gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository -> + maven { + url repository + if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) { + allowInsecureProtocol = true + } + } + } + } + + ext.kotlin_version = '1.8.21' + + dependencies { + classpath 'org.mozilla.apilint:apilint:0.5.2' + classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'org.apache.commons:commons-exec:1.3' + classpath 'com.diffplug.spotless:spotless-plugin-gradle:6.18.0' + classpath 'org.tomlj:tomlj:1.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +def tryInt = { string -> + if (string == null) { + return string + } + if (string.isInteger()) { + return string as Integer + } + return string +} + +// Parses the Cargo.lock and returns the version for the given package name. +def getRustVersionFor(packageName) { + String version = null; + TomlParseResult result = Toml.parse(file("Cargo.lock").getText()); + for (object in result.getArray("package").toList()) { + def table = (TomlTable) object + if (table.getString("name") == packageName) { + if (version != null) { + throw new StopExecutionException("Multiple versions for '${packageName}' found." + + " Ensure '${packageName}' is only included once.") + } + version = table.getString("version") + } + } + return version +} + +allprojects { + // Expose the per-object-directory configuration to all projects. + ext { + mozconfig = gradle.mozconfig + topsrcdir = gradle.mozconfig.topsrcdir + topobjdir = gradle.mozconfig.topobjdir + + gleanVersion = "57.0.0" + if (gleanVersion != getRustVersionFor("glean")) { + throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," + + " found ${getRustVersionFor("glean")}") + } + + artifactSuffix = getArtifactSuffix() + versionName = getVersionName() + versionCode = computeVersionCode() + versionNumber = getVersionNumber() + buildId = getBuildId() + + buildToolsVersion = mozconfig.substs.ANDROID_BUILD_TOOLS_VERSION + compileSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK) + targetSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK) + minSdkVersion = tryInt(mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION) + manifestPlaceholders = [ + ANDROID_PACKAGE_NAME: mozconfig.substs.ANDROID_PACKAGE_NAME, + ANDROID_TARGET_SDK: mozconfig.substs.ANDROID_TARGET_SDK, + MOZ_ANDROID_MIN_SDK_VERSION: mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION, + ] + } + + repositories { + gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository -> + maven { + url repository + if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) { + allowInsecureProtocol = true + } + } + } + } + + // Use the semanticdb-javac and semanticdb-kotlinc plugins to generate semanticdb files for Searchfox + if (mozconfig.substs.ENABLE_MOZSEARCH_PLUGIN || mozconfig.substs.DOWNLOAD_ALL_GRADLE_DEPENDENCIES) { + def targetRoot = new File(topobjdir, "mozsearch_java_index") + def semanticdbJavacVersion = "com.sourcegraph:semanticdb-javac:0.9.6" + def semanticdbKotlincVersion = "com.sourcegraph:semanticdb-kotlinc:0.3.2" + + afterEvaluate { + def addDependencyToConfigurationIfExists = { configurationName, dependency -> + def configuration = configurations.findByName(configurationName) + if (configuration != null) { + dependencies.add(configurationName, dependency) + } + } + + addDependencyToConfigurationIfExists("compileOnly", semanticdbJavacVersion) + addDependencyToConfigurationIfExists("testCompileOnly", semanticdbJavacVersion) + addDependencyToConfigurationIfExists("androidTestCompileOnly", semanticdbJavacVersion) + addDependencyToConfigurationIfExists("kotlinCompilerPluginClasspath", semanticdbKotlincVersion) + } + + tasks.withType(JavaCompile) { + options.compilerArgs += [ + "-Xplugin:semanticdb -sourceroot:${topsrcdir} -targetroot:${targetRoot}", + ] + } + + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + compilerOptions.freeCompilerArgs.addAll([ + "-P", "plugin:semanticdb-kotlinc:sourceroot=${topsrcdir}", + "-P", "plugin:semanticdb-kotlinc:targetroot=${targetRoot}", + ]) + } + } + + task downloadDependencies() { + description 'Download all dependencies to the Gradle cache' + doLast { + configurations.each { configuration -> + if (configuration.canBeResolved) { + configuration.allDependencies.each { dependency -> + try { + configuration.files(dependency) + } catch(e) { + println("Could not resolve ${configuration.name} -> ${dependency.name}") + println(" > ${e.message}") + if (e.cause) { + println(" >> ${e.cause}") + if (e.cause.cause) { + println(" >> ${e.cause.cause}") + } + } + println("") + } + } + } + } + } + } +} + +buildDir "${topobjdir}/gradle/build" + +// A stream that processes bytes line by line, prepending a tag before sending +// each line to Gradle's logging. +class TaggedLogOutputStream extends org.apache.commons.exec.LogOutputStream { + String tag + Logger logger + + TaggedLogOutputStream(tag, logger) { + this.tag = tag + this.logger = logger + } + + void processLine(String line, int level) { + logger.lifecycle("${this.tag} ${line}") + } +} + +ext.geckoBinariesOnlyIf = { task -> + // Never when Gradle was invoked within `mach build`. + if ('1' == System.env.GRADLE_INVOKED_WITHIN_MACH_BUILD) { + rootProject.logger.lifecycle("Skipping task ${task.path} because: within `mach build`") + return false + } + + // Never for official builds. + if (mozconfig.substs.MOZILLA_OFFICIAL) { + rootProject.logger.lifecycle("Skipping task ${task.path} because: MOZILLA_OFFICIAL") + return false + } + + // Multi-l10n builds set `AB_CD=multi`, which isn't a valid locale, and + // `MOZ_CHROME_MULTILOCALE`. To avoid failures, if Gradle is invoked with + // either, we don't invoke Make at all; this allows a multi-locale omnijar + // to be consumed without modification. + if ('multi' == System.env.AB_CD || System.env.MOZ_CHROME_MULTILOCALE) { + rootProject.logger.lifecycle("Skipping task ${task.path} because: AB_CD=multi") + return false + } + + // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and handle resource + // and code generation themselves. + if ('1' == System.env.IS_LANGUAGE_REPACK) { + rootProject.logger.lifecycle("Skipping task ${task.path} because: IS_LANGUAGE_REPACK") + return false + } + + rootProject.logger.lifecycle("Executing task ${task.path}") + return true +} + +// Non-official versions are like "61.0a1", where "a1" is the milestone. +// This simply strips that off, leaving "61.0" in this example. +def getAppVersionWithoutMilestone() { + return project.ext.mozconfig.substs.MOZ_APP_VERSION.replaceFirst(/a[0-9]/, "") +} + +// This converts MOZ_APP_VERSION into an integer +// version code. +// +// We take something like 58.1.2a1 and come out with 5800102 +// This gives us 3 digits for the major number, and 2 digits +// each for the minor and build number. Beta and Release +// +// This must be synchronized with _compute_gecko_version(...) in /taskcluster/gecko_taskgraph/transforms/task.py +def computeVersionCode() { + String appVersion = getAppVersionWithoutMilestone() + + // Split on the dot delimiter, e.g. 58.1.1a1 -> ["58, "1", "1a1"] + String[] parts = appVersion.split('\\.') + + assert parts.size() == 2 || parts.size() == 3 + + // Major + int code = Integer.parseInt(parts[0]) * 100000 + + // Minor + code += Integer.parseInt(parts[1]) * 100 + + // Build + if (parts.size() == 3) { + code += Integer.parseInt(parts[2]) + } + + return code; +} + +def getVersionName() { + return "${mozconfig.substs.MOZ_APP_VERSION}-${mozconfig.substs.MOZ_UPDATE_CHANNEL}" +} + +// Mimic Python: open(os.path.join(buildconfig.topobjdir, 'buildid.h')).readline().split()[2] +def getBuildId() { + return file("${topobjdir}/buildid.h").getText('utf-8').split()[2] +} + +def getVersionNumber() { + def appVersion = getAppVersionWithoutMilestone() + def parts = appVersion.split('\\.') + def version = parts[0] + "." + parts[1] + "." + getBuildId() + def substs = project.ext.mozconfig.substs + if (!substs.MOZILLA_OFFICIAL && !substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) { + // Use -SNAPSHOT versions locally to enable the local GeckoView substitution flow. + version += "-SNAPSHOT" + } + return version +} + +def getArtifactSuffix() { + def substs = project.ext.mozconfig.substs + + def suffix = "" + // Release artifacts don't specify the channel, for the sake of simplicity. + if (substs.MOZ_UPDATE_CHANNEL != 'release') { + suffix += "-${mozconfig.substs.MOZ_UPDATE_CHANNEL}" + } + + return suffix +} + +class MachExec extends Exec { + def MachExec() { + // Bug 1543982: When invoking `mach build` recursively, the outer `mach + // build` itself modifies the environment, causing configure to run + // again. This tries to restore the environment that the outer `mach + // build` was invoked in. See the comment in + // $topsrcdir/settings.gradle. + project.ext.mozconfig.mozconfig.env.unmodified.each { k, v -> environment.remove(k) } + environment project.ext.mozconfig.orig_mozconfig.env.unmodified + environment 'MOZCONFIG', project.ext.mozconfig.substs.MOZCONFIG + } +} + +task machBuildFaster(type: MachExec) { + onlyIf rootProject.ext.geckoBinariesOnlyIf + + workingDir "${topsrcdir}" + + commandLine mozconfig.substs.PYTHON3 + args "${topsrcdir}/mach" + args 'build' + args 'faster' + + // Add `-v` if we're running under `--info` (or `--debug`). + if (project.logger.isEnabled(LogLevel.INFO)) { + args '-v' + } + + // `path` is like `:machBuildFaster`. + standardOutput = new TaggedLogOutputStream("${path}>", logger) + errorOutput = standardOutput +} + +task machStagePackage(type: MachExec) { + onlyIf rootProject.ext.geckoBinariesOnlyIf + + dependsOn rootProject.machBuildFaster + + workingDir "${topobjdir}" + + // We'd prefer this to be a `mach` invocation, but `mach build + // mobile/android/installer/stage-package` doesn't work as expected. + commandLine mozconfig.substs.GMAKE + args '-C' + args "${topobjdir}/mobile/android/installer" + args 'stage-package' + + outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja" + + outputs.file "${topobjdir}/dist/geckoview/assets/${mozconfig.substs.ANDROID_CPU_ARCH}/libxul.so" + outputs.file "${topobjdir}/dist/geckoview/lib/${mozconfig.substs.ANDROID_CPU_ARCH}/libmozglue.so" + + // Force running `stage-package`. + outputs.upToDateWhen { false } + + // `path` is like `:machStagePackage`. + standardOutput = new TaggedLogOutputStream("${path}>", logger) + errorOutput = standardOutput +} + +afterEvaluate { + subprojects { project -> + tasks.withType(JavaCompile) { + // Add compiler args for all code except third-party code. + options.compilerArgs += [ + // Turn on all warnings, except... + "-Xlint:all", + // Deprecation, because we do use deprecated API for compatibility. + "-Xlint:-deprecation", + // Serial, because we don't use Java serialization. + "-Xlint:-serial", + // Classfile, because javac has a bug with MethodParameters attributes + // with Java 7. https://bugs.openjdk.java.net/browse/JDK-8190452 + "-Xlint:-classfile", + // Turn all remaining warnings into errors, + // unless marked by @SuppressWarnings. + "-Werror"] + } + } +} + +apply plugin: 'idea' + +idea { + project { + languageLevel = '1.8' + } + + module { + // Object directories take a huge amount of time for IntelliJ to index. + // Exclude them. Convention is that object directories start with obj. + // IntelliJ is clever and will not exclude the parts of the object + // directory that are referenced, if there are any. In practice, + // indexing the entirety of the tree is taking too long, so exclude all + // but mobile/. + def topsrcdirURI = file(topsrcdir).toURI() + excludeDirs += files(file(topsrcdir) + .listFiles({it.isDirectory()} as FileFilter) + .collect({topsrcdirURI.relativize(it.toURI()).toString()}) // Relative paths. + .findAll({!it.equals('mobile/')})) + + // If topobjdir is below topsrcdir, hide only some portions of that tree. + def topobjdirURI = file(topobjdir).toURI() + if (!topsrcdirURI.relativize(topobjdirURI).isAbsolute()) { + excludeDirs -= file(topobjdir) + excludeDirs += files(file(topobjdir).listFiles()) + excludeDirs -= file("${topobjdir}/gradle") + } + } +} + +subprojects { + apply plugin: "com.diffplug.spotless" + + spotless { + java { + target project.fileTree(project.projectDir) { + include '**/*.java' + exclude '**/thirdparty/**' + } + googleJavaFormat('1.17.0') + } + kotlin { + target project.fileTree(project.projectDir) { + include '**/*.kt' + exclude '**/thirdparty/**' + } + ktlint('0.48.2') + } + } +} diff --git a/build/.gdbinit b/build/.gdbinit new file mode 100644 index 0000000000..870c0a81da --- /dev/null +++ b/build/.gdbinit @@ -0,0 +1,208 @@ +# 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/. + +# .gdbinit file for debugging Mozilla + +# You may need to put an 'add-auto-load-safe-path' command in your +# $HOME/.gdbinit file to get GDB to trust this file. If your builds are +# generally in $HOME/moz, then you can say: +# +# add-auto-load-safe-path ~/moz + +# Don't stop for the SIG32/33/etc signals that Flash produces +handle SIG32 noprint nostop pass +handle SIG33 noprint nostop pass +handle SIGPIPE noprint nostop pass + +# Don't stop for certain other signals where it's not useful, +# such as the SIG64 signals triggered by the Linux +# sandboxing code on older kernels. +handle SIG38 noprint nostop pass +handle SIG64 noprint nostop pass +handle SIGSYS noprint nostop pass + +# Show the concrete types behind nsIFoo +set print object on + +# run when using the auto-solib-add trick +define prun + tbreak main + run + set auto-solib-add 0 + cont +end + +# run -mail, when using the auto-solib-add trick +define pmail + tbreak main + run -mail + set auto-solib-add 0 + cont +end + +# Define a "pu" command to display PRUnichar * strings (100 chars max) +# Also allows an optional argument for how many chars to print as long as +# it's less than 100. +define pu + set $uni = $arg0 + if $argc == 2 + set $limit = $arg1 + if $limit > 100 + set $limit = 100 + end + else + set $limit = 100 + end + # scratch array with space for 100 chars plus null terminator. Make + # sure to not use ' ' as the char so this copy/pastes well. + set $scratch = "____________________________________________________________________________________________________" + set $i = 0 + set $scratch_idx = 0 + while (*$uni && $i++ < $limit) + if (*$uni < 0x80) + set $scratch[$scratch_idx++] = *(char*)$uni++ + else + if ($scratch_idx > 0) + set $scratch[$scratch_idx] = '\0' + print $scratch + set $scratch_idx = 0 + end + print /x *(short*)$uni++ + end + end + if ($scratch_idx > 0) + set $scratch[$scratch_idx] = '\0' + print $scratch + end +end + +# Define a "ps" command to display subclasses of nsAC?String. Note that +# this assumes strings as of Gecko 1.9 (well, and probably a few +# releases before that as well); going back far enough will get you +# to string classes that this function doesn't work for. +define ps + set $str = $arg0 + if (sizeof(*$str.mData) == 1 && ($str.mFlags & 1) != 0) + print $str.mData + else + pu $str.mData $str.mLength + end +end + +# Define a "pa" command to display the string value for an nsAtom +define pa + set $atom = $arg0 + if (sizeof(*((&*$atom)->mString)) == 2) + pu (&*$atom)->mString + end +end + +# define a "pxul" command to display the type of a XUL element from +# an nsXULElement* pointer. +define pxul + set $p = $arg0 + print $p->mNodeInfo.mRawPtr->mInner.mName->mStaticAtom->mString +end + +# define a "prefcnt" command to display the refcount of an XPCOM obj +define prefcnt + set $p = $arg0 + print ((nsPurpleBufferEntry*)$p->mRefCnt.mTagged)->mRefCnt +end + +# define a "ptag" command to display the tag name of a content node +define ptag + set $p = $arg0 + pa $p->mNodeInfo.mRawPtr->mInner.mName +end + +## +## nsTArray +## +define ptarray + if $argc == 0 + help ptarray + else + set $size = $arg0.mHdr->mLength + set $capacity = $arg0.mHdr->mCapacity + set $size_max = $size - 1 + set $elts = $arg0.Elements() + end + if $argc == 1 + set $i = 0 + while $i < $size + printf "elem[%u]: ", $i + p *($elts + $i) + set $i++ + end + end + if $argc == 2 + set $idx = $arg1 + if $idx < 0 || $idx > $size_max + printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max + else + printf "elem[%u]: ", $idx + p *($elts + $idx) + end + end + if $argc == 3 + set $start_idx = $arg1 + set $stop_idx = $arg2 + if $start_idx > $stop_idx + set $tmp_idx = $start_idx + set $start_idx = $stop_idx + set $stop_idx = $tmp_idx + end + if $start_idx < 0 || $stop_idx < 0 || $start_idx > $size_max || $stop_idx > $size_max + printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max + else + set $i = $start_idx + while $i <= $stop_idx + printf "elem[%u]: ", $i + p *($elts + $i) + set $i++ + end + end + end + if $argc > 0 + printf "nsTArray length = %u\n", $size + printf "nsTArray capacity = %u\n", $capacity + printf "Element " + whatis *$elts + end +end + +document ptarray + Prints nsTArray information. + Syntax: ptarray + Note: idx, idx1 and idx2 must be in acceptable range [0...size()-1]. + Examples: + ptarray a - Prints tarray content, size, capacity and T typedef + ptarray a 0 - Prints element[idx] from tarray + ptarray a 1 2 - Prints elements in range [idx1..idx2] from tarray +end + +define js + call DumpJSStack() +end + +define ct + call $arg0->Dump() +end + +define ft + call $arg0->DumpFrameTree() +end + +define ftp + call $arg0->DumpFrameTreeInCSSPixels() +end + +define ftl + call $arg0->DumpFrameTreeLimited() +end + +define ftlp + call $arg0->DumpFrameTreeLimitedInCSSPixels() +end diff --git a/build/.gdbinit.loader b/build/.gdbinit.loader new file mode 100644 index 0000000000..e8a13432f7 --- /dev/null +++ b/build/.gdbinit.loader @@ -0,0 +1,29 @@ +# 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/. + +# loader for .gdbinit file + +# This file provides a guard against multiple inclusion. GDB command syntax is +# rather limited in that you cannot have a `documentation` command inside of an +# `if`. So we use a separate loader file that sources `.gdbinit` within the +# `if`. + +# You may need to put an 'add-auto-load-safe-path' command in your +# $HOME/.gdbinit file to get GDB to trust this file. If your builds are +# generally in $HOME/moz, then you can say: +# +# add-auto-load-safe-path ~/moz + +# Multiple include guard +if $_moz_gdbinit_loaded + # already loaded +else + set $_moz_gdbinit_loaded=1 + + source -s build/.gdbinit + + # This requires $objdir to have been added to gdb's source directory search + # path. Normally this will be done by libxul.so-gdb.py or js-gdb.py. + source -s build/.gdbinit.py +end diff --git a/build/.gdbinit.py.in b/build/.gdbinit.py.in new file mode 100644 index 0000000000..ec8c11b51b --- /dev/null +++ b/build/.gdbinit.py.in @@ -0,0 +1,19 @@ +#filter substitution + +import os +import sys + +sys.path.append(os.path.join('@topsrcdir@', 'js', 'src', 'gdb')) +sys.path.append(os.path.join('@topsrcdir@', 'python', 'gdbpp')) + +# JS prettyprinters + +import mozilla.autoload +mozilla.autoload.register(gdb.current_objfile()) + +import mozilla.asmjs +mozilla.asmjs.install() + +# Gecko prettyprinters + +import gdbpp diff --git a/build/.lldbinit.in b/build/.lldbinit.in new file mode 100644 index 0000000000..bf43fe9cff --- /dev/null +++ b/build/.lldbinit.in @@ -0,0 +1,21 @@ +# This must be the first Python variable set in this file +script ignore__see_bug_1605268 = True + +#filter substitution +script topsrcdir = "@topsrcdir@"; lldb.debugger.HandleCommand("command source -s true '%s'" % os.path.join(topsrcdir, ".lldbinit")) + +#ifdef MOZ_WIDGET_ANDROID +settings set symbols.enable-external-lookup true + +# This is where libxul.so and libmozglue.so are produced in full builds. +settings append target.exec-search-paths @topobjdir@/toolkit/library/build +settings append target.exec-search-paths @topobjdir@/mozglue/build +settings append target.exec-search-paths @topobjdir@/security + +# This is where artifact builds unpacks "crashreporter-symbols-full" uncompressed ELF debug symbols. +settings append target.debug-file-search-paths @topobjdir@/dist/crashreporter-symbols + +# These are specific paths encoded into Mozilla's automation outputs. +settings append target.source-map /builds/worker/workspace/build/src/obj-firefox @topobjdir@ +settings append target.source-map /builds/worker/workspace/build/src @topsrcdir@ +#endif diff --git a/build/RunCbindgen.py b/build/RunCbindgen.py new file mode 100644 index 0000000000..e166556f68 --- /dev/null +++ b/build/RunCbindgen.py @@ -0,0 +1,102 @@ +# 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/. + +import os +import subprocess + +import buildconfig +import mozpack.path as mozpath +import six +import toml + + +# Try to read the package name or otherwise assume same name as the crate path. +def _get_crate_name(crate_path): + try: + with open(mozpath.join(crate_path, "Cargo.toml"), encoding="utf-8") as f: + return toml.load(f)["package"]["name"] + except Exception: + return mozpath.basename(crate_path) + + +CARGO_LOCK = mozpath.join(buildconfig.topsrcdir, "Cargo.lock") +CARGO_TOML = mozpath.join(buildconfig.topsrcdir, "Cargo.toml") + + +def _run_process(args): + env = os.environ.copy() + env["CARGO"] = str(buildconfig.substs["CARGO"]) + env["RUSTC"] = str(buildconfig.substs["RUSTC"]) + + p = subprocess.Popen(args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + stdout, stderr = p.communicate() + stdout = six.ensure_text(stdout) + stderr = six.ensure_text(stderr) + if p.returncode != 0: + print(stdout) + print(stderr) + return (stdout, p.returncode) + + +def generate_metadata(output, cargo_config): + args = [ + buildconfig.substs["CARGO"], + "metadata", + "--all-features", + "--format-version", + "1", + "--manifest-path", + CARGO_TOML, + ] + + # The Spidermonkey library can be built from a package tarball outside the + # tree, so we want to let Cargo create lock files in this case. When built + # within a tree, the Rust dependencies have been vendored in so Cargo won't + # touch the lock file. + if not buildconfig.substs.get("JS_STANDALONE"): + args.append("--frozen") + + stdout, returncode = _run_process(args) + + if returncode != 0: + return returncode + + output.write(stdout) + + # This is not quite accurate, but cbindgen only cares about a subset of the + # data which, when changed, causes these files to change. + return set([CARGO_LOCK, CARGO_TOML]) + + +def generate(output, metadata_path, cbindgen_crate_path, *in_tree_dependencies): + stdout, returncode = _run_process( + [ + buildconfig.substs["CBINDGEN"], + buildconfig.topsrcdir, + "--lockfile", + CARGO_LOCK, + "--crate", + _get_crate_name(cbindgen_crate_path), + "--metadata", + metadata_path, + "--cpp-compat", + ] + ) + + if returncode != 0: + return returncode + + output.write(stdout) + + deps = set() + deps.add(CARGO_LOCK) + deps.add(mozpath.join(cbindgen_crate_path, "cbindgen.toml")) + for directory in in_tree_dependencies + (cbindgen_crate_path,): + for path, dirs, files in os.walk(directory): + for file in files: + if os.path.splitext(file)[1] == ".rs": + deps.add(mozpath.join(path, file)) + + return deps diff --git a/build/__init__.py b/build/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/build/__init__.py diff --git a/build/android/libgcc.a b/build/android/libgcc.a new file mode 100644 index 0000000000..d8349075d7 --- /dev/null +++ b/build/android/libgcc.a @@ -0,0 +1 @@ +INPUT(-lunwind) diff --git a/build/appini_header.py b/build/appini_header.py new file mode 100644 index 0000000000..4cf9481ea0 --- /dev/null +++ b/build/appini_header.py @@ -0,0 +1,90 @@ +# 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/. + +"""Parses a given application.ini file and outputs the corresponding + StaticXREAppData structure as a C++ header file""" + +import configparser +import sys + + +def main(output, file): + config = configparser.RawConfigParser() + config.read(file) + flags = set() + try: + if config.getint("XRE", "EnableProfileMigrator") == 1: + flags.add("NS_XRE_ENABLE_PROFILE_MIGRATOR") + except Exception: + pass + try: + if config.getint("Crash Reporter", "Enabled") == 1: + flags.add("NS_XRE_ENABLE_CRASH_REPORTER") + except Exception: + pass + appdata = dict( + ("%s:%s" % (s, o), config.get(s, o)) + for s in config.sections() + for o in config.options(s) + ) + appdata["flags"] = " | ".join(sorted(flags)) if flags else "0" + for key in ("App:vendor", "App:profile"): + # Set to NULL when not present or falsy such as an empty string + appdata[key] = '"%s"' % appdata[key] if appdata.get(key, None) else "NULL" + expected = ( + "App:vendor", + "App:name", + "App:remotingname", + "App:version", + "App:buildid", + "App:id", + "Gecko:minversion", + "Gecko:maxversion", + ) + missing = [var for var in expected if var not in appdata] + if missing: + print("Missing values in %s: %s" % (file, ", ".join(missing)), file=sys.stderr) + sys.exit(1) + + if "Crash Reporter:serverurl" not in appdata: + appdata["Crash Reporter:serverurl"] = "" + + if "App:sourcerepository" in appdata and "App:sourcestamp" in appdata: + appdata["App:sourceurl"] = ( + '"%(App:sourcerepository)s/rev/%(App:sourcestamp)s"' % appdata + ) + else: + appdata["App:sourceurl"] = "NULL" + + if "AppUpdate:url" not in appdata: + appdata["AppUpdate:url"] = "" + + output.write( + """#include "mozilla/XREAppData.h" + static const mozilla::StaticXREAppData sAppData = { + %(App:vendor)s, + "%(App:name)s", + "%(App:remotingname)s", + "%(App:version)s", + "%(App:buildid)s", + "%(App:id)s", + NULL, // copyright + %(flags)s, + "%(Gecko:minversion)s", + "%(Gecko:maxversion)s", + "%(Crash Reporter:serverurl)s", + %(App:profile)s, + NULL, // UAName + %(App:sourceurl)s, + "%(AppUpdate:url)s" + };""" + % appdata + ) + + +if __name__ == "__main__": + if len(sys.argv) != 1: + main(sys.stdout, sys.argv[1]) + else: + print("Usage: %s /path/to/application.ini" % sys.argv[0], file=sys.stderr) diff --git a/build/application.ini.in b/build/application.ini.in new file mode 100644 index 0000000000..6df13230a4 --- /dev/null +++ b/build/application.ini.in @@ -0,0 +1,56 @@ +#ifdef MOZ_BUILD_APP_IS_BROWSER +; This file is not used. If you modify it and want the application to use +; your modifications, move it under the browser/ subdirectory and start with +; the "-app /path/to/browser/application.ini" argument. +#else +; This file is not used. If you modify it and want the application to use +; your modifications, start with the "-app /path/to/application.ini" +; argument. +#endif +#if 0 +; 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/. +#endif +#filter substitution +#include @TOPOBJDIR@/buildid.h +#include @TOPOBJDIR@/source-repo.h +[App] +Vendor=@MOZ_APP_VENDOR@ +Name=@MOZ_APP_BASENAME@ +RemotingName=@MOZ_APP_REMOTINGNAME@ +#ifdef MOZ_APP_DISPLAYNAME +CodeName=@MOZ_APP_DISPLAYNAME@ +#endif +Version=@MOZ_APP_VERSION@ +#ifdef MOZ_APP_PROFILE +Profile=@MOZ_APP_PROFILE@ +#endif +BuildID=@MOZ_BUILDID@ +#ifdef MOZ_SOURCE_REPO +SourceRepository=@MOZ_SOURCE_REPO@ +#endif +#ifdef MOZ_SOURCE_STAMP +SourceStamp=@MOZ_SOURCE_STAMP@ +#endif +ID=@MOZ_APP_ID@ + +[Gecko] +MinVersion=@GRE_MILESTONE@ +MaxVersion=@GRE_MILESTONE@ + +[XRE] +#ifdef MOZ_PROFILE_MIGRATOR +EnableProfileMigrator=1 +#endif + +#if MOZ_CRASHREPORTER +[Crash Reporter] +Enabled=1 +ServerURL=@MOZ_CRASHREPORTER_URL@/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@MOZ_BUILDID@ +#endif + +#if MOZ_UPDATER +[AppUpdate] +URL=https://@MOZ_APPUPDATE_HOST@/update/6/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%SYSTEM_CAPABILITIES%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml +#endif diff --git a/build/autoconf/acgeneral.m4 b/build/autoconf/acgeneral.m4 new file mode 100644 index 0000000000..772622849b --- /dev/null +++ b/build/autoconf/acgeneral.m4 @@ -0,0 +1,2607 @@ +dnl Parameterized macros. +dnl Requires GNU m4. +dnl This file is part of Autoconf. +dnl Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception, the Free Software Foundation gives unlimited +dnl permission to copy, distribute and modify the configure scripts that +dnl are the output of Autoconf. You need not follow the terms of the GNU +dnl General Public License when using or distributing such scripts, even +dnl though portions of the text of Autoconf appear in them. The GNU +dnl General Public License (GPL) does govern all other use of the material +dnl that constitutes the Autoconf program. +dnl +dnl Certain portions of the Autoconf source text are designed to be copied +dnl (in certain cases, depending on the input) into the output of +dnl Autoconf. We call these the "data" portions. The rest of the Autoconf +dnl source text consists of comments plus executable code that decides which +dnl of the data portions to output in any given case. We call these +dnl comments and executable code the "non-data" portions. Autoconf never +dnl copies any of the non-data portions into its output. +dnl +dnl This special exception to the GPL applies to versions of Autoconf +dnl released by the Free Software Foundation. When you make and +dnl distribute a modified version of Autoconf, you may extend this special +dnl exception to the GPL to apply to your modified version as well, *unless* +dnl your modified version has the potential to copy into its output some +dnl of the text that was the non-data portion of the version that you started +dnl with. (In other words, unless your change moves or copies text from +dnl the non-data portions to the data portions.) If your modification has +dnl such potential, you must delete any notice of this special exception +dnl to the GPL from your modified version. +dnl +dnl Written by David MacKenzie, with help from +dnl Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor, +dnl Roland McGrath, Noah Friedman, david d zuhn, and many others. +dnl +divert(-1)dnl Throw away output until AC_INIT is called. +changequote([, ]) + +define(AC_ACVERSION, 2.13) + +dnl Some old m4's don't support m4exit. But they provide +dnl equivalent functionality by core dumping because of the +dnl long macros we define. +ifdef([__gnu__], , [errprint(Autoconf requires GNU m4. +Install it before installing Autoconf or set the +M4 environment variable to its path name. +)m4exit(2)]) + +undefine([eval]) +undefine([include]) +undefine([shift]) +undefine([format]) + + +dnl ### Defining macros + + +dnl m4 output diversions. We let m4 output them all in order at the end, +dnl except that we explicitly undivert AC_DIVERSION_SED, AC_DIVERSION_CMDS, +dnl and AC_DIVERSION_ICMDS. + +dnl AC_DIVERSION_NOTICE - 1 (= 0) AC_REQUIRE'd #! /bin/sh line +define(AC_DIVERSION_NOTICE, 1)dnl copyright notice & option help strings +define(AC_DIVERSION_INIT, 2)dnl initialization code +define(AC_DIVERSION_NORMAL_4, 3)dnl AC_REQUIRE'd code, 4 level deep +define(AC_DIVERSION_NORMAL_3, 4)dnl AC_REQUIRE'd code, 3 level deep +define(AC_DIVERSION_NORMAL_2, 5)dnl AC_REQUIRE'd code, 2 level deep +define(AC_DIVERSION_NORMAL_1, 6)dnl AC_REQUIRE'd code, 1 level deep +define(AC_DIVERSION_NORMAL, 7)dnl the tests and output code +define(AC_DIVERSION_SED, 8)dnl variable substitutions in config.status +define(AC_DIVERSION_CMDS, 9)dnl extra shell commands in config.status +define(AC_DIVERSION_ICMDS, 10)dnl extra initialization in config.status + +dnl Change the diversion stream to STREAM, while stacking old values. +dnl AC_DIVERT_PUSH(STREAM) +define(AC_DIVERT_PUSH, +[pushdef([AC_DIVERSION_CURRENT], $1)dnl +divert(AC_DIVERSION_CURRENT)dnl +]) + +dnl Change the diversion stream to its previous value, unstacking it. +dnl AC_DIVERT_POP() +define(AC_DIVERT_POP, +[popdef([AC_DIVERSION_CURRENT])dnl +divert(AC_DIVERSION_CURRENT)dnl +]) + +dnl Initialize the diversion setup. +define([AC_DIVERSION_CURRENT], AC_DIVERSION_NORMAL) +dnl This will be popped by AC_REQUIRE in AC_INIT. +pushdef([AC_DIVERSION_CURRENT], AC_DIVERSION_NOTICE) + +dnl The prologue for Autoconf macros. +dnl AC_PRO(MACRO-NAME) +define(AC_PRO, +[define([AC_PROVIDE_$1], )dnl +ifelse(AC_DIVERSION_CURRENT, AC_DIVERSION_NORMAL, +[AC_DIVERT_PUSH(builtin(eval, AC_DIVERSION_CURRENT - 1))], +[pushdef([AC_DIVERSION_CURRENT], AC_DIVERSION_CURRENT)])dnl +]) + +dnl The Epilogue for Autoconf macros. +dnl AC_EPI() +define(AC_EPI, +[AC_DIVERT_POP()dnl +ifelse(AC_DIVERSION_CURRENT, AC_DIVERSION_NORMAL, +[undivert(AC_DIVERSION_NORMAL_4)dnl +undivert(AC_DIVERSION_NORMAL_3)dnl +undivert(AC_DIVERSION_NORMAL_2)dnl +undivert(AC_DIVERSION_NORMAL_1)dnl +])dnl +]) + +dnl Define a macro which automatically provides itself. Add machinery +dnl so the macro automatically switches expansion to the diversion +dnl stack if it is not already using it. In this case, once finished, +dnl it will bring back all the code accumulated in the diversion stack. +dnl This, combined with AC_REQUIRE, achieves the topological ordering of +dnl macros. We don't use this macro to define some frequently called +dnl macros that are not involved in ordering constraints, to save m4 +dnl processing. +dnl AC_DEFUN(NAME, EXPANSION) +define([AC_DEFUN], +[define($1, [AC_PRO([$1])$2[]AC_EPI()])]) + + +dnl ### Initialization + + +dnl AC_INIT_NOTICE() +AC_DEFUN(AC_INIT_NOTICE, +[# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version] AC_ACVERSION [ +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +[#] Any additions from configure.in:]) + +dnl AC_PREFIX_DEFAULT(PREFIX) +AC_DEFUN(AC_PREFIX_DEFAULT, +[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +ac_default_prefix=$1 +AC_DIVERT_POP()]) + +dnl AC_INIT_PARSE_ARGS() +AC_DEFUN(AC_INIT_PARSE_ARGS, +[ +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +dnl Installation directory options. +dnl These are left unexpanded so users can "make install exec_prefix=/foo" +dnl and all the variables that are supposed to be based on exec_prefix +dnl by default will actually change. +dnl Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in +changequote(, )dnl + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; +changequote([, ])dnl + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_feature: invalid feature name) + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_feature: invalid feature name) + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +changequote(, )dnl +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +changequote([, ])dnl +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version AC_ACVERSION" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_package: invalid package name) + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. +changequote(, )dnl + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then +changequote([, ])dnl + AC_MSG_ERROR($ac_package: invalid package name) + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) AC_MSG_ERROR([$ac_option: invalid option; use --help to show usage]) + ;; + + *) +changequote(, )dnl + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then +changequote([, ])dnl + AC_MSG_WARN($ac_option: invalid host type) + fi + if test "x$nonopt" != xNONE; then + AC_MSG_ERROR(can only configure for one host and one target at a time) + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + AC_MSG_ERROR(missing argument to --`echo $ac_prev | sed 's/_/-/g'`) +fi +]) + +dnl Try to have only one #! line, so the script doesn't look funny +dnl for users of AC_REVISION. +dnl AC_INIT_BINSH() +AC_DEFUN(AC_INIT_BINSH, +[#! /bin/sh +]) + +dnl AC_INIT(UNIQUE-FILE-IN-SOURCE-DIR) +AC_DEFUN(AC_INIT, +[sinclude(acsite.m4)dnl +sinclude(./aclocal.m4)dnl +AC_REQUIRE([AC_INIT_BINSH])dnl +AC_INIT_NOTICE +AC_DIVERT_POP()dnl to NORMAL +AC_DIVERT_PUSH(AC_DIVERSION_INIT)dnl +AC_INIT_PARSE_ARGS +AC_INIT_PREPARE($1)dnl +AC_DIVERT_POP()dnl to NORMAL +]) + +dnl AC_INIT_PREPARE(UNIQUE-FILE-IN-SOURCE-DIR) +AC_DEFUN(AC_INIT_PREPARE, +[trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +define(AC_FD_MSG, 6)dnl +[#] AC_FD_MSG checking for... messages and results +define(AC_FD_CC, 5)dnl +[#] AC_FD_CC compiler messages saved in config.log +if test "$silent" = yes; then + exec AC_FD_MSG>/dev/null +else + exec AC_FD_MSG>&1 +fi +exec AC_FD_CC>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&AC_FD_CC + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; +changequote(<<, >>)dnl +dnl If you change this globbing pattern, test it on an old shell -- +dnl it's sensitive. Putting any kind of quote in it causes syntax errors. + *" "*|*" "*|*[\[\]\~\<<#>>\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; +changequote([, ])dnl + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=$1 + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=[$]0 +changequote(, )dnl + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + AC_MSG_ERROR(can not find sources in $ac_confdir or ..) + else + AC_MSG_ERROR(can not find sources in $srcdir) + fi +fi +dnl Double slashes in pathnames in object file debugging info +dnl mess up M-x gdb in Emacs. +changequote(, )dnl +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` +changequote([, ])dnl + +dnl Let the site file select an alternate cache file if it wants to. +AC_SITE_LOAD +AC_CACHE_LOAD +AC_LANG_C +dnl By default always use an empty string as the executable +dnl extension. Only change it if the script calls AC_EXEEXT. +ac_exeext= +dnl By default assume that objects files use an extension of .o. Only +dnl change it if the script calls AC_OBJEXT. +ac_objext=o +AC_PROG_ECHO_N +dnl Substitute for predefined variables. +AC_SUBST(SHELL)dnl +AC_SUBST(CFLAGS)dnl +AC_SUBST(CPPFLAGS)dnl +AC_SUBST(CXXFLAGS)dnl +AC_SUBST(FFLAGS)dnl +AC_SUBST(DEFS)dnl +AC_SUBST(LDFLAGS)dnl +AC_SUBST(LIBS)dnl +AC_SUBST(exec_prefix)dnl +AC_SUBST(prefix)dnl +AC_SUBST(program_transform_name)dnl +dnl Installation directory options. +AC_SUBST(bindir)dnl +AC_SUBST(sbindir)dnl +AC_SUBST(libexecdir)dnl +AC_SUBST(datadir)dnl +AC_SUBST(sysconfdir)dnl +AC_SUBST(sharedstatedir)dnl +AC_SUBST(localstatedir)dnl +AC_SUBST(libdir)dnl +AC_SUBST(includedir)dnl +AC_SUBST(oldincludedir)dnl +AC_SUBST(infodir)dnl +AC_SUBST(mandir)dnl +]) + + +dnl ### Selecting optional features + + +dnl AC_ARG_ENABLE(FEATURE, HELP-STRING, ACTION-IF-TRUE [, ACTION-IF-FALSE]) +AC_DEFUN(AC_ARG_ENABLE, +[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +ac_help="$ac_help +[$2]" +AC_DIVERT_POP()dnl +[#] Check whether --enable-[$1] or --disable-[$1] was given. +if test "[${enable_]patsubst([$1], -, _)+set}" = set; then + enableval="[$enable_]patsubst([$1], -, _)" + ifelse([$3], , :, [$3]) +ifelse([$4], , , [else + $4 +])dnl +fi +]) + +AC_DEFUN(AC_ENABLE, +[AC_OBSOLETE([$0], [; instead use AC_ARG_ENABLE])dnl +AC_ARG_ENABLE([$1], [ --enable-$1], [$2], [$3])dnl +]) + + +dnl ### Working with optional software + + +dnl AC_ARG_WITH(PACKAGE, HELP-STRING, ACTION-IF-TRUE [, ACTION-IF-FALSE]) +AC_DEFUN(AC_ARG_WITH, +[AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl +ac_help="$ac_help +[$2]" +AC_DIVERT_POP()dnl +[#] Check whether --with-[$1] or --without-[$1] was given. +if test "[${with_]patsubst([$1], -, _)+set}" = set; then + withval="[$with_]patsubst([$1], -, _)" + ifelse([$3], , :, [$3]) +ifelse([$4], , , [else + $4 +])dnl +fi +]) + +AC_DEFUN(AC_WITH, +[AC_OBSOLETE([$0], [; instead use AC_ARG_WITH])dnl +AC_ARG_WITH([$1], [ --with-$1], [$2], [$3])dnl +]) + + +dnl ### Transforming program names. + + +dnl AC_ARG_PROGRAM() +AC_DEFUN(AC_ARG_PROGRAM, +[if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," +]) + + +dnl ### Version numbers + + +dnl AC_REVISION(REVISION-INFO) +AC_DEFUN(AC_REVISION, +[AC_REQUIRE([AC_INIT_BINSH])dnl +[# From configure.in] translit([$1], $")]) + +dnl Subroutines of AC_PREREQ. + +dnl Change the dots in NUMBER into commas. +dnl AC_PREREQ_SPLIT(NUMBER) +define(AC_PREREQ_SPLIT, +[translit($1, ., [, ])]) + +dnl Default the ternary version number to 0 (e.g., 1, 7 -> 1, 7, 0). +dnl AC_PREREQ_CANON(MAJOR, MINOR [,TERNARY]) +define(AC_PREREQ_CANON, +[$1, $2, ifelse([$3], , 0, [$3])]) + +dnl Complain and exit if version number 1 is less than version number 2. +dnl PRINTABLE2 is the printable version of version number 2. +dnl AC_PREREQ_COMPARE(MAJOR1, MINOR1, TERNARY1, MAJOR2, MINOR2, TERNARY2, +dnl PRINTABLE2) +define(AC_PREREQ_COMPARE, +[ifelse(builtin([eval], +[$3 + $2 * 1000 + $1 * 1000000 < $6 + $5 * 1000 + $4 * 1000000]), 1, +[errprint(dnl +FATAL ERROR: Autoconf version $7 or higher is required for this script +)m4exit(3)])]) + +dnl Complain and exit if the Autoconf version is less than VERSION. +dnl AC_PREREQ(VERSION) +define(AC_PREREQ, +[AC_PREREQ_COMPARE(AC_PREREQ_CANON(AC_PREREQ_SPLIT(AC_ACVERSION)), +AC_PREREQ_CANON(AC_PREREQ_SPLIT([$1])), [$1])]) + + +dnl ### Getting the canonical system type + + +dnl Find install-sh, config.sub, config.guess, and Cygnus configure +dnl in directory DIR. These are auxiliary files used in configuration. +dnl DIR can be either absolute or relative to $srcdir. +dnl AC_CONFIG_AUX_DIR(DIR) +AC_DEFUN(AC_CONFIG_AUX_DIR, +[AC_CONFIG_AUX_DIRS($1 $srcdir/$1)]) + +dnl The default is `$srcdir' or `$srcdir/..' or `$srcdir/../..'. +dnl There's no need to call this macro explicitly; just AC_REQUIRE it. +AC_DEFUN(AC_CONFIG_AUX_DIR_DEFAULT, +[AC_CONFIG_AUX_DIRS($srcdir $srcdir/.. $srcdir/../..)]) + +dnl Internal subroutine. +dnl Search for the configuration auxiliary files in directory list $1. +dnl We look only for install-sh, so users of AC_PROG_INSTALL +dnl do not automatically need to distribute the other auxiliary files. +dnl AC_CONFIG_AUX_DIRS(DIR ...) +AC_DEFUN(AC_CONFIG_AUX_DIRS, +[ac_aux_dir= +for ac_dir in $1; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + AC_MSG_ERROR([can not find install-sh or install.sh in $1]) +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. +AC_PROVIDE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +]) + +dnl Canonicalize the host, target, and build system types. +AC_DEFUN(AC_CANONICAL_SYSTEM, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [AC_ARG_PROGRAM]) +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) AC_MSG_ERROR(can only configure for one host and one target at a time) ;; +esac + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AC_CANONICAL_BUILD +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- +]) + +dnl Subroutines of AC_CANONICAL_SYSTEM. + +AC_DEFUN(AC_CANONICAL_HOST, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else AC_MSG_ERROR(can not run $ac_config_sub) +fi + +AC_MSG_CHECKING(host system type) + +dnl Set host_alias. +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else AC_MSG_ERROR(can not guess host type; you must specify one) + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +dnl Set the other host vars. +changequote(<<, >>)dnl +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +changequote([, ])dnl +AC_MSG_RESULT($host) +AC_SUBST(host)dnl +AC_SUBST(host_alias)dnl +AC_SUBST(host_cpu)dnl +AC_SUBST(host_vendor)dnl +AC_SUBST(host_os)dnl +]) + +dnl Internal use only. +AC_DEFUN(AC_CANONICAL_TARGET, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_MSG_CHECKING(target system type) + +dnl Set target_alias. +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +dnl Set the other target vars. +changequote(<<, >>)dnl +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +changequote([, ])dnl +AC_MSG_RESULT($target) +AC_SUBST(target)dnl +AC_SUBST(target_alias)dnl +AC_SUBST(target_cpu)dnl +AC_SUBST(target_vendor)dnl +AC_SUBST(target_os)dnl +]) + +dnl Internal use only. +AC_DEFUN(AC_CANONICAL_BUILD, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_MSG_CHECKING(build system type) + +dnl Set build_alias. +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +dnl Set the other build vars. +changequote(<<, >>)dnl +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +changequote([, ])dnl +AC_MSG_RESULT($build) +AC_SUBST(build)dnl +AC_SUBST(build_alias)dnl +AC_SUBST(build_cpu)dnl +AC_SUBST(build_vendor)dnl +AC_SUBST(build_os)dnl +]) + + +dnl AC_VALIDATE_CACHED_SYSTEM_TUPLE[(cmd)] +dnl if the cache file is inconsistent with the current host, +dnl target and build system types, execute CMD or print a default +dnl error message. +AC_DEFUN(AC_VALIDATE_CACHED_SYSTEM_TUPLE, [ + AC_REQUIRE([AC_CANONICAL_SYSTEM]) + AC_MSG_CHECKING([cached system tuple]) + if { test x"${ac_cv_host_system_type+set}" = x"set" && + test x"$ac_cv_host_system_type" != x"$host"; } || + { test x"${ac_cv_build_system_type+set}" = x"set" && + test x"$ac_cv_build_system_type" != x"$build"; } || + { test x"${ac_cv_target_system_type+set}" = x"set" && + test x"$ac_cv_target_system_type" != x"$target"; }; then + AC_MSG_RESULT([different]) + ifelse($#, 1, [$1], + [AC_MSG_ERROR([remove config.cache and re-run configure])]) + else + AC_MSG_RESULT(ok) + fi + ac_cv_host_system_type="$host" + ac_cv_build_system_type="$build" + ac_cv_target_system_type="$target" +]) + + +dnl ### Caching test results + + +dnl Look for site or system specific initialization scripts. +dnl AC_SITE_LOAD() +define(AC_SITE_LOAD, +[# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done +]) + +dnl AC_CACHE_LOAD() +define(AC_CACHE_LOAD, +[if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi +]) + +dnl AC_CACHE_SAVE() +define(AC_CACHE_SAVE, +[cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +dnl Allow a site initialization script to override cache values. +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +changequote(, )dnl +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +changequote([, ])dnl +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache +]) + +dnl The name of shell var CACHE-ID must contain `_cv_' in order to get saved. +dnl AC_CACHE_VAL(CACHE-ID, COMMANDS-TO-SET-IT) +define(AC_CACHE_VAL, +[dnl We used to use the below line, but it fails if the 1st arg is a +dnl shell variable, so we need the eval. +dnl if test "${$1+set}" = set; then +dnl the '' avoids an AIX 4.1 sh bug ("invalid expansion"). +if eval "test \"`echo '$''{'$1'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&AC_FD_MSG +else + $2 +fi +]) + +dnl AC_CACHE_CHECK(MESSAGE, CACHE-ID, COMMANDS) +define(AC_CACHE_CHECK, +[AC_MSG_CHECKING([$1]) +AC_CACHE_VAL([$2], [$3]) +AC_MSG_RESULT([$]$2)]) + + +dnl ### Defining symbols + + +dnl Set VARIABLE to VALUE, verbatim, or 1. +dnl AC_DEFINE(VARIABLE [, VALUE]) +define(AC_DEFINE, +[cat >> confdefs.h <<\EOF +[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1) +EOF +]) + +dnl Similar, but perform shell substitutions $ ` \ once on VALUE. +define(AC_DEFINE_UNQUOTED, +[cat >> confdefs.h <<EOF +[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1) +EOF +]) + + +dnl ### Setting output variables + + +dnl This macro protects VARIABLE from being diverted twice +dnl if this macro is called twice for it. +dnl AC_SUBST(VARIABLE) +define(AC_SUBST, +[ifdef([AC_SUBST_$1], , +[define([AC_SUBST_$1], )dnl +AC_DIVERT_PUSH(AC_DIVERSION_SED)dnl +s%@$1@%[$]$1%g +AC_DIVERT_POP()dnl +])]) + +dnl AC_SUBST_FILE(VARIABLE) +define(AC_SUBST_FILE, +[ifdef([AC_SUBST_$1], , +[define([AC_SUBST_$1], )dnl +AC_DIVERT_PUSH(AC_DIVERSION_SED)dnl +/@$1@/r [$]$1 +s%@$1@%%g +AC_DIVERT_POP()dnl +])]) + + +dnl ### Printing messages + + +dnl AC_MSG_CHECKING(FEATURE-DESCRIPTION) +define(AC_MSG_CHECKING, +[echo $ac_n "checking $1""... $ac_c" 1>&AC_FD_MSG +echo "configure:__oline__: checking $1" >&AC_FD_CC]) + +dnl AC_CHECKING(FEATURE-DESCRIPTION) +define(AC_CHECKING, +[echo "checking $1" 1>&AC_FD_MSG +echo "configure:__oline__: checking $1" >&AC_FD_CC]) + +dnl AC_MSG_RESULT(RESULT-DESCRIPTION) +define(AC_MSG_RESULT, +[echo "$ac_t""$1" 1>&AC_FD_MSG]) + +dnl AC_VERBOSE(RESULT-DESCRIPTION) +define(AC_VERBOSE, +[AC_OBSOLETE([$0], [; instead use AC_MSG_RESULT])dnl +echo " $1" 1>&AC_FD_MSG]) + +dnl AC_MSG_WARN(PROBLEM-DESCRIPTION) +define(AC_MSG_WARN, +[echo "configure: warning: $1" 1>&2]) + +dnl AC_MSG_ERROR(ERROR-DESCRIPTION) +define(AC_MSG_ERROR, +[{ echo "configure: error: $1" 1>&2; exit 1; }]) + + +dnl ### Selecting which language to use for testing + + +dnl AC_LANG_C() +AC_DEFUN(AC_LANG_C, +[define([AC_LANG], [C])dnl +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +cross_compiling=$ac_cv_prog_cc_cross +]) + +dnl AC_LANG_CPLUSPLUS() +AC_DEFUN(AC_LANG_CPLUSPLUS, +[define([AC_LANG], [CPLUSPLUS])dnl +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&AC_FD_CC' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +cross_compiling=$ac_cv_prog_cxx_cross +]) + +dnl AC_LANG_FORTRAN77() +AC_DEFUN(AC_LANG_FORTRAN77, +[define([AC_LANG], [FORTRAN77])dnl +ac_ext=f +ac_compile='${F77-f77} -c $FFLAGS conftest.$ac_ext 1>&AC_FD_CC' +ac_link='${F77-f77} -o conftest${ac_exeext} $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +cross_compiling=$ac_cv_prog_f77_cross +]) + +dnl Push the current language on a stack. +dnl AC_LANG_SAVE() +define(AC_LANG_SAVE, +[pushdef([AC_LANG_STACK], AC_LANG)]) + +dnl Restore the current language from the stack. +dnl AC_LANG_RESTORE() +pushdef([AC_LANG_RESTORE], +[ifelse(AC_LANG_STACK, [C], [AC_LANG_C],dnl +AC_LANG_STACK, [CPLUSPLUS], [AC_LANG_CPLUSPLUS],dnl +AC_LANG_STACK, [FORTRAN77], [AC_LANG_FORTRAN77])[]popdef([AC_LANG_STACK])]) + + +dnl ### Compiler-running mechanics + + +dnl The purpose of this macro is to "configure:123: command line" +dnl written into config.log for every test run. +dnl AC_TRY_EVAL(VARIABLE) +AC_DEFUN(AC_TRY_EVAL, +[{ (eval echo configure:__oline__: \"[$]$1\") 1>&AC_FD_CC; dnl +(eval [$]$1) 2>&AC_FD_CC; }]) + +dnl AC_TRY_COMMAND(COMMAND) +AC_DEFUN(AC_TRY_COMMAND, +[{ ac_try='$1'; AC_TRY_EVAL(ac_try); }]) + + +dnl ### Dependencies between macros + + +dnl AC_BEFORE(THIS-MACRO-NAME, CALLED-MACRO-NAME) +define(AC_BEFORE, +[ifdef([AC_PROVIDE_$2], [errprint(__file__:__line__: [$2 was called before $1 +])])]) + +dnl AC_REQUIRE(MACRO-NAME) +define(AC_REQUIRE, +[ifdef([AC_PROVIDE_$1], , +[AC_DIVERT_PUSH(builtin(eval, AC_DIVERSION_CURRENT - 1))dnl +indir([$1]) +AC_DIVERT_POP()dnl +])]) + +dnl AC_PROVIDE(MACRO-NAME) +define(AC_PROVIDE, +[define([AC_PROVIDE_$1], )]) + +dnl AC_OBSOLETE(THIS-MACRO-NAME [, SUGGESTION]) +define(AC_OBSOLETE, +[errprint(__file__:__line__: warning: [$1] is obsolete[$2] +)]) + + +dnl ### Checking for programs + + +dnl AC_CHECK_PROG(VARIABLE, PROG-TO-CHECK-FOR, VALUE-IF-FOUND +dnl [, [VALUE-IF-NOT-FOUND] [, [PATH] [, [REJECT]]]]) +AC_DEFUN(AC_CHECK_PROG, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_prog_$1, +[if test -n "[$]$1"; then + ac_cv_prog_$1="[$]$1" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +ifelse([$6], , , [ ac_prog_rejected=no +])dnl +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$5], , $PATH, [$5])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then +ifelse([$6], , , dnl +[ if test "[$ac_dir/$ac_word]" = "$6"; then + ac_prog_rejected=yes + continue + fi +])dnl + ac_cv_prog_$1="$3" + break + fi + done + IFS="$ac_save_ifs" +ifelse([$6], , , [if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy [$]ac_cv_prog_$1 + shift + if test [$]# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set $1 to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "[$]@" + shift + ac_cv_prog_$1="[$]@" +ifelse([$2], [$4], dnl +[ else + # Default is a loser. + AC_MSG_ERROR([$1=$6 unacceptable, but no other $4 found in dnl +ifelse([$5], , [\$]PATH, [$5])]) +])dnl + fi +fi +])dnl +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_CHECK_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_prog_$1" && ac_cv_prog_$1="$4" +])dnl +fi])dnl +$1="$ac_cv_prog_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +dnl AC_PATH_PROG(VARIABLE, PROG-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AC_PATH_PROG, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$4], , $PATH, [$4])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" +dnl If no 3rd arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$3], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$3" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +dnl AC_CHECK_PROGS(VARIABLE, PROGS-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND +dnl [, PATH]]) +AC_DEFUN(AC_CHECK_PROGS, +[for ac_prog in $2 +do +AC_CHECK_PROG($1, [$]ac_prog, [$]ac_prog, , $4) +test -n "[$]$1" && break +done +ifelse([$3], , , [test -n "[$]$1" || $1="$3" +])]) + +dnl AC_PATH_PROGS(VARIABLE, PROGS-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND +dnl [, PATH]]) +AC_DEFUN(AC_PATH_PROGS, +[for ac_prog in $2 +do +AC_PATH_PROG($1, [$]ac_prog, , $4) +test -n "[$]$1" && break +done +ifelse([$3], , , [test -n "[$]$1" || $1="$3" +])]) + +dnl Internal subroutine. +AC_DEFUN(AC_CHECK_TOOL_PREFIX, +[AC_REQUIRE([AC_CANONICAL_HOST])AC_REQUIRE([AC_CANONICAL_BUILD])dnl +if test $host != $build; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi +]) + +dnl AC_CHECK_TOOL(VARIABLE, PROG-TO-CHECK-FOR[, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AC_CHECK_TOOL, +[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl +AC_CHECK_PROG($1, ${ac_tool_prefix}$2, ${ac_tool_prefix}$2, + ifelse([$3], , [$2], ), $4) +ifelse([$3], , , [ +if test -z "$ac_cv_prog_$1"; then +if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG($1, $2, $2, $3) +else + $1="$3" +fi +fi]) +]) + +dnl Guess the value for the `prefix' variable by looking for +dnl the argument program along PATH and taking its parent. +dnl Example: if the argument is `gcc' and we find /usr/local/gnu/bin/gcc, +dnl set `prefix' to /usr/local/gnu. +dnl This comes too late to find a site file based on the prefix, +dnl and it might use a cached value for the path. +dnl No big loss, I think, since most configures don't use this macro anyway. +dnl AC_PREFIX_PROGRAM(PROGRAM) +AC_DEFUN(AC_PREFIX_PROGRAM, +[if test "x$prefix" = xNONE; then +changequote(<<, >>)dnl +define(<<AC_VAR_NAME>>, translit($1, [a-z], [A-Z]))dnl +changequote([, ])dnl +dnl We reimplement AC_MSG_CHECKING (mostly) to avoid the ... in the middle. +echo $ac_n "checking for prefix by $ac_c" 1>&AC_FD_MSG +AC_PATH_PROG(AC_VAR_NAME, $1) +changequote(<<, >>)dnl + if test -n "$ac_cv_path_<<>>AC_VAR_NAME"; then + prefix=`echo $ac_cv_path_<<>>AC_VAR_NAME|sed 's%/[^/][^/]*//*[^/][^/]*$%%'` +changequote([, ])dnl + fi +fi +undefine([AC_VAR_NAME])dnl +]) + +dnl Try to compile, link and execute TEST-PROGRAM. Set WORKING-VAR to +dnl `yes' if the current compiler works, otherwise set it ti `no'. Set +dnl CROSS-VAR to `yes' if the compiler and linker produce non-native +dnl executables, otherwise set it to `no'. Before calling +dnl `AC_TRY_COMPILER()', call `AC_LANG_*' to set-up for the right +dnl language. +dnl +dnl AC_TRY_COMPILER(TEST-PROGRAM, WORKING-VAR, CROSS-VAR) +AC_DEFUN(AC_TRY_COMPILER, +[cat > conftest.$ac_ext << EOF +ifelse(AC_LANG, [FORTRAN77], , +[ +[#]line __oline__ "configure" +#include "confdefs.h" +]) +[$1] +EOF +if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + [$2]=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + [$3]=no + else + [$3]=yes + fi +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + [$2]=no +fi +rm -fr conftest*]) + + +dnl ### Checking for libraries + + +dnl AC_TRY_LINK_FUNC(func, action-if-found, action-if-not-found) +dnl Try to link a program that calls FUNC, handling GCC builtins. If +dnl the link succeeds, execute ACTION-IF-FOUND; otherwise, execute +dnl ACTION-IF-NOT-FOUND. + +AC_DEFUN(AC_TRY_LINK_FUNC, +AC_TRY_LINK(dnl +ifelse([$1], [main], , dnl Avoid conflicting decl of main. +[/* Override any gcc2 internal prototype to avoid an error. */ +]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus +extern "C" +#endif +])dnl +[/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $1(); +]), +[$1()], +[$2], +[$3])) + + +dnl AC_SEARCH_LIBS(FUNCTION, SEARCH-LIBS [, ACTION-IF-FOUND +dnl [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]]) +dnl Search for a library defining FUNC, if it's not already available. + +AC_DEFUN(AC_SEARCH_LIBS, +[AC_PREREQ([2.13]) +AC_CACHE_CHECK([for library containing $1], [ac_cv_search_$1], +[ac_func_search_save_LIBS="$LIBS" +ac_cv_search_$1="no" +AC_TRY_LINK_FUNC([$1], [ac_cv_search_$1="none required"]) +test "$ac_cv_search_$1" = "no" && for i in $2; do +LIBS="-l$i $5 $ac_func_search_save_LIBS" +AC_TRY_LINK_FUNC([$1], +[ac_cv_search_$1="-l$i" +break]) +done +LIBS="$ac_func_search_save_LIBS"]) +if test "$ac_cv_search_$1" != "no"; then + test "$ac_cv_search_$1" = "none required" || LIBS="$ac_cv_search_$1 $LIBS" + $3 +else : + $4 +fi]) + + + +dnl AC_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND +dnl [, OTHER-LIBRARIES]]]) +AC_DEFUN(AC_CHECK_LIB, +[AC_MSG_CHECKING([for $2 in -l$1]) +dnl Use a cache variable name containing both the library and function name, +dnl because the test really is for library $1 defining function $2, not +dnl just for library $1. Separate tests with the same $1 and different $2s +dnl may have different results. +ac_lib_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` +AC_CACHE_VAL(ac_cv_lib_$ac_lib_var, +[ac_save_LIBS="$LIBS" +LIBS="-l$1 $5 $LIBS" +AC_TRY_LINK(dnl +ifelse(AC_LANG, [FORTRAN77], , +ifelse([$2], [main], , dnl Avoid conflicting decl of main. +[/* Override any gcc2 internal prototype to avoid an error. */ +]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus +extern "C" +#endif +])dnl +[/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $2(); +])), + [$2()], + eval "ac_cv_lib_$ac_lib_var=yes", + eval "ac_cv_lib_$ac_lib_var=no") +LIBS="$ac_save_LIBS" +])dnl +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$3], , +[changequote(, )dnl + ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_lib) + LIBS="-l$1 $LIBS" +], [$3]) +else + AC_MSG_RESULT(no) +ifelse([$4], , , [$4 +])dnl +fi +]) + +dnl AC_HAVE_LIBRARY(LIBRARY, [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND +dnl [, OTHER-LIBRARIES]]]) +AC_DEFUN(AC_HAVE_LIBRARY, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_LIB])dnl +changequote(<<, >>)dnl +define(<<AC_LIB_NAME>>, dnl +patsubst(patsubst($1, <<lib\([^\.]*\)\.a>>, <<\1>>), <<-l>>, <<>>))dnl +define(<<AC_CV_NAME>>, ac_cv_lib_<<>>AC_LIB_NAME)dnl +changequote([, ])dnl +AC_MSG_CHECKING([for -l[]AC_LIB_NAME]) +AC_CACHE_VAL(AC_CV_NAME, +[ac_save_LIBS="$LIBS" +LIBS="-l[]AC_LIB_NAME[] $4 $LIBS" +AC_TRY_LINK( , [main()], AC_CV_NAME=yes, AC_CV_NAME=no) +LIBS="$ac_save_LIBS" +])dnl +AC_MSG_RESULT($AC_CV_NAME) +if test "$AC_CV_NAME" = yes; then + ifelse([$2], , +[AC_DEFINE([HAVE_LIB]translit(AC_LIB_NAME, [a-z], [A-Z])) + LIBS="-l[]AC_LIB_NAME[] $LIBS" +], [$2]) +ifelse([$3], , , [else + $3 +])dnl +fi +undefine([AC_LIB_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + + +dnl ### Examining declarations + + +dnl AC_TRY_CPP(INCLUDES, [ACTION-IF-TRUE [, ACTION-IF-FALSE]]) +AC_DEFUN(AC_TRY_CPP, +[AC_REQUIRE_CPP()dnl +cat > conftest.$ac_ext <<EOF +[#]line __oline__ "configure" +#include "confdefs.h" +[$1] +EOF +dnl Capture the stderr of cpp. eval is necessary to expand ac_cpp. +dnl We used to copy stderr to stdout and capture it in a variable, but +dnl that breaks under sh -x, which writes compile commands starting +dnl with ` +' to stderr in eval and subshells. +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +AC_TRY_EVAL(ac_try) +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + ifelse([$2], , :, [rm -rf conftest* + $2]) +else + echo "$ac_err" >&AC_FD_CC + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$3], , , [ rm -rf conftest* + $3 +])dnl +fi +rm -f conftest*]) + +dnl AC_EGREP_HEADER(PATTERN, HEADER-FILE, ACTION-IF-FOUND [, +dnl ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_EGREP_HEADER, +[AC_EGREP_CPP([$1], [#include <$2>], [$3], [$4])]) + +dnl Because this macro is used by AC_PROG_GCC_TRADITIONAL, which must +dnl come early, it is not included in AC_BEFORE checks. +dnl AC_EGREP_CPP(PATTERN, PROGRAM, [ACTION-IF-FOUND [, +dnl ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_EGREP_CPP, +[AC_REQUIRE_CPP()dnl +cat > conftest.$ac_ext <<EOF +[#]line __oline__ "configure" +#include "confdefs.h" +[$2] +EOF +dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +if (eval "$ac_cpp conftest.$ac_ext") 2>&AC_FD_CC | +dnl Prevent m4 from eating character classes: +changequote(, )dnl + grep -E "$1" >/dev/null 2>&1; then +changequote([, ])dnl + ifelse([$3], , :, [rm -rf conftest* + $3]) +ifelse([$4], , , [else + rm -rf conftest* + $4 +])dnl +fi +rm -f conftest* +]) + + +dnl ### Examining syntax + + +dnl AC_TRY_COMPILE(INCLUDES, FUNCTION-BODY, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_TRY_COMPILE, +[cat > conftest.$ac_ext <<EOF +ifelse(AC_LANG, [FORTRAN77], +[ program main +[$2] + end], +[dnl This sometimes fails to find confdefs.h, for some reason. +dnl [#]line __oline__ "[$]0" +[#]line __oline__ "configure" +#include "confdefs.h" +[$1] +int main() { +[$2] +; return 0; } +])EOF +if AC_TRY_EVAL(ac_compile); then + ifelse([$3], , :, [rm -rf conftest* + $3]) +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$4], , , [ rm -rf conftest* + $4 +])dnl +fi +rm -f conftest*]) + + +dnl ### Examining libraries + + +dnl AC_COMPILE_CHECK(ECHO-TEXT, INCLUDES, FUNCTION-BODY, +dnl ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_COMPILE_CHECK, +[AC_OBSOLETE([$0], [; instead use AC_TRY_COMPILE or AC_TRY_LINK, and AC_MSG_CHECKING and AC_MSG_RESULT])dnl +ifelse([$1], , , [AC_CHECKING([for $1]) +])dnl +AC_TRY_LINK([$2], [$3], [$4], [$5]) +]) + +dnl AC_TRY_LINK(INCLUDES, FUNCTION-BODY, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_TRY_LINK, +[cat > conftest.$ac_ext <<EOF +ifelse(AC_LANG, [FORTRAN77], +[ + program main + call [$2] + end +], +[dnl This sometimes fails to find confdefs.h, for some reason. +dnl [#]line __oline__ "[$]0" +[#]line __oline__ "configure" +#include "confdefs.h" +[$1] +int main() { +[$2] +; return 0; } +])EOF +if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + ifelse([$3], , :, [rm -rf conftest* + $3]) +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$4], , , [ rm -rf conftest* + $4 +])dnl +fi +rm -f conftest*]) + + +dnl ### Checking for run-time features + + +dnl AC_TRY_RUN(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE +dnl [, ACTION-IF-CROSS-COMPILING]]]) +AC_DEFUN(AC_TRY_RUN, +[if test "$cross_compiling" = yes; then + ifelse([$4], , + [errprint(__file__:__line__: warning: [AC_TRY_RUN] called without default to allow cross compiling +)dnl + AC_MSG_ERROR(can not run test program while cross compiling)], + [$4]) +else + AC_TRY_RUN_NATIVE([$1], [$2], [$3]) +fi +]) + +dnl Like AC_TRY_RUN but assumes a native-environment (non-cross) compiler. +dnl AC_TRY_RUN_NATIVE(PROGRAM, [ACTION-IF-TRUE [, ACTION-IF-FALSE]]) +AC_DEFUN(AC_TRY_RUN_NATIVE, +[cat > conftest.$ac_ext <<EOF +[#]line __oline__ "configure" +#include "confdefs.h" +ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus +extern "C" void exit(int); +#endif +])dnl +[$1] +EOF +if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then +dnl Don't remove the temporary files here, so they can be examined. + ifelse([$2], , :, [$2]) +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$3], , , [ rm -fr conftest* + $3 +])dnl +fi +rm -fr conftest*]) + + +dnl ### Checking for header files + + +dnl AC_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_HEADER, +[dnl Do the transliteration at runtime so arg 1 can be a shell variable. +ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_header_$ac_safe, +[AC_TRY_CPP([#include <$1>], eval "ac_cv_header_$ac_safe=yes", + eval "ac_cv_header_$ac_safe=no")])dnl +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3 +])dnl +fi +]) + +dnl AC_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_HEADERS, +[for ac_hdr in $1 +do +AC_CHECK_HEADER($ac_hdr, +[changequote(, )dnl + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3)dnl +done +]) + + +dnl ### Checking for the existence of files + +dnl AC_CHECK_FILE(FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FILE, +[AC_REQUIRE([AC_PROG_CC]) +dnl Do the transliteration at runtime so arg 1 can be a shell variable. +ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_file_$ac_safe, +[if test "$cross_compiling" = yes; then + errprint(__file__:__line__: warning: Cannot check for file existence when cross compiling +)dnl + AC_MSG_ERROR(Cannot check for file existence when cross compiling) +else + if test -r $1; then + eval "ac_cv_file_$ac_safe=yes" + else + eval "ac_cv_file_$ac_safe=no" + fi +fi])dnl +if eval "test \"`echo '$ac_cv_file_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3]) +fi +]) + +dnl AC_CHECK_FILES(FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FILES, +[for ac_file in $1 +do +AC_CHECK_FILE($ac_file, +[changequote(, )dnl + ac_tr_file=HAVE_`echo $ac_file | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_file) $2], $3)dnl +done +]) + + +dnl ### Checking for library functions + + +dnl AC_CHECK_FUNC(FUNCTION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FUNC, +[AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_func_$1, +[AC_TRY_LINK( +dnl Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h> +dnl which includes <sys/select.h> which contains a prototype for +dnl select. Similarly for bzero. +[/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $1(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus +extern "C" +#endif +])dnl +[/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $1(); +], [ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$1) || defined (__stub___$1) +choke me +#else +$1(); +#endif +], eval "ac_cv_func_$1=yes", eval "ac_cv_func_$1=no")]) +if eval "test \"`echo '$ac_cv_func_'$1`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) +ifelse([$3], , , [$3 +])dnl +fi +]) + +dnl AC_CHECK_FUNCS(FUNCTION... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_FUNCS, +[for ac_func in $1 +do +AC_CHECK_FUNC($ac_func, +[changequote(, )dnl + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_func) $2], $3)dnl +done +]) + +dnl AC_REPLACE_FUNCS(FUNCTION...) +AC_DEFUN(AC_REPLACE_FUNCS, +[AC_CHECK_FUNCS([$1], , [LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"]) +AC_SUBST(LIBOBJS)dnl +]) + + +dnl ### Checking compiler characteristics + + +dnl AC_CHECK_SIZEOF(TYPE [, CROSS-SIZE]) +AC_DEFUN(AC_CHECK_SIZEOF, +[changequote(<<, >>)dnl +dnl The name to #define. +define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[AC_TRY_RUN([#include <stdio.h> +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof($1)); + exit(0); +}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + + +dnl ### Checking for typedefs + + +dnl AC_CHECK_TYPE(TYPE, DEFAULT) +AC_DEFUN(AC_CHECK_TYPE, +[AC_REQUIRE([AC_HEADER_STDC])dnl +AC_MSG_CHECKING(for $1) +AC_CACHE_VAL(ac_cv_type_$1, +[AC_EGREP_CPP(dnl +changequote(<<,>>)dnl +<<(^|[^a-zA-Z_0-9])$1[^a-zA-Z_0-9]>>dnl +changequote([,]), [#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif], ac_cv_type_$1=yes, ac_cv_type_$1=no)])dnl +AC_MSG_RESULT($ac_cv_type_$1) +if test $ac_cv_type_$1 = no; then + AC_DEFINE($1, $2) +fi +]) + + +dnl ### Creating output files + + +dnl AC_CONFIG_HEADER(HEADER-TO-CREATE ...) +AC_DEFUN(AC_CONFIG_HEADER, +[define(AC_LIST_HEADER, $1)]) + +dnl Link each of the existing files SOURCE... to the corresponding +dnl link name in DEST... +dnl AC_LINK_FILES(SOURCE..., DEST...) +AC_DEFUN(AC_LINK_FILES, +[dnl +define([AC_LIST_FILES], ifdef([AC_LIST_FILES], [AC_LIST_FILES ],)[$1])dnl +define([AC_LIST_LINKS], ifdef([AC_LIST_LINKS], [AC_LIST_LINKS ],)[$2])]) + +dnl Add additional commands for AC_OUTPUT to put into config.status. +dnl Use diversions instead of macros so we can be robust in the +dnl presence of commas in $1 and/or $2. +dnl AC_OUTPUT_COMMANDS(EXTRA-CMDS, INIT-CMDS) +AC_DEFUN(AC_OUTPUT_COMMANDS, +[AC_DIVERT_PUSH(AC_DIVERSION_CMDS)dnl +[$1] +AC_DIVERT_POP()dnl +AC_DIVERT_PUSH(AC_DIVERSION_ICMDS)dnl +[$2] +AC_DIVERT_POP()]) + +dnl AC_CONFIG_SUBDIRS(DIR ...) +AC_DEFUN(AC_CONFIG_SUBDIRS, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +define([AC_LIST_SUBDIRS], ifdef([AC_LIST_SUBDIRS], [AC_LIST_SUBDIRS ],)[$1])dnl +subdirs="AC_LIST_SUBDIRS" +AC_SUBST(subdirs)dnl +]) + +dnl The big finish. +dnl Produce config.status, config.h, and links; and configure subdirs. +dnl AC_OUTPUT([FILE...] [, EXTRA-CMDS] [, INIT-CMDS]) +define(AC_OUTPUT, +[trap '' 1 2 15 +AC_CACHE_SAVE +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then +changequote(, )dnl + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +changequote([, ])dnl +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +ifdef([AC_LIST_HEADER], [DEFS=-DHAVE_CONFIG_H], [AC_OUTPUT_MAKE_DEFS()]) + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +dnl hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +dnl so uname gets run too. +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +[#] [$]0 [$]ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +changequote(, )dnl +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +changequote([, ])dnl +for ac_option +do + case "[\$]ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create --no-recursion" + exec [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version AC_ACVERSION" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "[\$]ac_cs_usage"; exit 0 ;; + *) echo "[\$]ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ifdef([AC_PROVIDE_AC_PROG_INSTALL], [ac_given_INSTALL="$INSTALL" +])dnl + +changequote(<<, >>)dnl +ifdef(<<AC_LIST_HEADER>>, +<<trap 'rm -fr `echo "$1 AC_LIST_HEADER" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15>>, +<<trap 'rm -fr `echo "$1" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15>>) +changequote([, ])dnl +EOF +cat >> $CONFIG_STATUS <<EOF + +AC_OUTPUT_FILES($1) +ifdef([AC_LIST_HEADER], [AC_OUTPUT_HEADER(AC_LIST_HEADER)])dnl +ifdef([AC_LIST_LINKS], [AC_OUTPUT_LINKS(AC_LIST_FILES, AC_LIST_LINKS)])dnl +EOF +cat >> $CONFIG_STATUS <<EOF +undivert(AC_DIVERSION_ICMDS)dnl +$3 +EOF +cat >> $CONFIG_STATUS <<\EOF +undivert(AC_DIVERSION_CMDS)dnl +$2 +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 +dnl config.status should not do recursion. +ifdef([AC_LIST_SUBDIRS], [AC_OUTPUT_SUBDIRS(AC_LIST_SUBDIRS)])dnl +])dnl + +dnl Set the DEFS variable to the -D options determined earlier. +dnl This is a subroutine of AC_OUTPUT. +dnl It is called inside configure, outside of config.status. +dnl AC_OUTPUT_MAKE_DEFS() +define(AC_OUTPUT_MAKE_DEFS, +[# Transform confdefs.h into DEFS. +dnl Using a here document instead of a string reduces the quoting nightmare. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +changequote(<<, >>)dnl +s%<<#define>> \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~<<#>>$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +changequote([, ])dnl +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs +]) + +dnl Do the variable substitutions to create the Makefiles or whatever. +dnl This is a subroutine of AC_OUTPUT. It is called inside an unquoted +dnl here document whose contents are going into config.status, but +dnl upon returning, the here document is being quoted. +dnl AC_OUTPUT_FILES(FILE...) +define(AC_OUTPUT_FILES, +[# Protect against being on the right side of a sed subst in config.status. +changequote(, )dnl +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +changequote([, ])dnl +dnl These here document variables are unquoted when configure runs +dnl but quoted when config.status runs, so variables are expanded once. +$ac_vpsub +dnl Shell code in configure.in might set extrasub. +$extrasub +dnl Insert the sed substitutions of variables. +undivert(AC_DIVERSION_SED) +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"$1"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then +changequote(, )dnl + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. +changequote(, )dnl + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` +changequote([, ])dnl + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + +ifdef([AC_PROVIDE_AC_PROG_INSTALL], +[ case "$ac_given_INSTALL" in +changequote(, )dnl + [/$]*) INSTALL="$ac_given_INSTALL" ;; +changequote([, ])dnl + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac +])dnl + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +ifdef([AC_PROVIDE_AC_PROG_INSTALL], [s%@INSTALL@%$INSTALL%g +])dnl +dnl The parens around the eval prevent an "illegal io" in Ultrix sh. +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +dnl This would break Makefile dependencies. +dnl if cmp -s $ac_file conftest.out 2>/dev/null; then +dnl echo "$ac_file is unchanged" +dnl rm -f conftest.out +dnl else +dnl rm -f $ac_file +dnl mv conftest.out $ac_file +dnl fi +fi; done +rm -f conftest.s* +]) + +dnl Create the config.h files from the config.h.in files. +dnl This is a subroutine of AC_OUTPUT. It is called inside a quoted +dnl here document whose contents are going into config.status. +dnl AC_OUTPUT_HEADER(HEADER-FILE...) +define(AC_OUTPUT_HEADER, +[changequote(<<, >>)dnl +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='<<$>>%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' +changequote([, ])dnl + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +dnl Support passing AC_CONFIG_HEADER a value containing shell variables. +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="$1" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then +changequote(, )dnl + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac +changequote([, ])dnl + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +dnl Using a here document instead of a string reduces the quoting nightmare. +dnl Putting comments in sed scripts is not portable. +cat > conftest.hdr <<\EOF +changequote(<<, >>)dnl +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%<<#define>> \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +changequote([, ])dnl +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +changequote(, )dnl +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +changequote([, ])dnl +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +dnl Now back to your regularly scheduled config.status. +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + changequote(, )dnl + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + changequote([, ])dnl + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +]) + +dnl This is a subroutine of AC_OUTPUT. It is called inside a quoted +dnl here document whose contents are going into config.status. +dnl AC_OUTPUT_LINKS(SOURCE..., DEST...) +define(AC_OUTPUT_LINKS, +[EOF + +cat >> $CONFIG_STATUS <<EOF +ac_sources="$1" +ac_dests="$2" +EOF + +cat >> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=[$]1; shift; ac_dests=[$]* + set $ac_sources; ac_source=[$]1; shift; ac_sources=[$]* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + AC_MSG_ERROR($srcdir/$ac_source: File not found) + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. +changequote(, )dnl + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` +changequote([, ])dnl + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. +changequote(, )dnl + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` +changequote([, ])dnl + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in +changequote(, )dnl + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; +changequote([, ])dnl + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + AC_MSG_ERROR(can not link $ac_dest to $srcdir/$ac_source) + fi +done +]) + +dnl This is a subroutine of AC_OUTPUT. +dnl It is called after running config.status. +dnl AC_OUTPUT_SUBDIRS(DIRECTORY...) +define(AC_OUTPUT_SUBDIRS, +[ +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in $1; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + AC_MSG_ERROR(can not create `pwd`/$ac_config_dir) + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + +changequote(, )dnl + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` +changequote([, ])dnl + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + AC_MSG_WARN(no configuration information is in $ac_config_dir) + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + ac_sub_cache_file="$ac_dots$cache_file" ;; + esac +ifdef([AC_PROVIDE_AC_PROG_INSTALL], + [ case "$ac_given_INSTALL" in +changequote(, )dnl + [/$]*) INSTALL="$ac_given_INSTALL" ;; +changequote([, ])dnl + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac +])dnl + + echo "[running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file] --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + AC_MSG_ERROR($ac_sub_configure failed for $ac_config_dir) + fi + fi + + cd $ac_popdir + done +fi +]) diff --git a/build/autoconf/acoldnames.m4 b/build/autoconf/acoldnames.m4 new file mode 100644 index 0000000000..d31cdd754f --- /dev/null +++ b/build/autoconf/acoldnames.m4 @@ -0,0 +1,80 @@ +dnl Map old names of Autoconf macros to new regularized names. +dnl This file is part of Autoconf. +dnl Copyright (C) 1994 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl General macros. +dnl +define(AC_WARN, [indir([AC_MSG_WARN], $@)])dnl +define(AC_ERROR, [indir([AC_MSG_ERROR], $@)])dnl +AC_DEFUN(AC_PROGRAM_CHECK, [indir([AC_CHECK_PROG], $@)])dnl +AC_DEFUN(AC_PROGRAM_PATH, [indir([AC_PATH_PROG], $@)])dnl +AC_DEFUN(AC_PROGRAMS_CHECK, [indir([AC_CHECK_PROGS], $@)])dnl +AC_DEFUN(AC_PROGRAMS_PATH, [indir([AC_PATH_PROGS], $@)])dnl +AC_DEFUN(AC_PREFIX, [indir([AC_PREFIX_PROGRAM], $@)])dnl +AC_DEFUN(AC_HEADER_EGREP, [indir([AC_EGREP_HEADER], $@)])dnl +AC_DEFUN(AC_PROGRAM_EGREP, [indir([AC_EGREP_CPP], $@)])dnl +AC_DEFUN(AC_TEST_PROGRAM, [indir([AC_TRY_RUN], $@)])dnl +AC_DEFUN(AC_TEST_CPP, [indir([AC_TRY_CPP], $@)])dnl +AC_DEFUN(AC_HEADER_CHECK, [indir([AC_CHECK_HEADER], $@)])dnl +AC_DEFUN(AC_FUNC_CHECK, [indir([AC_CHECK_FUNC], $@)])dnl +AC_DEFUN(AC_HAVE_FUNCS, [indir([AC_CHECK_FUNCS], $@)])dnl +AC_DEFUN(AC_HAVE_HEADERS, [indir([AC_CHECK_HEADERS], $@)])dnl +AC_DEFUN(AC_SIZEOF_TYPE, [indir([AC_CHECK_SIZEOF], $@)])dnl +dnl +dnl Specific macros. +dnl +AC_DEFUN(AC_GCC_TRADITIONAL, [indir([AC_PROG_GCC_TRADITIONAL])])dnl +AC_DEFUN(AC_MINUS_C_MINUS_O, [indir([AC_PROG_CC_C_O])])dnl +AC_DEFUN(AC_SET_MAKE, [indir([AC_PROG_MAKE_SET])])dnl +AC_DEFUN(AC_YYTEXT_POINTER, [indir([AC_DECL_YYTEXT])])dnl +AC_DEFUN(AC_LN_S, [indir([AC_PROG_LN_S])])dnl +AC_DEFUN(AC_STDC_HEADERS, [indir([AC_HEADER_STDC])])dnl +AC_DEFUN(AC_MAJOR_HEADER, [indir([AC_HEADER_MAJOR])])dnl +AC_DEFUN(AC_STAT_MACROS_BROKEN, [indir([AC_HEADER_STAT])])dnl +AC_DEFUN(AC_SYS_SIGLIST_DECLARED, [indir([AC_DECL_SYS_SIGLIST])])dnl +AC_DEFUN(AC_GETGROUPS_T, [indir([AC_TYPE_GETGROUPS])])dnl +AC_DEFUN(AC_UID_T, [indir([AC_TYPE_UID_T])])dnl +AC_DEFUN(AC_SIZE_T, [indir([AC_TYPE_SIZE_T])])dnl +AC_DEFUN(AC_PID_T, [indir([AC_TYPE_PID_T])])dnl +AC_DEFUN(AC_OFF_T, [indir([AC_TYPE_OFF_T])])dnl +AC_DEFUN(AC_MODE_T, [indir([AC_TYPE_MODE_T])])dnl +AC_DEFUN(AC_RETSIGTYPE, [indir([AC_TYPE_SIGNAL])])dnl +AC_DEFUN(AC_MMAP, [indir([AC_FUNC_MMAP])])dnl +AC_DEFUN(AC_VPRINTF, [indir([AC_FUNC_VPRINTF])])dnl +AC_DEFUN(AC_VFORK, [indir([AC_FUNC_VFORK])])dnl +AC_DEFUN(AC_WAIT3, [indir([AC_FUNC_WAIT3])])dnl +AC_DEFUN(AC_ALLOCA, [indir([AC_FUNC_ALLOCA])])dnl +AC_DEFUN(AC_GETLOADAVG, [indir([AC_FUNC_GETLOADAVG])])dnl +AC_DEFUN(AC_UTIME_NULL, [indir([AC_FUNC_UTIME_NULL])])dnl +AC_DEFUN(AC_STRCOLL, [indir([AC_FUNC_STRCOLL])])dnl +AC_DEFUN(AC_SETVBUF_REVERSED, [indir([AC_FUNC_SETVBUF_REVERSED])])dnl +AC_DEFUN(AC_TIME_WITH_SYS_TIME, [indir([AC_HEADER_TIME])])dnl +AC_DEFUN(AC_TIMEZONE, [indir([AC_STRUCT_TIMEZONE])])dnl +AC_DEFUN(AC_ST_BLOCKS, [indir([AC_STRUCT_ST_BLOCKS])])dnl +AC_DEFUN(AC_ST_BLKSIZE, [indir([AC_STRUCT_ST_BLKSIZE])])dnl +AC_DEFUN(AC_ST_RDEV, [indir([AC_STRUCT_ST_RDEV])])dnl +AC_DEFUN(AC_CROSS_CHECK, [indir([AC_C_CROSS])])dnl +AC_DEFUN(AC_CHAR_UNSIGNED, [indir([AC_C_CHAR_UNSIGNED])])dnl +AC_DEFUN(AC_LONG_DOUBLE, [indir([AC_C_LONG_DOUBLE])])dnl +AC_DEFUN(AC_WORDS_BIGENDIAN, [indir([AC_C_BIGENDIAN])])dnl +AC_DEFUN(AC_INLINE, [indir([AC_C_INLINE])])dnl +AC_DEFUN(AC_CONST, [indir([AC_C_CONST])])dnl +AC_DEFUN(AC_LONG_FILE_NAMES, [indir([AC_SYS_LONG_FILE_NAMES])])dnl +AC_DEFUN(AC_RESTARTABLE_SYSCALLS, [indir([AC_SYS_RESTARTABLE_SYSCALLS])])dnl +AC_DEFUN(AC_FIND_X, [indir([AC_PATH_X])])dnl +AC_DEFUN(AC_FIND_XTRA, [indir([AC_PATH_XTRA])])dnl diff --git a/build/autoconf/acspecific.m4 b/build/autoconf/acspecific.m4 new file mode 100644 index 0000000000..28af522876 --- /dev/null +++ b/build/autoconf/acspecific.m4 @@ -0,0 +1,2758 @@ +dnl Macros that test for specific features. +dnl This file is part of Autoconf. +dnl Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception, the Free Software Foundation gives unlimited +dnl permission to copy, distribute and modify the configure scripts that +dnl are the output of Autoconf. You need not follow the terms of the GNU +dnl General Public License when using or distributing such scripts, even +dnl though portions of the text of Autoconf appear in them. The GNU +dnl General Public License (GPL) does govern all other use of the material +dnl that constitutes the Autoconf program. +dnl +dnl Certain portions of the Autoconf source text are designed to be copied +dnl (in certain cases, depending on the input) into the output of +dnl Autoconf. We call these the "data" portions. The rest of the Autoconf +dnl source text consists of comments plus executable code that decides which +dnl of the data portions to output in any given case. We call these +dnl comments and executable code the "non-data" portions. Autoconf never +dnl copies any of the non-data portions into its output. +dnl +dnl This special exception to the GPL applies to versions of Autoconf +dnl released by the Free Software Foundation. When you make and +dnl distribute a modified version of Autoconf, you may extend this special +dnl exception to the GPL to apply to your modified version as well, *unless* +dnl your modified version has the potential to copy into its output some +dnl of the text that was the non-data portion of the version that you started +dnl with. (In other words, unless your change moves or copies text from +dnl the non-data portions to the data portions.) If your modification has +dnl such potential, you must delete any notice of this special exception +dnl to the GPL from your modified version. +dnl +dnl Written by David MacKenzie, with help from +dnl Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor, +dnl Roland McGrath, Noah Friedman, david d zuhn, and many others. + + +dnl ### Checks for programs + + +dnl Check whether to use -n, \c, or newline-tab to separate +dnl checking messages from result messages. +dnl Idea borrowed from dist 3.0. +dnl Internal use only. +AC_DEFUN(AC_PROG_ECHO_N, +[if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi +]) + +AC_DEFUN(AC_PROG_CC, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +AC_CHECK_PROG(CC, gcc, gcc) +if test -z "$CC"; then + AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc) + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + AC_CHECK_PROG(CC, cl, cl) ;; + esac + fi + test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) +fi + +AC_PROG_CC_WORKS +AC_PROG_CC_GNU + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +dnl Check whether -g works, even if CFLAGS is set, in case the package +dnl plays around with CFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +AC_PROG_CC_G +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +]) + +AC_DEFUN(AC_PROG_CXX, +[AC_BEFORE([$0], [AC_PROG_CXXCPP])dnl +AC_CHECK_PROGS(CXX, $CCC c++ g++ gcc CC cxx cc++ cl, gcc) + +AC_PROG_CXX_WORKS +AC_PROG_CXX_GNU + +if test $ac_cv_prog_gxx = yes; then + GXX=yes +else + GXX= +fi + +dnl Check whether -g works, even if CXXFLAGS is set, in case the package +dnl plays around with CXXFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. +ac_test_CXXFLAGS="${CXXFLAGS+set}" +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS= +AC_PROG_CXX_G +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +]) + +dnl Determine a Fortran 77 compiler to use. If `F77' is not already set +dnl in the environment, check for `g77', `f77' and `f2c', in that order. +dnl Set the output variable `F77' to the name of the compiler found. +dnl +dnl If using `g77' (the GNU Fortran 77 compiler), then `AC_PROG_F77' +dnl will set the shell variable `G77' to `yes', and empty otherwise. If +dnl the output variable `FFLAGS' was not already set in the environment, +dnl then set it to `-g -02' for `g77' (or `-O2' where `g77' does not +dnl accept `-g'). Otherwise, set `FFLAGS' to `-g' for all other Fortran +dnl 77 compilers. +dnl +dnl AC_PROG_F77() +AC_DEFUN(AC_PROG_F77, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +if test -z "$F77"; then + AC_CHECK_PROGS(F77, g77 f77 f2c) + test -z "$F77" && AC_MSG_ERROR([no acceptable Fortran 77 compiler found in \$PATH]) +fi + +AC_PROG_F77_WORKS +AC_PROG_F77_GNU + +if test $ac_cv_prog_g77 = yes; then + G77=yes +dnl Check whether -g works, even if FFLAGS is set, in case the package +dnl plays around with FFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. + ac_test_FFLAGS="${FFLAGS+set}" + ac_save_FFLAGS="$FFLAGS" + FFLAGS= + AC_PROG_F77_G + if test "$ac_test_FFLAGS" = set; then + FFLAGS="$ac_save_FFLAGS" + elif test $ac_cv_prog_f77_g = yes; then + FFLAGS="-g -O2" + else + FFLAGS="-O2" + fi +else + G77= + test "${FFLAGS+set}" = set || FFLAGS="-g" +fi +]) + +AC_DEFUN(AC_PROG_CC_WORKS, +[AC_MSG_CHECKING([whether the C compiler ($CC $CFLAGS $LDFLAGS) works]) +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILER([main(){return(0);}], ac_cv_prog_cc_works, ac_cv_prog_cc_cross) +AC_LANG_RESTORE +AC_MSG_RESULT($ac_cv_prog_cc_works) +if test $ac_cv_prog_cc_works = no; then + AC_MSG_ERROR([installation or configuration problem: C compiler cannot create executables.]) +fi +AC_MSG_CHECKING([whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler]) +AC_MSG_RESULT($ac_cv_prog_cc_cross) +cross_compiling=$ac_cv_prog_cc_cross +]) + +AC_DEFUN(AC_PROG_CXX_WORKS, +[AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works]) +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_TRY_COMPILER([int main(){return(0);}], ac_cv_prog_cxx_works, ac_cv_prog_cxx_cross) +AC_LANG_RESTORE +AC_MSG_RESULT($ac_cv_prog_cxx_works) +if test $ac_cv_prog_cxx_works = no; then + AC_MSG_ERROR([installation or configuration problem: C++ compiler cannot create executables.]) +fi +AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler]) +AC_MSG_RESULT($ac_cv_prog_cxx_cross) +cross_compiling=$ac_cv_prog_cxx_cross +]) + +dnl Test whether the Fortran 77 compiler can compile and link a trivial +dnl Fortran program. Also, test whether the Fortran 77 compiler is a +dnl cross-compiler (which may realistically be the case if the Fortran +dnl compiler is `g77'). +dnl +dnl AC_PROG_F77_WORKS() +AC_DEFUN(AC_PROG_F77_WORKS, +[AC_MSG_CHECKING([whether the Fortran 77 compiler ($F77 $FFLAGS $LDFLAGS) works]) +AC_LANG_SAVE +AC_LANG_FORTRAN77 +AC_TRY_COMPILER(dnl +[ program conftest + end +], ac_cv_prog_f77_works, ac_cv_prog_f77_cross) +AC_LANG_RESTORE +AC_MSG_RESULT($ac_cv_prog_f77_works) +if test $ac_cv_prog_f77_works = no; then + AC_MSG_ERROR([installation or configuration problem: Fortran 77 compiler cannot create executables.]) +fi +AC_MSG_CHECKING([whether the Fortran 77 compiler ($F77 $FFLAGS $LDFLAGS) is a cross-compiler]) +AC_MSG_RESULT($ac_cv_prog_f77_cross) +cross_compiling=$ac_cv_prog_f77_cross +]) + +AC_DEFUN(AC_PROG_CC_GNU, +[AC_CACHE_CHECK(whether we are using GNU C, ac_cv_prog_gcc, +[dnl The semicolon is to pacify NeXT's syntax-checking cpp. +cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if AC_TRY_COMMAND(${CC-cc} -E conftest.c) | grep -E yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi])]) + +AC_DEFUN(AC_PROG_CXX_GNU, +[AC_CACHE_CHECK(whether we are using GNU C++, ac_cv_prog_gxx, +[dnl The semicolon is to pacify NeXT's syntax-checking cpp. +cat > conftest.C <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if AC_TRY_COMMAND(${CXX-g++} -E conftest.C) | grep -E yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi])]) + +dnl Test whether for Fortran 77 compiler is `g77' (the GNU Fortran 77 +dnl Compiler). This test depends on whether the Fortran 77 compiler can +dnl do CPP pre-processing. +dnl +dnl AC_PROG_F77_GNU() +AC_DEFUN(AC_PROG_F77_GNU, +[AC_CACHE_CHECK(whether we are using GNU Fortran 77, ac_cv_prog_g77, +[cat > conftest.fpp <<EOF +#ifdef __GNUC__ + yes +#endif +EOF +if AC_TRY_COMMAND($F77 -E conftest.fpp) | grep -E yes >/dev/null 2>&1; then + ac_cv_prog_g77=yes +else + ac_cv_prog_g77=no +fi])]) + +AC_DEFUN(AC_PROG_CC_G, +[AC_CACHE_CHECK(whether ${CC-cc} accepts -g, ac_cv_prog_cc_g, +[echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* +])]) + +AC_DEFUN(AC_PROG_CXX_G, +[AC_CACHE_CHECK(whether ${CXX-g++} accepts -g, ac_cv_prog_cxx_g, +[echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* +])]) + +dnl Test whether the Fortran 77 compiler can accept the `-g' option to +dnl enable debugging. +dnl +dnl AC_PROG_F77_G() +AC_DEFUN(AC_PROG_F77_G, +[AC_CACHE_CHECK(whether $F77 accepts -g, ac_cv_prog_f77_g, +[cat > conftest.f << EOF + program conftest + end +EOF +if test -z "`$F77 -g -c conftest.f 2>&1`"; then + ac_cv_prog_f77_g=yes +else + ac_cv_prog_f77_g=no +fi +rm -f conftest* +])]) + +AC_DEFUN(AC_PROG_GCC_TRADITIONAL, +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +if test $ac_cv_prog_gcc = yes; then + AC_CACHE_CHECK(whether ${CC-cc} needs -traditional, + ac_cv_prog_gcc_traditional, +[ ac_pattern="Autoconf.*'x'" + AC_EGREP_CPP($ac_pattern, [#include <sgtty.h> +Autoconf TIOCGETP], + ac_cv_prog_gcc_traditional=yes, ac_cv_prog_gcc_traditional=no) + + if test $ac_cv_prog_gcc_traditional = no; then + AC_EGREP_CPP($ac_pattern, [#include <termio.h> +Autoconf TCGETA], + ac_cv_prog_gcc_traditional=yes) + fi]) + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi +]) + +AC_DEFUN(AC_PROG_CC_C_O, +[if test "x$CC" != xcc; then + AC_MSG_CHECKING(whether $CC and cc understand -c and -o together) +else + AC_MSG_CHECKING(whether cc understands -c and -o together) +fi +set dummy $CC; ac_cc="`echo [$]2 | +changequote(, )dnl + sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`" +changequote([, ])dnl +AC_CACHE_VAL(ac_cv_prog_cc_${ac_cc}_c_o, +[echo 'foo(){}' > conftest.c +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='${CC-cc} -c conftest.c -o conftest.o 1>&AC_FD_CC' +if AC_TRY_EVAL(ac_try) && + test -f conftest.o && AC_TRY_EVAL(ac_try); +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if AC_TRY_COMMAND(cc -c conftest.c 1>&AC_FD_CC); then + ac_try='cc -c conftest.c -o conftest.o 1>&AC_FD_CC' + if AC_TRY_EVAL(ac_try) && + test -f conftest.o && AC_TRY_EVAL(ac_try); + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f conftest* +])dnl +if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = yes"; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) + AC_DEFINE(NO_MINUS_C_MINUS_O) +fi +]) + +dnl Test if the Fortran 77 compiler accepts the options `-c' and `-o' +dnl simultaneously, and define `F77_NO_MINUS_C_MINUS_O' if it does not. +dnl +dnl The usefulness of this macro is questionable, as I can't really see +dnl why anyone would use it. The only reason I include it is for +dnl completeness, since a similar test exists for the C compiler. +dnl +dnl AC_PROG_F77_C_O +AC_DEFUN(AC_PROG_F77_C_O, +[AC_BEFORE([$0], [AC_PROG_F77])dnl +AC_MSG_CHECKING(whether $F77 understand -c and -o together) +set dummy $F77; ac_f77="`echo [$]2 | +changequote(, )dnl +sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`" +changequote([, ])dnl +AC_CACHE_VAL(ac_cv_prog_f77_${ac_f77}_c_o, +[cat > conftest.f << EOF + program conftest + end +EOF +# We do the `AC_TRY_EVAL' test twice because some compilers refuse to +# overwrite an existing `.o' file with `-o', although they will create +# one. +ac_try='$F77 $FFLAGS -c conftest.f -o conftest.o 1>&AC_FD_CC' +if AC_TRY_EVAL(ac_try) && test -f conftest.o && AC_TRY_EVAL(ac_try); then + eval ac_cv_prog_f77_${ac_f77}_c_o=yes +else + eval ac_cv_prog_f77_${ac_f77}_c_o=no +fi +rm -f conftest* +])dnl +if eval "test \"`echo '$ac_cv_prog_f77_'${ac_f77}_c_o`\" = yes"; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) + AC_DEFINE(F77_NO_MINUS_C_MINUS_O) +fi +]) + +dnl Define SET_MAKE to set ${MAKE} if make doesn't. +AC_DEFUN(AC_PROG_MAKE_SET, +[AC_MSG_CHECKING(whether ${MAKE-make} sets \${MAKE}) +set dummy ${MAKE-make}; ac_make=`echo "[$]2" | sed 'y%./+-%__p_%'` +AC_CACHE_VAL(ac_cv_prog_make_${ac_make}_set, +[cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +changequote(, )dnl +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +changequote([, ])dnl +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake])dnl +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + AC_MSG_RESULT(yes) + SET_MAKE= +else + AC_MSG_RESULT(no) + SET_MAKE="MAKE=${MAKE-make}" +fi +AC_SUBST([SET_MAKE])dnl +]) + +AC_DEFUN(AC_PROG_RANLIB, +[AC_CHECK_PROG(RANLIB, ranlib, ranlib, :)]) + +dnl Check for mawk first since it's generally faster. +AC_DEFUN(AC_PROG_AWK, +[AC_CHECK_PROGS(AWK, mawk gawk nawk awk, )]) + +AC_DEFUN(AC_PROG_YACC, +[AC_CHECK_PROGS(YACC, 'bison -y' byacc, yacc)]) + +AC_DEFUN(AC_PROG_CPP, +[AC_MSG_CHECKING(how to run the C preprocessor) +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +AC_CACHE_VAL(ac_cv_prog_CPP, +[ # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. +dnl Use a header file that comes with gcc, so configuring glibc +dnl with a fresh cross-compiler works. + AC_TRY_CPP([#include <assert.h> +Syntax Error], , + CPP="${CC-cc} -E -traditional-cpp" + AC_TRY_CPP([#include <assert.h> +Syntax Error], , + CPP="${CC-cc} -nologo -E" + AC_TRY_CPP([#include <assert.h> +Syntax Error], , CPP=/lib/cpp))) + ac_cv_prog_CPP="$CPP"])dnl + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +AC_MSG_RESULT($CPP) +AC_SUBST(CPP)dnl +]) + +AC_DEFUN(AC_PROG_CXXCPP, +[AC_MSG_CHECKING(how to run the C++ preprocessor) +if test -z "$CXXCPP"; then +AC_CACHE_VAL(ac_cv_prog_CXXCPP, +[AC_LANG_SAVE[]dnl +AC_LANG_CPLUSPLUS[]dnl + CXXCPP="${CXX-g++} -E" + AC_TRY_CPP([#include <stdlib.h>], , CXXCPP=/lib/cpp) + ac_cv_prog_CXXCPP="$CXXCPP" +AC_LANG_RESTORE[]dnl +fi])dnl +CXXCPP="$ac_cv_prog_CXXCPP" +AC_MSG_RESULT($CXXCPP) +AC_SUBST(CXXCPP)dnl +]) + +dnl Require finding the C or C++ preprocessor, whichever is the +dnl current language. +AC_DEFUN(AC_REQUIRE_CPP, +[ifelse(AC_LANG, C, [AC_REQUIRE([AC_PROG_CPP])], [AC_REQUIRE([AC_PROG_CXXCPP])])]) + +AC_DEFUN(AC_PROG_LEX, +[AC_CHECK_PROG(LEX, flex, flex, lex) +if test -z "$LEXLIB" +then + case "$LEX" in + flex*) ac_lib=fl ;; + *) ac_lib=l ;; + esac + AC_CHECK_LIB($ac_lib, yywrap, LEXLIB="-l$ac_lib") +fi +AC_SUBST(LEXLIB)]) + +dnl Check if lex declares yytext as a char * by default, not a char[]. +undefine([AC_DECL_YYTEXT]) +AC_DEFUN(AC_DECL_YYTEXT, +[AC_REQUIRE_CPP()dnl +AC_REQUIRE([AC_PROG_LEX])dnl +AC_CACHE_CHECK(lex output file root, ac_cv_prog_lex_root, +[# The minimal lex program is just a single line: %%. But some broken lexes +# (Solaris, I think it was) want two %% lines, so accommodate them. +echo '%% +%%' | $LEX +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + AC_MSG_ERROR(cannot find output from $LEX; giving up) +fi]) +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root +AC_SUBST(LEX_OUTPUT_ROOT)dnl + +AC_CACHE_CHECK(whether yytext is a pointer, ac_cv_prog_lex_yytext_pointer, +[# POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c +ac_save_LIBS="$LIBS" +LIBS="$LIBS $LEXLIB" +AC_TRY_LINK(`cat $LEX_OUTPUT_ROOT.c`, , ac_cv_prog_lex_yytext_pointer=yes) +LIBS="$ac_save_LIBS" +rm -f "${LEX_OUTPUT_ROOT}.c" +]) +dnl +if test $ac_cv_prog_lex_yytext_pointer = yes; then + AC_DEFINE(YYTEXT_POINTER) +fi +]) + +AC_DEFUN(AC_PROG_INSTALL, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +AC_MSG_CHECKING(for a BSD compatible install) +if test -z "$INSTALL"; then +AC_CACHE_VAL(ac_cv_path_install, +[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" +])dnl + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +dnl We do special magic for INSTALL instead of AC_SUBST, to get +dnl relative paths right. +AC_MSG_RESULT($INSTALL) + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' +AC_SUBST(INSTALL_PROGRAM)dnl + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' +AC_SUBST(INSTALL_SCRIPT)dnl + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +AC_SUBST(INSTALL_DATA)dnl +]) + +AC_DEFUN(AC_PROG_LN_S, +[AC_MSG_CHECKING(whether ln -s works) +AC_CACHE_VAL(ac_cv_prog_LN_S, +[rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi])dnl +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi +AC_SUBST(LN_S)dnl +]) + +define(AC_RSH, +[errprint(__file__:__line__: [$0] has been removed; replace it with equivalent code +)m4exit(4)]) + + +dnl ### Checks for header files + + +AC_DEFUN(AC_HEADER_STDC, +[AC_REQUIRE_CPP()dnl +AC_CACHE_CHECK(for ANSI C header files, ac_cv_header_stdc, +[AC_TRY_CPP([#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h>], ac_cv_header_stdc=yes, ac_cv_header_stdc=no) + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +AC_EGREP_HEADER(memchr, string.h, , ac_cv_header_stdc=no) +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +AC_EGREP_HEADER(free, stdlib.h, , ac_cv_header_stdc=no) +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +AC_TRY_RUN([#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } +], , ac_cv_header_stdc=no, :) +fi]) +if test $ac_cv_header_stdc = yes; then + AC_DEFINE(STDC_HEADERS) +fi +]) + +AC_DEFUN(AC_UNISTD_H, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_HEADERS(unistd.h)])dnl +AC_CHECK_HEADER(unistd.h, AC_DEFINE(HAVE_UNISTD_H))]) + +AC_DEFUN(AC_USG, +[AC_OBSOLETE([$0], + [; instead use AC_CHECK_HEADERS(string.h) and HAVE_STRING_H])dnl +AC_MSG_CHECKING([for BSD string and memory functions]) +AC_TRY_LINK([#include <strings.h>], [rindex(0, 0); bzero(0, 0);], + [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no); AC_DEFINE(USG)])]) + + +dnl If memchr and the like aren't declared in <string.h>, include <memory.h>. +dnl To avoid problems, don't check for gcc2 built-ins. +AC_DEFUN(AC_MEMORY_H, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_HEADERS(memory.h) and HAVE_MEMORY_H])dnl +AC_MSG_CHECKING(whether string.h declares mem functions) +AC_EGREP_HEADER(memchr, string.h, ac_found=yes, ac_found=no) +AC_MSG_RESULT($ac_found) +if test $ac_found = no; then + AC_CHECK_HEADER(memory.h, [AC_DEFINE(NEED_MEMORY_H)]) +fi +]) + +AC_DEFUN(AC_HEADER_MAJOR, +[AC_CACHE_CHECK(whether sys/types.h defines makedev, + ac_cv_header_sys_types_h_makedev, +[AC_TRY_LINK([#include <sys/types.h>], [return makedev(0, 0);], + ac_cv_header_sys_types_h_makedev=yes, ac_cv_header_sys_types_h_makedev=no) +]) + +if test $ac_cv_header_sys_types_h_makedev = no; then +AC_CHECK_HEADER(sys/mkdev.h, [AC_DEFINE(MAJOR_IN_MKDEV)]) + + if test $ac_cv_header_sys_mkdev_h = no; then +AC_CHECK_HEADER(sys/sysmacros.h, [AC_DEFINE(MAJOR_IN_SYSMACROS)]) + fi +fi +]) + +AC_DEFUN(AC_HEADER_DIRENT, +[ac_header_dirent=no +AC_CHECK_HEADERS_DIRENT(dirent.h sys/ndir.h sys/dir.h ndir.h, + [ac_header_dirent=$ac_hdr; break]) +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +AC_CHECK_LIB(dir, opendir, LIBS="$LIBS -ldir") +else +AC_CHECK_LIB(x, opendir, LIBS="$LIBS -lx") +fi +]) + +dnl Like AC_CHECK_HEADER, except also make sure that HEADER-FILE +dnl defines the type `DIR'. dirent.h on NextStep 3.2 doesn't. +dnl AC_CHECK_HEADER_DIRENT(HEADER-FILE, ACTION-IF-FOUND) +AC_DEFUN(AC_CHECK_HEADER_DIRENT, +[ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1 that defines DIR]) +AC_CACHE_VAL(ac_cv_header_dirent_$ac_safe, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <$1>], [DIR *dirp = 0;], + eval "ac_cv_header_dirent_$ac_safe=yes", + eval "ac_cv_header_dirent_$ac_safe=no")])dnl +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + $2 +else + AC_MSG_RESULT(no) +fi +]) + +dnl Like AC_CHECK_HEADERS, except succeed only for a HEADER-FILE that +dnl defines `DIR'. +dnl AC_CHECK_HEADERS_DIRENT(HEADER-FILE... [, ACTION]) +define(AC_CHECK_HEADERS_DIRENT, +[for ac_hdr in $1 +do +AC_CHECK_HEADER_DIRENT($ac_hdr, +[changequote(, )dnl + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_hdr) $2])dnl +done]) + +AC_DEFUN(AC_DIR_HEADER, +[AC_OBSOLETE([$0], [; instead use AC_HEADER_DIRENT])dnl +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + AC_CHECK_HEADER_DIRENT($ac_hdr, [ac_header_dirent=$ac_hdr; break]) +done + +case "$ac_header_dirent" in +dirent.h) AC_DEFINE(DIRENT) ;; +sys/ndir.h) AC_DEFINE(SYSNDIR) ;; +sys/dir.h) AC_DEFINE(SYSDIR) ;; +ndir.h) AC_DEFINE(NDIR) ;; +esac + +AC_CACHE_CHECK(whether closedir returns void, ac_cv_func_closedir_void, +[AC_TRY_RUN([#include <sys/types.h> +#include <$ac_header_dirent> +int closedir(); main() { exit(closedir(opendir(".")) != 0); }], + ac_cv_func_closedir_void=no, ac_cv_func_closedir_void=yes, ac_cv_func_closedir_void=yes)]) +if test $ac_cv_func_closedir_void = yes; then + AC_DEFINE(VOID_CLOSEDIR) +fi +]) + +AC_DEFUN(AC_HEADER_STAT, +[AC_CACHE_CHECK(whether stat file-mode macros are broken, + ac_cv_header_stat_broken, +[AC_EGREP_CPP([You lose], [#include <sys/types.h> +#include <sys/stat.h> + +#if defined(S_ISBLK) && defined(S_IFDIR) +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined(S_ISBLK) && defined(S_IFCHR) +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined(S_ISLNK) && defined(S_IFREG) +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFREG) +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif +], ac_cv_header_stat_broken=yes, ac_cv_header_stat_broken=no)]) +if test $ac_cv_header_stat_broken = yes; then + AC_DEFINE(STAT_MACROS_BROKEN) +fi +]) + +AC_DEFUN(AC_DECL_SYS_SIGLIST, +[AC_CACHE_CHECK([for sys_siglist declaration in signal.h or unistd.h], + ac_cv_decl_sys_siglist, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <signal.h> +/* NetBSD declares sys_siglist in unistd.h. */ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif], [char *msg = *(sys_siglist + 1);], + ac_cv_decl_sys_siglist=yes, ac_cv_decl_sys_siglist=no)]) +if test $ac_cv_decl_sys_siglist = yes; then + AC_DEFINE(SYS_SIGLIST_DECLARED) +fi +]) + +AC_DEFUN(AC_HEADER_SYS_WAIT, +[AC_CACHE_CHECK([for sys/wait.h that is POSIX.1 compatible], + ac_cv_header_sys_wait_h, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/wait.h> +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif], [int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;], +ac_cv_header_sys_wait_h=yes, ac_cv_header_sys_wait_h=no)]) +if test $ac_cv_header_sys_wait_h = yes; then + AC_DEFINE(HAVE_SYS_WAIT_H) +fi +]) + + +dnl ### Checks for typedefs + + +AC_DEFUN(AC_TYPE_GETGROUPS, +[AC_REQUIRE([AC_TYPE_UID_T])dnl +AC_CACHE_CHECK(type of array argument to getgroups, ac_cv_type_getgroups, +[AC_TRY_RUN( +changequote(<<, >>)dnl +<< +/* Thanks to Mike Rendell for this test. */ +#include <sys/types.h> +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +main() +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short but getgroups modifies an array of ints. */ + exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); +} +>>, +changequote([, ])dnl + ac_cv_type_getgroups=gid_t, ac_cv_type_getgroups=int, + ac_cv_type_getgroups=cross) +if test $ac_cv_type_getgroups = cross; then + dnl When we can't run the test program (we are cross compiling), presume + dnl that <unistd.h> has either an accurate prototype for getgroups or none. + dnl Old systems without prototypes probably use int. + AC_EGREP_HEADER([getgroups.*int.*gid_t], unistd.h, + ac_cv_type_getgroups=gid_t, ac_cv_type_getgroups=int) +fi]) +AC_DEFINE_UNQUOTED(GETGROUPS_T, $ac_cv_type_getgroups) +]) + +AC_DEFUN(AC_TYPE_UID_T, +[AC_CACHE_CHECK(for uid_t in sys/types.h, ac_cv_type_uid_t, +[AC_EGREP_HEADER(uid_t, sys/types.h, + ac_cv_type_uid_t=yes, ac_cv_type_uid_t=no)]) +if test $ac_cv_type_uid_t = no; then + AC_DEFINE(uid_t, int) + AC_DEFINE(gid_t, int) +fi +]) + +AC_DEFUN(AC_TYPE_SIZE_T, +[AC_CHECK_TYPE(size_t, unsigned)]) + +AC_DEFUN(AC_TYPE_PID_T, +[AC_CHECK_TYPE(pid_t, int)]) + +AC_DEFUN(AC_TYPE_OFF_T, +[AC_CHECK_TYPE(off_t, long)]) + +AC_DEFUN(AC_TYPE_MODE_T, +[AC_CHECK_TYPE(mode_t, int)]) + +dnl Note that identifiers starting with SIG are reserved by ANSI C. +AC_DEFUN(AC_TYPE_SIGNAL, +[AC_CACHE_CHECK([return type of signal handlers], ac_cv_type_signal, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <signal.h> +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif +], +[int i;], ac_cv_type_signal=void, ac_cv_type_signal=int)]) +AC_DEFINE_UNQUOTED(RETSIGTYPE, $ac_cv_type_signal) +]) + + +dnl ### Checks for functions + + +AC_DEFUN(AC_FUNC_CLOSEDIR_VOID, +[AC_REQUIRE([AC_HEADER_DIRENT])dnl +AC_CACHE_CHECK(whether closedir returns void, ac_cv_func_closedir_void, +[AC_TRY_RUN([#include <sys/types.h> +#include <$ac_header_dirent> +int closedir(); main() { exit(closedir(opendir(".")) != 0); }], + ac_cv_func_closedir_void=no, ac_cv_func_closedir_void=yes, ac_cv_func_closedir_void=yes)]) +if test $ac_cv_func_closedir_void = yes; then + AC_DEFINE(CLOSEDIR_VOID) +fi +]) + +AC_DEFUN(AC_FUNC_FNMATCH, +[AC_CACHE_CHECK(for working fnmatch, ac_cv_func_fnmatch_works, +# Some versions of Solaris or SCO have a broken fnmatch function. +# So we run a test program. If we are cross-compiling, take no chance. +# Thanks to John Oleynick and Franc,ois Pinard for this test. +[AC_TRY_RUN([main() { exit (fnmatch ("a*", "abc", 0) != 0); }], +ac_cv_func_fnmatch_works=yes, ac_cv_func_fnmatch_works=no, +ac_cv_func_fnmatch_works=no)]) +if test $ac_cv_func_fnmatch_works = yes; then + AC_DEFINE(HAVE_FNMATCH) +fi +]) + +AC_DEFUN(AC_FUNC_MMAP, +[AC_CHECK_HEADERS(unistd.h) +AC_CHECK_FUNCS(getpagesize) +AC_CACHE_CHECK(for working mmap, ac_cv_func_mmap_fixed_mapped, +[AC_TRY_RUN([ +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the filesystem buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propogated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ +#include <sys/types.h> +#include <fcntl.h> +#include <sys/mman.h> + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} +], ac_cv_func_mmap_fixed_mapped=yes, ac_cv_func_mmap_fixed_mapped=no, +ac_cv_func_mmap_fixed_mapped=no)]) +if test $ac_cv_func_mmap_fixed_mapped = yes; then + AC_DEFINE(HAVE_MMAP) +fi +]) + +AC_DEFUN(AC_FUNC_GETPGRP, +[AC_CACHE_CHECK(whether getpgrp takes no argument, ac_cv_func_getpgrp_void, +[AC_TRY_RUN([ +/* + * If this system has a BSD-style getpgrp(), + * which takes a pid argument, exit unsuccessfully. + * + * Snarfed from Chet Ramey's bash pgrp.c test program + */ +#include <stdio.h> +#include <sys/types.h> + +int pid; +int pg1, pg2, pg3, pg4; +int ng, np, s, child; + +main() +{ + pid = getpid(); + pg1 = getpgrp(0); + pg2 = getpgrp(); + pg3 = getpgrp(pid); + pg4 = getpgrp(1); + + /* + * If all of these values are the same, it's pretty sure that + * we're on a system that ignores getpgrp's first argument. + */ + if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3) + exit(0); + + child = fork(); + if (child < 0) + exit(1); + else if (child == 0) { + np = getpid(); + /* + * If this is Sys V, this will not work; pgrp will be + * set to np because setpgrp just changes a pgrp to be + * the same as the pid. + */ + setpgrp(np, pg1); + ng = getpgrp(0); /* Same result for Sys V and BSD */ + if (ng == pg1) { + exit(1); + } else { + exit(0); + } + } else { + wait(&s); + exit(s>>8); + } +} +], ac_cv_func_getpgrp_void=yes, ac_cv_func_getpgrp_void=no, + AC_MSG_ERROR(cannot check getpgrp if cross compiling)) +]) +if test $ac_cv_func_getpgrp_void = yes; then + AC_DEFINE(GETPGRP_VOID) +fi +]) + +AC_DEFUN(AC_FUNC_SETPGRP, +[AC_CACHE_CHECK(whether setpgrp takes no argument, ac_cv_func_setpgrp_void, +AC_TRY_RUN([ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +/* + * If this system has a BSD-style setpgrp, which takes arguments, exit + * successfully. + */ +main() +{ + if (setpgrp(1,1) == -1) + exit(0); + else + exit(1); +} +], ac_cv_func_setpgrp_void=no, ac_cv_func_setpgrp_void=yes, + AC_MSG_ERROR(cannot check setpgrp if cross compiling)) +) +if test $ac_cv_func_setpgrp_void = yes; then + AC_DEFINE(SETPGRP_VOID) +fi +]) + +AC_DEFUN(AC_FUNC_VPRINTF, +[AC_CHECK_FUNC(vprintf, AC_DEFINE(HAVE_VPRINTF)) +if test "$ac_cv_func_vprintf" != yes; then +AC_CHECK_FUNC(_doprnt, AC_DEFINE(HAVE_DOPRNT)) +fi +]) + +AC_DEFUN(AC_FUNC_VFORK, +[AC_REQUIRE([AC_TYPE_PID_T])dnl +AC_CHECK_HEADER(vfork.h, AC_DEFINE(HAVE_VFORK_H)) +AC_CACHE_CHECK(for working vfork, ac_cv_func_vfork_works, +[AC_TRY_RUN([/* Thanks to Paul Eggert for this test. */ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_VFORK_H +#include <vfork.h> +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. + The compiler is told about this with #include <vfork.h>, + but some compilers (e.g. gcc -O) don't grok <vfork.h>. + Test for this by using a static variable whose address + is put into a register that is clobbered by the vfork. */ +static +#ifdef __cplusplus +sparc_address_test (int arg) +#else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} +main() { + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. + This test uses lots of local variables, at least + as many local variables as main has allocated so far + including compiler temporaries. 4 locals are enough for + gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. + A buggy compiler should reuse the register of parent + for one of the local variables, since it will think that + parent can't possibly be used any more in this routine. + Assigning to the local variable will thus munge parent + in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), + vfork doesn't separate parent from child file descriptors. + If the child closes a descriptor before it execs or exits, + this munges the parent's descriptor as well. + Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + exit( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +}], +ac_cv_func_vfork_works=yes, ac_cv_func_vfork_works=no, AC_CHECK_FUNC(vfork) +ac_cv_func_vfork_works=$ac_cv_func_vfork)]) +if test $ac_cv_func_vfork_works = no; then + AC_DEFINE(vfork, fork) +fi +]) + +AC_DEFUN(AC_FUNC_WAIT3, +[AC_CACHE_CHECK(for wait3 that fills in rusage, ac_cv_func_wait3_rusage, +[AC_TRY_RUN([#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <stdio.h> +/* HP-UX has wait3 but does not fill in rusage at all. */ +main() { + struct rusage r; + int i; + /* Use a field that we can force nonzero -- + voluntary context switches. + For systems like NeXT and OSF/1 that don't set it, + also use the system CPU time. And page faults (I/O) for Linux. */ + r.ru_nvcsw = 0; + r.ru_stime.tv_sec = 0; + r.ru_stime.tv_usec = 0; + r.ru_majflt = r.ru_minflt = 0; + switch (fork()) { + case 0: /* Child. */ + sleep(1); /* Give up the CPU. */ + _exit(0); + case -1: _exit(0); /* What can we do? */ + default: /* Parent. */ + wait3(&i, 0, &r); + sleep(2); /* Avoid "text file busy" from rm on fast HP-UX machines. */ + exit(r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0 + && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0); + } +}], ac_cv_func_wait3_rusage=yes, ac_cv_func_wait3_rusage=no, +ac_cv_func_wait3_rusage=no)]) +if test $ac_cv_func_wait3_rusage = yes; then + AC_DEFINE(HAVE_WAIT3) +fi +]) + +AC_DEFUN(AC_FUNC_ALLOCA, +[AC_REQUIRE_CPP()dnl Set CPP; we run AC_EGREP_CPP conditionally. +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +AC_CACHE_CHECK([for working alloca.h], ac_cv_header_alloca_h, +[AC_TRY_LINK([#include <alloca.h>], [char *p = alloca(2 * sizeof(int));], + ac_cv_header_alloca_h=yes, ac_cv_header_alloca_h=no)]) +if test $ac_cv_header_alloca_h = yes; then + AC_DEFINE(HAVE_ALLOCA_H) +fi + +AC_CACHE_CHECK([for alloca], ac_cv_func_alloca_works, +[AC_TRY_LINK([ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif +], [char *p = (char *) alloca(1);], + ac_cv_func_alloca_works=yes, ac_cv_func_alloca_works=no)]) +if test $ac_cv_func_alloca_works = yes; then + AC_DEFINE(HAVE_ALLOCA) +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + AC_DEFINE(C_ALLOCA) + +AC_CACHE_CHECK(whether alloca needs Cray hooks, ac_cv_os_cray, +[AC_EGREP_CPP(webecray, +[#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif +], ac_cv_os_cray=yes, ac_cv_os_cray=no)]) +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + AC_CHECK_FUNC($ac_func, [AC_DEFINE_UNQUOTED(CRAY_STACKSEG_END, $ac_func) + break]) +done +fi + +AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction, +[AC_TRY_RUN([find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +}], ac_cv_c_stack_direction=1, ac_cv_c_stack_direction=-1, + ac_cv_c_stack_direction=0)]) +AC_DEFINE_UNQUOTED(STACK_DIRECTION, $ac_cv_c_stack_direction) +fi +AC_SUBST(ALLOCA)dnl +]) + +AC_DEFUN(AC_FUNC_GETLOADAVG, +[ac_have_func=no # yes means we've found a way to get the load average. + +# Some systems with -lutil have (and need) -lkvm as well, some do not. +# On Solaris, -lkvm requires nlist from -lelf, so check that first +# to get the right answer into the cache. +AC_CHECK_LIB(elf, elf_begin, LIBS="-lelf $LIBS") +AC_CHECK_LIB(kvm, kvm_open, LIBS="-lkvm $LIBS") +# Check for the 4.4BSD definition of getloadavg. +AC_CHECK_LIB(util, getloadavg, + [LIBS="-lutil $LIBS" ac_have_func=yes ac_cv_func_getloadavg_setgid=yes]) + +if test $ac_have_func = no; then + # There is a commonly available library for RS/6000 AIX. + # Since it is not a standard part of AIX, it might be installed locally. + ac_getloadavg_LIBS="$LIBS"; LIBS="-L/usr/local/lib $LIBS" + AC_CHECK_LIB(getloadavg, getloadavg, + LIBS="-lgetloadavg $LIBS", LIBS="$ac_getloadavg_LIBS") +fi + +# Make sure it is really in the library, if we think we found it. +AC_REPLACE_FUNCS(getloadavg) + +if test $ac_cv_func_getloadavg = yes; then + AC_DEFINE(HAVE_GETLOADAVG) + ac_have_func=yes +else + # Figure out what our getloadavg.c needs. + ac_have_func=no + AC_CHECK_HEADER(sys/dg_sys_info.h, + [ac_have_func=yes; AC_DEFINE(DGUX) + AC_CHECK_LIB(dgc, dg_sys_info)]) + + # We cannot check for <dwarf.h>, because Solaris 2 does not use dwarf (it + # uses stabs), but it is still SVR4. We cannot check for <elf.h> because + # Irix 4.0.5F has the header but not the library. + if test $ac_have_func = no && test $ac_cv_lib_elf_elf_begin = yes; then + ac_have_func=yes; AC_DEFINE(SVR4) + fi + + if test $ac_have_func = no; then + AC_CHECK_HEADER(inq_stats/cpustats.h, + [ac_have_func=yes; AC_DEFINE(UMAX) + AC_DEFINE(UMAX4_3)]) + fi + + if test $ac_have_func = no; then + AC_CHECK_HEADER(sys/cpustats.h, + [ac_have_func=yes; AC_DEFINE(UMAX)]) + fi + + if test $ac_have_func = no; then + AC_CHECK_HEADERS(mach/mach.h) + fi + + AC_CHECK_HEADER(nlist.h, + [AC_DEFINE(NLIST_STRUCT) + AC_CACHE_CHECK([for n_un in struct nlist], ac_cv_struct_nlist_n_un, + [AC_TRY_COMPILE([#include <nlist.h>], + [struct nlist n; n.n_un.n_name = 0;], + ac_cv_struct_nlist_n_un=yes, ac_cv_struct_nlist_n_un=no)]) + if test $ac_cv_struct_nlist_n_un = yes; then + AC_DEFINE(NLIST_NAME_UNION) + fi + ])dnl +fi # Do not have getloadavg in system libraries. + +# Some definitions of getloadavg require that the program be installed setgid. +dnl FIXME Don't hardwire the path of getloadavg.c in the top-level directory. +AC_CACHE_CHECK(whether getloadavg requires setgid, + ac_cv_func_getloadavg_setgid, +[AC_EGREP_CPP([Yowza Am I SETGID yet], +[#include "$srcdir/getloadavg.c" +#ifdef LDAV_PRIVILEGED +Yowza Am I SETGID yet +#endif], + ac_cv_func_getloadavg_setgid=yes, ac_cv_func_getloadavg_setgid=no)]) +if test $ac_cv_func_getloadavg_setgid = yes; then + NEED_SETGID=true; AC_DEFINE(GETLOADAVG_PRIVILEGED) +else + NEED_SETGID=false +fi +AC_SUBST(NEED_SETGID)dnl + +if test $ac_cv_func_getloadavg_setgid = yes; then + AC_CACHE_CHECK(group of /dev/kmem, ac_cv_group_kmem, +[changequote(, )dnl + # On Solaris, /dev/kmem is a symlink. Get info on the real file. + ac_ls_output=`ls -lgL /dev/kmem 2>/dev/null` + # If we got an error (system does not support symlinks), try without -L. + test -z "$ac_ls_output" && ac_ls_output=`ls -lg /dev/kmem` + ac_cv_group_kmem=`echo $ac_ls_output \ + | sed -ne 's/[ ][ ]*/ /g; + s/^.[sSrwx-]* *[0-9]* *\([^0-9]*\) *.*/\1/; + / /s/.* //;p;'` +changequote([, ])dnl +]) + KMEM_GROUP=$ac_cv_group_kmem +fi +AC_SUBST(KMEM_GROUP)dnl +]) + +AC_DEFUN(AC_FUNC_UTIME_NULL, +[AC_CACHE_CHECK(whether utime accepts a null argument, ac_cv_func_utime_null, +[rm -f conftestdata; > conftestdata +# Sequent interprets utime(file, 0) to mean use start of epoch. Wrong. +AC_TRY_RUN([#include <sys/types.h> +#include <sys/stat.h> +main() { +struct stat s, t; +exit(!(stat ("conftestdata", &s) == 0 && utime("conftestdata", (long *)0) == 0 +&& stat("conftestdata", &t) == 0 && t.st_mtime >= s.st_mtime +&& t.st_mtime - s.st_mtime < 120)); +}], ac_cv_func_utime_null=yes, ac_cv_func_utime_null=no, + ac_cv_func_utime_null=no) +rm -f core core.* *.core]) +if test $ac_cv_func_utime_null = yes; then + AC_DEFINE(HAVE_UTIME_NULL) +fi +]) + +AC_DEFUN(AC_FUNC_STRCOLL, +[AC_CACHE_CHECK(for working strcoll, ac_cv_func_strcoll_works, +[AC_TRY_RUN([#include <string.h> +main () +{ + exit (strcoll ("abc", "def") >= 0 || + strcoll ("ABC", "DEF") >= 0 || + strcoll ("123", "456") >= 0); +}], ac_cv_func_strcoll_works=yes, ac_cv_func_strcoll_works=no, +ac_cv_func_strcoll_works=no)]) +if test $ac_cv_func_strcoll_works = yes; then + AC_DEFINE(HAVE_STRCOLL) +fi +]) + +AC_DEFUN(AC_FUNC_SETVBUF_REVERSED, +[AC_CACHE_CHECK(whether setvbuf arguments are reversed, + ac_cv_func_setvbuf_reversed, +[AC_TRY_RUN([#include <stdio.h> +/* If setvbuf has the reversed format, exit 0. */ +main () { + /* This call has the arguments reversed. + A reversed system may check and see that the address of main + is not _IOLBF, _IONBF, or _IOFBF, and return nonzero. */ + if (setvbuf(stdout, _IOLBF, (char *) main, BUFSIZ) != 0) + exit(1); + putc('\r', stdout); + exit(0); /* Non-reversed systems segv here. */ +}], ac_cv_func_setvbuf_reversed=yes, ac_cv_func_setvbuf_reversed=no) +rm -f core core.* *.core]) +if test $ac_cv_func_setvbuf_reversed = yes; then + AC_DEFINE(SETVBUF_REVERSED) +fi +]) + +AC_DEFUN(AC_FUNC_GETMNTENT, +[# getmntent is in -lsun on Irix 4, -lseq on Dynix/PTX, -lgen on Unixware. +AC_CHECK_LIB(sun, getmntent, LIBS="-lsun $LIBS", + [AC_CHECK_LIB(seq, getmntent, LIBS="-lseq $LIBS", + [AC_CHECK_LIB(gen, getmntent, LIBS="-lgen $LIBS")])]) +AC_CHECK_FUNC(getmntent, [AC_DEFINE(HAVE_GETMNTENT)])]) + +AC_DEFUN(AC_FUNC_STRFTIME, +[AC_CHECK_FUNC(strftime, [AC_DEFINE(HAVE_STRFTIME)], +[# strftime is in -lintl on SCO UNIX. +AC_CHECK_LIB(intl, strftime, +[AC_DEFINE(HAVE_STRFTIME) +LIBS="-lintl $LIBS"])])]) + +AC_DEFUN(AC_FUNC_MEMCMP, +[AC_CACHE_CHECK(for 8-bit clean memcmp, ac_cv_func_memcmp_clean, +[AC_TRY_RUN([ +main() +{ + char c0 = 0x40, c1 = 0x80, c2 = 0x81; + exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1); +} +], ac_cv_func_memcmp_clean=yes, ac_cv_func_memcmp_clean=no, +ac_cv_func_memcmp_clean=no)]) +test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" +AC_SUBST(LIBOBJS)dnl +]) + +AC_DEFUN(AC_FUNC_SELECT_ARGTYPES, +[AC_MSG_CHECKING([types of arguments for select()]) + AC_CACHE_VAL(ac_cv_func_select_arg234,dnl + [AC_CACHE_VAL(ac_cv_func_select_arg1,dnl + [AC_CACHE_VAL(ac_cv_func_select_arg5,dnl + [for ac_cv_func_select_arg234 in 'fd_set *' 'int *' 'void *'; do + for ac_cv_func_select_arg1 in 'int' 'size_t' 'unsigned long' 'unsigned'; do + for ac_cv_func_select_arg5 in 'struct timeval *' 'const struct timeval *'; do + AC_TRY_COMPILE(dnl +[#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +extern select ($ac_cv_func_select_arg1,$ac_cv_func_select_arg234,$ac_cv_func_select_arg234,$ac_cv_func_select_arg234,$ac_cv_func_select_arg5);],,dnl + [ac_not_found=no ; break 3],ac_not_found=yes) + done + done + done + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + ])dnl AC_CACHE_VAL + if test "$ac_not_found" = yes; then + ac_cv_func_select_arg1=int + ac_cv_func_select_arg234='int *' + ac_cv_func_select_arg5='struct timeval *' + fi + AC_MSG_RESULT([$ac_cv_func_select_arg1,$ac_cv_func_select_arg234,$ac_cv_func_select_arg5]) + AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG1,$ac_cv_func_select_arg1) + AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG234,($ac_cv_func_select_arg234)) + AC_DEFINE_UNQUOTED(SELECT_TYPE_ARG5,($ac_cv_func_select_arg5)) +]) + + +dnl ### Checks for structure members + + +AC_DEFUN(AC_HEADER_TIME, +[AC_CACHE_CHECK([whether time.h and sys/time.h may both be included], + ac_cv_header_time, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/time.h> +#include <time.h>], +[struct tm *tp;], ac_cv_header_time=yes, ac_cv_header_time=no)]) +if test $ac_cv_header_time = yes; then + AC_DEFINE(TIME_WITH_SYS_TIME) +fi +]) + +AC_DEFUN(AC_STRUCT_TM, +[AC_CACHE_CHECK([whether struct tm is in sys/time.h or time.h], + ac_cv_struct_tm, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <time.h>], +[struct tm *tp; tp->tm_sec;], + ac_cv_struct_tm=time.h, ac_cv_struct_tm=sys/time.h)]) +if test $ac_cv_struct_tm = sys/time.h; then + AC_DEFINE(TM_IN_SYS_TIME) +fi +]) + +AC_DEFUN(AC_STRUCT_TIMEZONE, +[AC_REQUIRE([AC_STRUCT_TM])dnl +AC_CACHE_CHECK([for tm_zone in struct tm], ac_cv_struct_tm_zone, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <$ac_cv_struct_tm>], [struct tm tm; tm.tm_zone;], + ac_cv_struct_tm_zone=yes, ac_cv_struct_tm_zone=no)]) +if test "$ac_cv_struct_tm_zone" = yes; then + AC_DEFINE(HAVE_TM_ZONE) +else + AC_CACHE_CHECK(for tzname, ac_cv_var_tzname, +[AC_TRY_LINK( +changequote(<<, >>)dnl +<<#include <time.h> +#ifndef tzname /* For SGI. */ +extern char *tzname[]; /* RS6000 and others reject char **tzname. */ +#endif>>, +changequote([, ])dnl +[atoi(*tzname);], ac_cv_var_tzname=yes, ac_cv_var_tzname=no)]) + if test $ac_cv_var_tzname = yes; then + AC_DEFINE(HAVE_TZNAME) + fi +fi +]) + +AC_DEFUN(AC_STRUCT_ST_BLOCKS, +[AC_CACHE_CHECK([for st_blocks in struct stat], ac_cv_struct_st_blocks, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/stat.h>], [struct stat s; s.st_blocks;], +ac_cv_struct_st_blocks=yes, ac_cv_struct_st_blocks=no)]) +if test $ac_cv_struct_st_blocks = yes; then + AC_DEFINE(HAVE_ST_BLOCKS) +else + LIBOBJS="$LIBOBJS fileblocks.${ac_objext}" +fi +AC_SUBST(LIBOBJS)dnl +]) + +AC_DEFUN(AC_STRUCT_ST_BLKSIZE, +[AC_CACHE_CHECK([for st_blksize in struct stat], ac_cv_struct_st_blksize, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/stat.h>], [struct stat s; s.st_blksize;], +ac_cv_struct_st_blksize=yes, ac_cv_struct_st_blksize=no)]) +if test $ac_cv_struct_st_blksize = yes; then + AC_DEFINE(HAVE_ST_BLKSIZE) +fi +]) + +AC_DEFUN(AC_STRUCT_ST_RDEV, +[AC_CACHE_CHECK([for st_rdev in struct stat], ac_cv_struct_st_rdev, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/stat.h>], [struct stat s; s.st_rdev;], +ac_cv_struct_st_rdev=yes, ac_cv_struct_st_rdev=no)]) +if test $ac_cv_struct_st_rdev = yes; then + AC_DEFINE(HAVE_ST_RDEV) +fi +]) + + +dnl ### Checks for compiler characteristics + + +AC_DEFUN(AC_C_CROSS, +[AC_OBSOLETE([$0], [; it has been merged into AC_PROG_CC])]) + +AC_DEFUN(AC_C_CHAR_UNSIGNED, +[AC_CACHE_CHECK(whether char is unsigned, ac_cv_c_char_unsigned, +[if test "$GCC" = yes; then + # GCC predefines this symbol on systems where it applies. +AC_EGREP_CPP(yes, +[#ifdef __CHAR_UNSIGNED__ + yes +#endif +], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no) +else +AC_TRY_RUN( +[/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +main() { + volatile char c = 255; exit(c < 0); +}], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no) +fi]) +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + AC_DEFINE(__CHAR_UNSIGNED__) +fi +]) + +AC_DEFUN(AC_C_LONG_DOUBLE, +[AC_CACHE_CHECK(for long double, ac_cv_c_long_double, +[if test "$GCC" = yes; then + ac_cv_c_long_double=yes +else +AC_TRY_RUN([int main() { +/* The Stardent Vistra knows sizeof(long double), but does not support it. */ +long double foo = 0.0; +/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ +exit(sizeof(long double) < sizeof(double)); }], +ac_cv_c_long_double=yes, ac_cv_c_long_double=no) +fi]) +if test $ac_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE) +fi +]) + +AC_DEFUN(AC_INT_16_BITS, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_SIZEOF(int)])dnl +AC_MSG_CHECKING(whether int is 16 bits) +AC_TRY_RUN([main() { exit(sizeof(int) != 2); }], + [AC_MSG_RESULT(yes) + AC_DEFINE(INT_16_BITS)], AC_MSG_RESULT(no)) +]) + +AC_DEFUN(AC_LONG_64_BITS, +[AC_OBSOLETE([$0], [; instead use AC_CHECK_SIZEOF(long)])dnl +AC_MSG_CHECKING(whether long int is 64 bits) +AC_TRY_RUN([main() { exit(sizeof(long int) != 8); }], + [AC_MSG_RESULT(yes) + AC_DEFINE(LONG_64_BITS)], AC_MSG_RESULT(no)) +]) + +AC_DEFUN(AC_C_BIGENDIAN, +[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian, +[ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/param.h>], [ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif], [# It does; now see whether it defined to BIG_ENDIAN or not. +AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/param.h>], [ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)]) +if test $ac_cv_c_bigendian = unknown; then +AC_TRY_RUN([main () { + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes) +fi]) +if test $ac_cv_c_bigendian = yes; then + AC_DEFINE(WORDS_BIGENDIAN) +fi +]) + +dnl Do nothing if the compiler accepts the inline keyword. +dnl Otherwise define inline to __inline__ or __inline if one of those work, +dnl otherwise define inline to be empty. +AC_DEFUN(AC_C_INLINE, +[AC_CACHE_CHECK([for inline], ac_cv_c_inline, +[ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + AC_TRY_COMPILE(, [} $ac_kw foo() {], [ac_cv_c_inline=$ac_kw; break]) +done +]) +case "$ac_cv_c_inline" in + inline | yes) ;; + no) AC_DEFINE(inline, ) ;; + *) AC_DEFINE_UNQUOTED(inline, $ac_cv_c_inline) ;; +esac +]) + +AC_DEFUN(AC_C_CONST, +[dnl This message is consistent in form with the other checking messages, +dnl and with the result message. +AC_CACHE_CHECK([for working const], ac_cv_c_const, +[AC_TRY_COMPILE(, +changequote(<<, >>)dnl +<< +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} +>>, +changequote([, ])dnl +ac_cv_c_const=yes, ac_cv_c_const=no)]) +if test $ac_cv_c_const = no; then + AC_DEFINE(const, ) +fi +]) + +AC_DEFUN(AC_C_STRINGIZE, [ +AC_REQUIRE([AC_PROG_CPP]) +AC_MSG_CHECKING([for preprocessor stringizing operator]) +AC_CACHE_VAL(ac_cv_c_stringize, +AC_EGREP_CPP([#teststring],[ +#define x(y) #y + +char *s = x(teststring); +], ac_cv_c_stringize=no, ac_cv_c_stringize=yes)) +if test "${ac_cv_c_stringize}" = yes +then + AC_DEFINE(HAVE_STRINGIZE) +fi +AC_MSG_RESULT([${ac_cv_c_stringize}]) +])dnl + +define(AC_ARG_ARRAY, +[errprint(__file__:__line__: [$0] has been removed; don't do unportable things with arguments +)m4exit(4)]) + +dnl Check the object extension used by the compiler: typically .o or +dnl .obj. If this is called, some other behaviour will change, +dnl determined by ac_objext. +AC_DEFUN(AC_OBJEXT, +[AC_MSG_CHECKING([for object suffix]) +AC_CACHE_VAL(ac_cv_objext, +[rm -f conftest* +echo 'int i = 1;' > conftest.$ac_ext +if AC_TRY_EVAL(ac_compile); then + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + AC_MSG_ERROR([installation or configuration problem; compiler does not work]) +fi +rm -f conftest*]) +AC_MSG_RESULT($ac_cv_objext) +OBJEXT=$ac_cv_objext +ac_objext=$ac_cv_objext +AC_SUBST(OBJEXT)]) + +dnl Determine the linker flags (e.g. `-L' and `-l') for the Fortran 77 +dnl intrinsic and run-time libraries that are required to successfully +dnl link a Fortran 77 program or shared library. The output variable +dnl FLIBS is set to these flags. +dnl +dnl This macro is intended to be used in those situations when it is +dnl necessary to mix, e.g. C++ and Fortran 77, source code into a single +dnl program or shared library. +dnl +dnl For example, if object files from a C++ and Fortran 77 compiler must +dnl be linked together, then the C++ compiler/linker must be used for +dnl linking (since special C++-ish things need to happen at link time +dnl like calling global constructors, instantiating templates, enabling +dnl exception support, etc.). +dnl +dnl However, the Fortran 77 intrinsic and run-time libraries must be +dnl linked in as well, but the C++ compiler/linker doesn't know how to +dnl add these Fortran 77 libraries. Hence, the macro +dnl `AC_F77_LIBRARY_LDFLAGS' was created to determine these Fortran 77 +dnl libraries. +dnl +dnl This macro was packaged in its current form by Matthew D. Langston +dnl <langston@SLAC.Stanford.EDU>. However, nearly all of this macro +dnl came from the `OCTAVE_FLIBS' macro in `octave-2.0.13/aclocal.m4', +dnl and full credit should go to John W. Eaton for writing this +dnl extremely useful macro. Thank you John. +dnl +dnl AC_F77_LIBRARY_LDFLAGS() +AC_DEFUN(AC_F77_LIBRARY_LDFLAGS, +[AC_MSG_CHECKING([for Fortran 77 libraries]) +AC_REQUIRE([AC_PROG_F77]) +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_VAL(ac_cv_flibs, +[changequote(, )dnl +dnl Write a minimal program and compile it with -v. I don't know what +dnl to do if your compiler doesn't have -v... +echo " END" > conftest.f +foutput=`${F77} -v -o conftest conftest.f 2>&1` +dnl +dnl The easiest thing to do for xlf output is to replace all the commas +dnl with spaces. Try to only do that if the output is really from xlf, +dnl since doing that causes problems on other systems. +dnl +xlf_p=`echo $foutput | grep xlfentry` +if test -n "$xlf_p"; then + foutput=`echo $foutput | sed 's/,/ /g'` +fi +dnl +ld_run_path=`echo $foutput | \ + sed -n -e 's/^.*LD_RUN_PATH *= *\([^ ]*\).*/\1/p'` +dnl +dnl We are only supposed to find this on Solaris systems... +dnl Uh, the run path should be absolute, shouldn't it? +dnl +case "$ld_run_path" in + /*) + if test "$ac_cv_prog_gcc" = yes; then + ld_run_path="-Xlinker -R -Xlinker $ld_run_path" + else + ld_run_path="-R $ld_run_path" + fi + ;; + *) + ld_run_path= + ;; +esac +dnl +flibs= +lflags= +dnl +dnl If want_arg is set, we know we want the arg to be added to the list, +dnl so we don't have to examine it. +dnl +want_arg= +dnl +for arg in $foutput; do + old_want_arg=$want_arg + want_arg= +dnl +dnl None of the options that take arguments expect the argument to +dnl start with a -, so pretend we didn't see anything special. +dnl + if test -n "$old_want_arg"; then + case "$arg" in + -*) + old_want_arg= + ;; + esac + fi + case "$old_want_arg" in + '') + case $arg in + /*.a) + exists=false + for f in $lflags; do + if test x$arg = x$f; then + exists=true + fi + done + if $exists; then + arg= + else + lflags="$lflags $arg" + fi + ;; + -bI:*) + exists=false + for f in $lflags; do + if test x$arg = x$f; then + exists=true + fi + done + if $exists; then + arg= + else + if test "$ac_cv_prog_gcc" = yes; then + lflags="$lflags -Xlinker $arg" + else + lflags="$lflags $arg" + fi + fi + ;; + -lang* | -lcrt0.o | -lc | -lgcc) + arg= + ;; + -[lLR]) + want_arg=$arg + arg= + ;; + -[lLR]*) + exists=false + for f in $lflags; do + if test x$arg = x$f; then + exists=true + fi + done + if $exists; then + arg= + else + case "$arg" in + -lkernel32) + case "$canonical_host_type" in + *-*-cygwin*) + arg= + ;; + *) + lflags="$lflags $arg" + ;; + esac + ;; + -lm) + ;; + *) + lflags="$lflags $arg" + ;; + esac + fi + ;; + -u) + want_arg=$arg + arg= + ;; + -Y) + want_arg=$arg + arg= + ;; + *) + arg= + ;; + esac + ;; + -[lLR]) + arg="$old_want_arg $arg" + ;; + -u) + arg="-u $arg" + ;; + -Y) +dnl +dnl Should probably try to ensure unique directory options here too. +dnl This probably only applies to Solaris systems, and then will only +dnl work with gcc... +dnl + arg=`echo $arg | sed -e 's%^P,%%'` + SAVE_IFS=$IFS + IFS=: + list= + for elt in $arg; do + list="$list -L$elt" + done + IFS=$SAVE_IFS + arg="$list" + ;; + esac +dnl + if test -n "$arg"; then + flibs="$flibs $arg" + fi +done +if test -n "$ld_run_path"; then + flibs_result="$ld_run_path $flibs" +else + flibs_result="$flibs" +fi +changequote([, ])dnl +ac_cv_flibs="$flibs_result"]) +FLIBS="$ac_cv_flibs" +AC_SUBST(FLIBS)dnl +AC_MSG_RESULT($FLIBS) +]) + + +dnl ### Checks for operating system services + + +AC_DEFUN(AC_SYS_INTERPRETER, +[# Pull the hash mark out of the macro call to avoid m4 problems. +ac_msg="whether #! works in shell scripts" +AC_CACHE_CHECK($ac_msg, ac_cv_sys_interpreter, +[echo '#! /bin/cat +exit 69 +' > conftest +chmod u+x conftest +(SHELL=/bin/sh; export SHELL; ./conftest >/dev/null) +if test $? -ne 69; then + ac_cv_sys_interpreter=yes +else + ac_cv_sys_interpreter=no +fi +rm -f conftest]) +interpval="$ac_cv_sys_interpreter" +]) + +define(AC_HAVE_POUNDBANG, +[errprint(__file__:__line__: [$0 has been replaced by AC_SYS_INTERPRETER, taking no arguments +])m4exit(4)]) + +AC_DEFUN(AC_SYS_LONG_FILE_NAMES, +[AC_CACHE_CHECK(for long file names, ac_cv_sys_long_file_names, +[ac_cv_sys_long_file_names=yes +# Test for long file names in all the places we know might matter: +# . the current directory, where building will happen +# $prefix/lib where we will be installing things +# $exec_prefix/lib likewise +# eval it to expand exec_prefix. +# $TMPDIR if set, where it might want to write temporary files +# if $TMPDIR is not set: +# /tmp where it might want to write temporary files +# /var/tmp likewise +# /usr/tmp likewise +if test -n "$TMPDIR" && test -d "$TMPDIR" && test -w "$TMPDIR"; then + ac_tmpdirs="$TMPDIR" +else + ac_tmpdirs='/tmp /var/tmp /usr/tmp' +fi +for ac_dir in . $ac_tmpdirs `eval echo $prefix/lib $exec_prefix/lib` ; do + test -d $ac_dir || continue + test -w $ac_dir || continue # It is less confusing to not echo anything here. + (echo 1 > $ac_dir/conftest9012345) 2>/dev/null + (echo 2 > $ac_dir/conftest9012346) 2>/dev/null + val=`cat $ac_dir/conftest9012345 2>/dev/null` + if test ! -f $ac_dir/conftest9012345 || test "$val" != 1; then + ac_cv_sys_long_file_names=no + rm -f $ac_dir/conftest9012345 $ac_dir/conftest9012346 2>/dev/null + break + fi + rm -f $ac_dir/conftest9012345 $ac_dir/conftest9012346 2>/dev/null +done]) +if test $ac_cv_sys_long_file_names = yes; then + AC_DEFINE(HAVE_LONG_FILE_NAMES) +fi +]) + +AC_DEFUN(AC_SYS_RESTARTABLE_SYSCALLS, +[AC_CACHE_CHECK(for restartable system calls, ac_cv_sys_restartable_syscalls, +[AC_TRY_RUN( +[/* Exit 0 (true) if wait returns something other than -1, + i.e. the pid of the child, which means that wait was restarted + after getting the signal. */ +#include <sys/types.h> +#include <signal.h> +ucatch (isig) { } +main () { + int i = fork (), status; + if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); exit (0); } + signal (SIGINT, ucatch); + status = wait(&i); + if (status == -1) wait(&i); + exit (status == -1); +} +], ac_cv_sys_restartable_syscalls=yes, ac_cv_sys_restartable_syscalls=no)]) +if test $ac_cv_sys_restartable_syscalls = yes; then + AC_DEFINE(HAVE_RESTARTABLE_SYSCALLS) +fi +]) + +AC_DEFUN(AC_PATH_X, +[AC_REQUIRE_CPP()dnl Set CPP; we run AC_PATH_X_DIRECT conditionally. +# If we find X, set shell vars x_includes and x_libraries to the +# paths, otherwise set no_x=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +# --without-x overrides everything else, but does not touch the cache. +AC_MSG_CHECKING(for X) + +AC_ARG_WITH(x, [ --with-x use the X Window System]) +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else +AC_CACHE_VAL(ac_cv_have_x, +[# One or both of the vars are not set, and there is no cached value. +ac_x_includes=NO ac_x_libraries=NO +AC_PATH_X_XMKMF +AC_PATH_X_DIRECT +if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi])dnl + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + AC_MSG_RESULT($have_x) + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + AC_MSG_RESULT([libraries $x_libraries, headers $x_includes]) +fi +]) + +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN(AC_PATH_X_XMKMF, +[rm -fr conftestdir +if mkdir conftestdir; then + cd conftestdir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +EOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case "$ac_im_incroot" in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; + esac + case "$ac_im_usrlibdir" in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; + esac + fi + cd .. + rm -fr conftestdir +fi +]) + +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN(AC_PATH_X_DIRECT, +[if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +AC_TRY_CPP([#include <$x_direct_test_include>], +[# We can compile using X headers with no special include directory. +ac_x_includes=], +[# Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done]) +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +AC_TRY_LINK(, [${x_direct_test_function}()], +[LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries=], +[LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do +dnl Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done]) +fi # $ac_x_libraries = NO +]) + +dnl Find additional X libraries, magic flags, etc. +AC_DEFUN(AC_PATH_XTRA, +[AC_REQUIRE([AC_PATH_X])dnl +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + AC_DEFINE(X_DISPLAY_MISSING) + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" +dnl FIXME banish uname from this macro! + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case "`(uname -sr) 2>/dev/null`" in + "SunOS 5"*) + AC_MSG_CHECKING(whether -R must be followed by a space) + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" + AC_TRY_LINK(, , ac_R_nospace=yes, ac_R_nospace=no) + if test $ac_R_nospace = yes; then + AC_MSG_RESULT(no) + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + AC_TRY_LINK(, , ac_R_space=yes, ac_R_space=no) + if test $ac_R_space = yes; then + AC_MSG_RESULT(yes) + X_LIBS="$X_LIBS -R $x_libraries" + else + AC_MSG_RESULT(neither works) + fi + fi + LIBS="$ac_xsave_LIBS" + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And karl@cs.umb.edu says + # the Alpha needs dnet_stub (dnet does not exist). + AC_CHECK_LIB(dnet, dnet_ntoa, [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"]) + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + AC_CHECK_LIB(dnet_stub, dnet_ntoa, + [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"]) + fi + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to dickey@clark.net. + AC_CHECK_FUNC(gethostbyname) + if test $ac_cv_func_gethostbyname = no; then + AC_CHECK_LIB(nsl, gethostbyname, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl") + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says simon@lia.di.epfl.ch: it contains + # gethostby* variants that don't use the nameserver (or something). + # -lsocket must be given before -lnsl if both are needed. + # We assume that if connect needs -lnsl, so does gethostbyname. + AC_CHECK_FUNC(connect) + if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect, X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS", , + $X_EXTRA_LIBS) + fi + + # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. + AC_CHECK_FUNC(remove) + if test $ac_cv_func_remove = no; then + AC_CHECK_LIB(posix, remove, X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix") + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + AC_CHECK_FUNC(shmat) + if test $ac_cv_func_shmat = no; then + AC_CHECK_LIB(ipc, shmat, X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc") + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS="$LDFLAGS" + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. + AC_CHECK_LIB(ICE, IceConnectionNumber, + [X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"], , $X_EXTRA_LIBS) + LDFLAGS="$ac_save_LDFLAGS" + +fi +AC_SUBST(X_CFLAGS)dnl +AC_SUBST(X_PRE_LIBS)dnl +AC_SUBST(X_LIBS)dnl +AC_SUBST(X_EXTRA_LIBS)dnl +]) + +dnl The old Cygwin32 macro is deprecated. +AC_DEFUN(AC_CYGWIN32, +[AC_OBSOLETE([$0], [; instead use AC_CYGWIN])dnl +AC_CYGWIN]) + +dnl Check for Cygwin. This is a way to set the right value for +dnl EXEEXT. +AC_DEFUN(AC_CYGWIN, +[AC_CACHE_CHECK(for Cygwin environment, ac_cv_cygwin, +[AC_TRY_COMPILE(,[ +#ifndef __CYGWIN__ +#define __CYGWIN__ __CYGWIN32__ +#endif +return __CYGWIN__;], +ac_cv_cygwin=yes, ac_cv_cygwin=no) +rm -f conftest*]) +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes]) + +dnl Check for mingw32. This is another way to set the right value for +dnl EXEEXT. +AC_DEFUN(AC_MINGW32, +[AC_CACHE_CHECK(for mingw32 environment, ac_cv_mingw32, +[AC_TRY_COMPILE(,[return __MINGW32__;], +ac_cv_mingw32=yes, ac_cv_mingw32=no) +rm -f conftest*]) +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes]) + +dnl Check for the extension used for executables. This knows that we +dnl add .exe for Cygwin or mingw32. Otherwise, it compiles a test +dnl executable. If this is called, the executable extensions will be +dnl automatically used by link commands run by the configure script. +AC_DEFUN(AC_EXEEXT, +[AC_REQUIRE([AC_CYGWIN]) +AC_REQUIRE([AC_MINGW32]) +AC_MSG_CHECKING([for executable suffix]) +AC_CACHE_VAL(ac_cv_exeext, +[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe +else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if AC_TRY_EVAL(ac_link); then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + AC_MSG_ERROR([installation or configuration problem: compiler cannot create executables.]) + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no +fi]) +EXEEXT="" +test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} +AC_MSG_RESULT(${ac_cv_exeext}) +dnl Setting ac_exeext will implicitly change the ac_link command. +ac_exeext=$EXEEXT +AC_SUBST(EXEEXT)]) + + +dnl ### Checks for UNIX variants +dnl These are kludges which should be replaced by a single POSIX check. +dnl They aren't cached, to discourage their use. + + +AC_DEFUN(AC_AIX, +[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl +AC_BEFORE([$0], [AC_TRY_RUN])dnl +AC_MSG_CHECKING(for AIX) +AC_EGREP_CPP(yes, +[#ifdef _AIX + yes +#endif +], [AC_MSG_RESULT(yes); AC_DEFINE(_ALL_SOURCE)], AC_MSG_RESULT(no)) +]) + +AC_DEFUN(AC_MINIX, +[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl +AC_BEFORE([$0], [AC_TRY_RUN])dnl +AC_CHECK_HEADER(minix/config.h, MINIX=yes, MINIX=) +if test "$MINIX" = yes; then + AC_DEFINE(_POSIX_SOURCE) + AC_DEFINE(_POSIX_1_SOURCE, 2) + AC_DEFINE(_MINIX) +fi +]) + +AC_DEFUN(AC_ISC_POSIX, +[AC_REQUIRE([AC_PROG_CC])dnl +AC_BEFORE([$0], [AC_TRY_COMPILE])dnl +AC_BEFORE([$0], [AC_TRY_RUN])dnl +AC_MSG_CHECKING(for POSIXized ISC) +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION [/usr/include/sys/unistd.h] >/dev/null 2>&1 +then + AC_MSG_RESULT(yes) + ISC=yes # If later tests want to check for ISC. + AC_DEFINE(_POSIX_SOURCE) + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + AC_MSG_RESULT(no) + ISC= +fi +]) + +AC_DEFUN(AC_XENIX_DIR, +[AC_OBSOLETE([$0], [; instead use AC_HEADER_DIRENT])dnl +AC_REQUIRE([AC_DIR_HEADER])dnl +AC_MSG_CHECKING(for Xenix) +AC_EGREP_CPP(yes, +[#if defined(M_XENIX) && !defined(M_UNIX) + yes +#endif +], [AC_MSG_RESULT(yes); XENIX=yes], [AC_MSG_RESULT(no); XENIX=]) +if test "$XENIX" = yes; then + # Make sure -ldir precedes -lx. + test $ac_header_dirent = dirent.h && LIBS="-ldir $LIBS" + LIBS="$LIBS -lx" +fi +]) + +AC_DEFUN(AC_DYNIX_SEQ, +[AC_OBSOLETE([$0], [; instead use AC_FUNC_GETMNTENT])dnl +AC_CHECK_LIB(seq, getmntent, LIBS="-lseq $LIBS") +]) + +AC_DEFUN(AC_IRIX_SUN, +[AC_OBSOLETE([$0], [; instead use AC_FUNC_GETMNTENT or AC_CHECK_LIB(sun, getpwnam)])dnl +AC_CHECK_LIB(sun, getmntent, LIBS="-lsun $LIBS") +]) + +AC_DEFUN(AC_SCO_INTL, +[AC_OBSOLETE([$0], [; instead use AC_FUNC_STRFTIME])dnl +AC_CHECK_LIB(intl, strftime, LIBS="-lintl $LIBS") +]) diff --git a/build/autoconf/alloc.m4 b/build/autoconf/alloc.m4 new file mode 100644 index 0000000000..5a739a420c --- /dev/null +++ b/build/autoconf/alloc.m4 @@ -0,0 +1,57 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl Check for the existence of various allocation headers/functions +AC_DEFUN([MOZ_CHECK_ALLOCATOR],[ + +MALLOC_HEADERS="malloc.h malloc_np.h malloc/malloc.h sys/malloc.h" +MALLOC_H= + +for file in $MALLOC_HEADERS; do + MOZ_CHECK_HEADER($file, [MALLOC_H=$file]) + if test "$MALLOC_H" != ""; then + AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>) + break + fi +done + +MALLOC_USABLE_SIZE_CONST_PTR=const +if test -n "$HAVE_MALLOC_H"; then + AC_CACHE_CHECK([whether malloc_usable_size definition can use const argument], + moz_cv_malloc_usable_size_constness, + [AC_TRY_COMPILE([#include <malloc.h> + #include <stddef.h> + size_t malloc_usable_size(const void *ptr);], + [return malloc_usable_size(0);], + [moz_cv_malloc_usable_size_constness=yes], + [moz_cv_malloc_usable_size_constness=no])]) + if test "$moz_cv_malloc_usable_size_constness" = no ; then + MALLOC_USABLE_SIZE_CONST_PTR= + fi +fi +AC_DEFINE_UNQUOTED([MALLOC_USABLE_SIZE_CONST_PTR],[$MALLOC_USABLE_SIZE_CONST_PTR]) + + +dnl In newer bionic headers, valloc is built but not defined, +dnl so we check more carefully here. +AC_MSG_CHECKING([for valloc in malloc.h]) +AC_EGREP_HEADER(valloc, malloc.h, + AC_DEFINE(HAVE_VALLOC) + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no])) + +AC_MSG_CHECKING([for valloc in unistd.h]) +AC_EGREP_HEADER(valloc, unistd.h, + AC_DEFINE(HAVE_VALLOC) + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no])) + +AC_MSG_CHECKING([for _aligned_malloc in malloc.h]) +AC_EGREP_HEADER(_aligned_malloc, malloc.h, + AC_DEFINE(HAVE_ALIGNED_MALLOC) + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no])) + + +]) diff --git a/build/autoconf/altoptions.m4 b/build/autoconf/altoptions.m4 new file mode 100644 index 0000000000..3105de0065 --- /dev/null +++ b/build/autoconf/altoptions.m4 @@ -0,0 +1,72 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl altoptions.m4 - An alternative way of specifying command-line options. +dnl These macros are needed to support a menu-based configurator. +dnl This file also includes the macro, AM_READ_MYCONFIG, for reading +dnl the 'myconfig.m4' file. + +dnl Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com). + + +dnl MOZ_ARG_ENABLE_BOOL( NAME, HELP, IF-YES [, IF-NO [, ELSE]]) +dnl MOZ_ARG_DISABLE_BOOL( NAME, HELP, IF-NO [, IF-YES [, ELSE]]) +dnl MOZ_ARG_ENABLE_STRING( NAME, HELP, IF-SET [, ELSE]) +dnl MOZ_ARG_WITH_BOOL( NAME, HELP, IF-YES [, IF-NO [, ELSE]) +dnl MOZ_ARG_WITH_STRING( NAME, HELP, IF-SET [, ELSE]) +dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file + +define([MOZ_DIVERSION_ARGS], 12) + +AC_DEFUN([MOZ_ARG],[dnl +AC_DIVERT_PUSH(MOZ_DIVERSION_ARGS)dnl + '$1', +AC_DIVERT_POP()dnl +]) +AC_DEFUN([MOZ_AC_ARG_ENABLE],[MOZ_ARG([--enable-]translit([$1],[_],[-]))AC_ARG_ENABLE([$1], [$2], [$3], [$4])]) +AC_DEFUN([MOZ_AC_ARG_WITH],[MOZ_ARG([--with-]translit([$1],[_],[-]))AC_ARG_WITH([$1], [$2], [$3], [$4])]) + +dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE]) +AC_DEFUN([MOZ_TWO_STRING_TEST], +[if test "[$2]" = "[$3]"; then + ifelse([$4], , :, [$4]) + elif test "[$2]" = "[$5]"; then + ifelse([$6], , :, [$6]) + else + ifelse([$7], , + [AC_MSG_ERROR([Option, [$1], does not take an argument ([$2]).])], + [$7]) + fi]) + +dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]]) +AC_DEFUN([MOZ_ARG_ENABLE_BOOL], +[MOZ_AC_ARG_ENABLE([$1], [$2], + [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])], + [$5])]) + +dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]]) +AC_DEFUN([MOZ_ARG_DISABLE_BOOL], +[MOZ_AC_ARG_ENABLE([$1], [$2], + [MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])], + [$5])]) + +dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE]) +AC_DEFUN([MOZ_ARG_ENABLE_STRING], +[MOZ_AC_ARG_ENABLE([$1], [$2], [$3], [$4])]) + +dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]) +AC_DEFUN([MOZ_ARG_WITH_BOOL], +[MOZ_AC_ARG_WITH([$1], [$2], + [MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])], + [$5])]) + +dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE]) +AC_DEFUN([MOZ_ARG_WITH_STRING], +[MOZ_AC_ARG_WITH([$1], [$2], [$3], [$4])]) + +dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file +AC_DEFUN([MOZ_READ_MOZCONFIG], +[AC_REQUIRE([AC_INIT_BINSH])dnl +. $OLD_CONFIGURE_VARS +]) diff --git a/build/autoconf/android.m4 b/build/autoconf/android.m4 new file mode 100644 index 0000000000..95027ded9d --- /dev/null +++ b/build/autoconf/android.m4 @@ -0,0 +1,20 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +AC_DEFUN([MOZ_ANDROID_NDK], +[ + +case "$target" in +*-android*|*-linuxandroid*) + dnl $extra_android_flags will be set for us by Python configure. + dnl $_topsrcdir/build/android is a hack for versions of rustc < 1.68 + LDFLAGS="$extra_android_flags -L$_topsrcdir/build/android $LDFLAGS" + CPPFLAGS="$extra_android_flags $CPPFLAGS" + CFLAGS="-fno-short-enums $CFLAGS" + CXXFLAGS="-fno-short-enums $CXXFLAGS" + ASFLAGS="$extra_android_flags -DANDROID $ASFLAGS" + ;; +esac + +]) diff --git a/build/autoconf/arch.m4 b/build/autoconf/arch.m4 new file mode 100644 index 0000000000..45c671082d --- /dev/null +++ b/build/autoconf/arch.m4 @@ -0,0 +1,15 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +AC_DEFUN([MOZ_ARCH_OPTS], +[ +if test -n "$_ARM_FLAGS"; then + CFLAGS="$CFLAGS $_ARM_FLAGS" + CXXFLAGS="$CXXFLAGS $_ARM_FLAGS" + ASFLAGS="$ASFLAGS $_ARM_FLAGS" + if test -n "$_THUMB_FLAGS"; then + LDFLAGS="$LDFLAGS $_THUMB_FLAGS" + fi +fi +]) diff --git a/build/autoconf/autoconf.m4 b/build/autoconf/autoconf.m4 new file mode 100644 index 0000000000..dde59ab380 --- /dev/null +++ b/build/autoconf/autoconf.m4 @@ -0,0 +1,28 @@ +dnl Driver that loads the Autoconf macro files. +dnl Requires GNU m4. +dnl This file is part of Autoconf. +dnl Copyright (C) 1994 Free Software Foundation, Inc. +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl Written by David MacKenzie. +dnl +include(acgeneral.m4)dnl +builtin(include, acspecific.m4)dnl +builtin(include, acoldnames.m4)dnl +dnl Do not sinclude acsite.m4 here, because it may not be installed +dnl yet when Autoconf is frozen. +dnl Do not sinclude ./aclocal.m4 here, to prevent it from being frozen. diff --git a/build/autoconf/autoconf.sh b/build/autoconf/autoconf.sh new file mode 100644 index 0000000000..ceb8a25b00 --- /dev/null +++ b/build/autoconf/autoconf.sh @@ -0,0 +1,158 @@ +#! @SHELL@ +# autoconf -- create `configure' using m4 macros +# Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# If given no args, create `configure' from template file `configure.in'. +# With one arg, create a configure script on standard output from +# the given template file. + +usage="\ +Usage: autoconf [-h] [--help] [-m dir] [--macrodir=dir] + [-l dir] [--localdir=dir] [--version] [template-file]" + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +: ${AC_MACRODIR=@datadir@} +: ${M4=@M4@} +: ${AWK=@AWK@} +case "${M4}" in +/*) # Handle the case that m4 has moved since we were configured. + # It may have been found originally in a build directory. + test -f "${M4}" || M4=m4 ;; +esac + +: ${TMPDIR=/tmp} +tmpout=${TMPDIR}/acout.$$ +localdir= +show_version=no + +while test $# -gt 0 ; do + case "${1}" in + -h | --help | --h* ) + echo "${usage}" 1>&2; exit 0 ;; + --localdir=* | --l*=* ) + localdir="`echo \"${1}\" | sed -e 's/^[^=]*=//'`" + shift ;; + -l | --localdir | --l*) + shift + test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } + localdir="${1}" + shift ;; + --macrodir=* | --m*=* ) + AC_MACRODIR="`echo \"${1}\" | sed -e 's/^[^=]*=//'`" + shift ;; + -m | --macrodir | --m* ) + shift + test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } + AC_MACRODIR="${1}" + shift ;; + --version | --v* ) + show_version=yes; shift ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "${usage}" 1>&2; exit 1 ;; + * ) + break ;; + esac +done + +if test $show_version = yes; then + version=`sed -n 's/define.AC_ACVERSION.[ ]*\([0-9.]*\).*/\1/p' \ + $AC_MACRODIR/acgeneral.m4` + echo "Autoconf version $version" + exit 0 +fi + +case $# in + 0) infile=configure.in ;; + 1) infile="$1" ;; + *) echo "$usage" >&2; exit 1 ;; +esac + +trap 'rm -f $tmpin $tmpout; exit 1' 1 2 15 + +tmpin=${TMPDIR}/acin.$$ # Always set this, to avoid bogus errors from some rm's. +if test z$infile = z-; then + infile=$tmpin + cat > $infile +elif test ! -r "$infile"; then + echo "autoconf: ${infile}: No such file or directory" >&2 + exit 1 +fi + +if test -n "$localdir"; then + use_localdir="-I$localdir -DAC_LOCALDIR=$localdir" +else + use_localdir= +fi + +# Use the frozen version of Autoconf if available. +r= f= +# Some non-GNU m4's don't reject the --help option, so give them /dev/null. +case `$M4 --help < /dev/null 2>&1` in +*reload-state*) test -r $AC_MACRODIR/autoconf.m4f && { r=--reload f=f; } ;; +*traditional*) ;; +*) echo Autoconf requires GNU m4 1.1 or later >&2; rm -f $tmpin; exit 1 ;; +esac + +$M4 -I$AC_MACRODIR $use_localdir $r autoconf.m4$f $infile > $tmpout || + { rm -f $tmpin $tmpout; exit 2; } + +# You could add your own prefixes to pattern if you wanted to check for +# them too, e.g. pattern='\(AC_\|ILT_\)', except that UNIX sed doesn't do +# alternation. +pattern="AC_" + +status=0 +if grep "^[^#]*${pattern}" $tmpout > /dev/null 2>&1; then + echo "autoconf: Undefined macros:" >&2 + sed -n "s/^[^#]*\\(${pattern}[_A-Za-z0-9]*\\).*/\\1/p" $tmpout | + while read macro; do + grep -n "^[^#]*$macro" $infile /dev/null + test $? -eq 1 && echo >&2 "***BUG in Autoconf--please report*** $macro" + done | sort -u >&2 + status=1 +fi + +if test $# -eq 0; then + echo "This case should not be reached." + exit 1 +fi + +# Put the real line numbers into the output to make config.log more helpful. +$AWK ' +/__oline__/ { printf "%d:", NR + 1 } + { print } +' $tmpout | sed ' +/__oline__/s/^\([0-9][0-9]*\):\(.*\)__oline__/\2\1/ +' + +rm -f $tmpout + +exit $status diff --git a/build/autoconf/clang-plugin.m4 b/build/autoconf/clang-plugin.m4 new file mode 100644 index 0000000000..2bbb471e5b --- /dev/null +++ b/build/autoconf/clang-plugin.m4 @@ -0,0 +1,107 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +AC_DEFUN([MOZ_CONFIG_CLANG_PLUGIN], [ + +if test -n "$ENABLE_CLANG_PLUGIN"; then + dnl For some reason the llvm-config downloaded from clang.llvm.org for clang3_8 + dnl produces a -isysroot flag for a sysroot which might not ship when passed + dnl --cxxflags. We use sed to remove this argument so that builds work on OSX + dnl + dnl For a similar reason, we remove any -gcc-toolchain arguments, since the + dnl directories specified by such arguments might not exist on the current + dnl machine. + LLVM_CXXFLAGS=`$LLVM_CONFIG --cxxflags | sed -e 's/-isysroot [[^ ]]*//' -e 's/-gcc-toolchain [[^ ]]*//'` + + LLVM_LDFLAGS=`$LLVM_CONFIG --ldflags | tr '\n' ' '` + + if test "${HOST_OS_ARCH}" = "Darwin"; then + dnl We need to make sure that we use the symbols coming from the clang + dnl binary. In order to do this, we need to pass -flat_namespace and + dnl -undefined suppress to the linker. This makes sure that we link the + dnl symbols into the flat namespace provided by clang, and thus get + dnl access to all of the symbols which are undefined in our dylib as we + dnl are building it right now, and also that we don't fail the build + dnl due to undefined symbols (which will be provided by clang). + CLANG_LDFLAGS="-Wl,-flat_namespace -Wl,-undefined,suppress" + dnl We are loaded into clang, so we don't need to link to very many things, + dnl we just need to link to clangASTMatchers because it is not used by clang + CLANG_LDFLAGS="$CLANG_LDFLAGS `$LLVM_CONFIG --prefix`/lib/libclangASTMatchers.a" + dnl We need to remove -L/path/to/clang/lib from LDFLAGS to ensure that we + dnl don't accidentally link against the libc++ there which is a newer + dnl version that what our build machines have installed. + LLVM_LDFLAGS=`echo "$LLVM_LDFLAGS" | sed -E 's/-L[[^ ]]+\/clang\/lib//'` + elif test "${HOST_OS_ARCH}" = "WINNT"; then + CLANG_LDFLAGS="clangASTMatchers.lib clang.lib" + else + CLANG_LDFLAGS="-lclangASTMatchers" + fi + + if test -n "$CLANG_CL"; then + dnl The llvm-config coming with clang-cl may give us arguments in the + dnl /ARG form, which in msys will be interpreted as a path name. So we + dnl need to split the args and convert the leading slashes that we find + dnl into a dash. + LLVM_REPLACE_CXXFLAGS='' + for arg in $LLVM_CXXFLAGS; do + dnl The following expression replaces a leading slash with a dash. + dnl Also replace any backslashes with forward slash. + arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'` + LLVM_REPLACE_CXXFLAGS="$LLVM_REPLACE_CXXFLAGS $arg" + done + LLVM_CXXFLAGS="$LLVM_REPLACE_CXXFLAGS" + dnl We'll also want to replace `-std:` with `-Xclang -std=` so that + dnl LLVM_CXXFLAGS can correctly override the `-Xclang -std=` set by + dnl toolchain.configure. + LLVM_CXXFLAGS=`echo "$LLVM_CXXFLAGS"|sed -e 's/ \(-Xclang \|\)-std[[:=]]/ -Xclang -std=/'` + + LLVM_REPLACE_LDFLAGS='' + for arg in $LLVM_LDFLAGS; do + dnl The following expression replaces a leading slash with a dash. + dnl Also replace any backslashes with forward slash. + arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'` + LLVM_REPLACE_LDFLAGS="$LLVM_REPLACE_LDFLAGS $arg" + done + LLVM_LDFLAGS="$LLVM_REPLACE_LDFLAGS" + + CLANG_REPLACE_LDFLAGS='' + for arg in $CLANG_LDFLAGS; do + dnl The following expression replaces a leading slash with a dash. + dnl Also replace any backslashes with forward slash. + arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'` + CLANG_REPLACE_LDFLAGS="$CLANG_REPLACE_LDFLAGS $arg" + done + CLANG_LDFLAGS="$CLANG_REPLACE_LDFLAGS" + fi + + CLANG_PLUGIN_FLAGS="-Xclang -load -Xclang $CLANG_PLUGIN -Xclang -add-plugin -Xclang moz-check" + + AC_DEFINE(MOZ_CLANG_PLUGIN) +fi + +if test -n "$ENABLE_MOZSEARCH_PLUGIN"; then + if test -z "${ENABLE_CLANG_PLUGIN}"; then + AC_MSG_ERROR([Can't use mozsearch plugin without --enable-clang-plugin.]) + fi + + CLANG_PLUGIN_FLAGS="$CLANG_PLUGIN_FLAGS -Xclang -add-plugin -Xclang mozsearch-index" + + dnl Parameters are: srcdir, outdir (path where output JSON is stored), objdir. + CLANG_PLUGIN_FLAGS="$CLANG_PLUGIN_FLAGS -Xclang -plugin-arg-mozsearch-index -Xclang $_topsrcdir" + CLANG_PLUGIN_FLAGS="$CLANG_PLUGIN_FLAGS -Xclang -plugin-arg-mozsearch-index -Xclang $_objdir/mozsearch_index" + CLANG_PLUGIN_FLAGS="$CLANG_PLUGIN_FLAGS -Xclang -plugin-arg-mozsearch-index -Xclang $_objdir" + + AC_DEFINE(MOZ_MOZSEARCH_PLUGIN) +fi + +AC_SUBST_LIST(CLANG_PLUGIN_FLAGS) +AC_SUBST_LIST(LLVM_CXXFLAGS) +AC_SUBST_LIST(LLVM_LDFLAGS) +AC_SUBST_LIST(CLANG_LDFLAGS) + +AC_SUBST(ENABLE_CLANG_PLUGIN) +AC_SUBST(ENABLE_CLANG_PLUGIN_ALPHA) +AC_SUBST(ENABLE_MOZSEARCH_PLUGIN) + +]) diff --git a/build/autoconf/codeset.m4 b/build/autoconf/codeset.m4 new file mode 100644 index 0000000000..3a25c42961 --- /dev/null +++ b/build/autoconf/codeset.m4 @@ -0,0 +1,25 @@ +# codeset.m4 serial AM1 (gettext-0.10.40) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, + [AC_TRY_LINK([#include <langinfo.h>], + [char* cs = nl_langinfo(CODESET);], + am_cv_langinfo_codeset=yes, + am_cv_langinfo_codeset=no) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE(HAVE_LANGINFO_CODESET, 1, + [Define if you have <langinfo.h> and nl_langinfo(CODESET).]) + HAVE_LANGINFO_CODESET=1 + fi + AC_SUBST(HAVE_LANGINFO_CODESET) +]) diff --git a/build/autoconf/compiler-opts.m4 b/build/autoconf/compiler-opts.m4 new file mode 100644 index 0000000000..68960acbc1 --- /dev/null +++ b/build/autoconf/compiler-opts.m4 @@ -0,0 +1,198 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl Add compiler specific options + +dnl ============================================================================ +dnl C++ rtti +dnl We don't use it in the code, but it can be usefull for debugging, so give +dnl the user the option of enabling it. +dnl ============================================================================ +AC_DEFUN([MOZ_RTTI], +[ +if test -z "$_MOZ_USE_RTTI"; then + if test "$GNU_CC"; then + CXXFLAGS="$CXXFLAGS -fno-rtti" + else + case "$target" in + *-mingw*) + CXXFLAGS="$CXXFLAGS -GR-" + esac + fi +fi +]) + +dnl ======================================================== +dnl = +dnl = Debugging Options +dnl = +dnl ======================================================== +AC_DEFUN([MOZ_DEBUGGING_OPTS], +[ + +if test -z "$MOZ_DEBUG" -o -n "$MOZ_ASAN"; then + MOZ_NO_DEBUG_RTL=1 +fi + +AC_SUBST(MOZ_NO_DEBUG_RTL) + +if test -n "$MOZ_DEBUG"; then + if test -n "$COMPILE_ENVIRONMENT"; then + AC_MSG_CHECKING([for valid debug flags]) + _SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS" + AC_TRY_COMPILE([#include <stdio.h>], + [printf("Hello World\n");], + _results=yes, + _results=no) + AC_MSG_RESULT([$_results]) + if test "$_results" = "no"; then + AC_MSG_ERROR([These compiler flags are invalid: $MOZ_DEBUG_FLAGS]) + fi + CFLAGS=$_SAVE_CFLAGS + fi +fi +]) + +dnl A high level macro for selecting compiler options. +AC_DEFUN([MOZ_COMPILER_OPTS], +[ + MOZ_DEBUGGING_OPTS + MOZ_RTTI + +if test "$GNU_CC"; then + if test -z "$DEVELOPER_OPTIONS"; then + CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" + CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections" + fi + + CFLAGS="$CFLAGS -fno-math-errno" + CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno" +fi + +dnl ======================================================== +dnl = Identical Code Folding +dnl ======================================================== + +if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF" -a -z "$DEVELOPER_OPTIONS"; then + AC_CACHE_CHECK([whether the linker supports Identical Code Folding], + moz_cv_opt_ld_supports_icf, + [echo 'int foo() {return 42;}' \ + 'int bar() {return 42;}' \ + 'int main() {return foo() - bar();}' > conftest.${ac_ext} + # If the linker supports ICF, foo and bar symbols will have + # the same address + if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) && + test -s conftest${ac_exeext} && + $LLVM_OBJDUMP -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then + moz_cv_opt_ld_supports_icf=yes + else + moz_cv_opt_ld_supports_icf=no + fi + rm -rf conftest*]) + if test "$moz_cv_opt_ld_supports_icf" = yes; then + _SAVE_LDFLAGS="$LDFLAGS -Wl,--icf=safe" + LDFLAGS="$LDFLAGS -Wl,--icf=safe -Wl,--print-icf-sections" + AC_TRY_LINK([], [], + [LD_PRINT_ICF_SECTIONS=-Wl,--print-icf-sections], + [LD_PRINT_ICF_SECTIONS=]) + AC_SUBST([LD_PRINT_ICF_SECTIONS]) + LDFLAGS="$_SAVE_LDFLAGS" + fi +fi + +dnl ======================================================== +dnl = Detect static linkage of libstdc++ +dnl ======================================================== + +if test "$OS_TARGET" = Linux; then + +AC_CACHE_CHECK([whether we're trying to statically link with libstdc++], + moz_cv_opt_static_libstdcxx, + [moz_cv_opt_static_libstdcxx=no + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + cat > conftest.$ac_ext <<EOF +#include <iostream> +int main() { std::cout << 1; } +EOF + dnl This test is quite conservative: it assumes dynamic linkage if the compilation step fails or if + dnl the binary format is not supported. But it still detects basic issues. + if AC_TRY_EVAL([ac_link]) && test -s conftest${ac_exeext} && $LLVM_OBJDUMP --private-headers conftest${ac_exeext} 2> conftest.err 1> conftest.out + then + if test -s conftest.err + then : + elif grep -q -E 'NEEDED.*lib(std)?c\+\+' conftest.out + then : + else moz_cv_opt_static_libstdcxx=yes + fi + fi + AC_LANG_RESTORE + rm -f conftest* +]) +if test "$moz_cv_opt_static_libstdcxx" = "yes"; then + AC_MSG_ERROR([Firefox does not support linking statically with libstdc++]) +fi + +fi + +dnl ======================================================== +dnl = Automatically remove dead symbols +dnl ======================================================== + +SANCOV= +if test -n "$LIBFUZZER"; then + case "$LIBFUZZER_FLAGS" in + *-fsanitize-coverage*|*-fsanitize=fuzzer*) + SANCOV=1 + ;; + esac +fi + +if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$DEVELOPER_OPTIONS" -a -z "$MOZ_PROFILE_GENERATE" -a -z "$SANCOV"; then + if test -n "$MOZ_DEBUG_FLAGS"; then + dnl See bug 670659 + AC_CACHE_CHECK([whether removing dead symbols breaks debugging], + moz_cv_opt_gc_sections_breaks_debug_ranges, + [echo 'int foo() {return 42;}' \ + 'int bar() {return 1;}' \ + 'int main() {return foo();}' > conftest.${ac_ext} + if AC_TRY_COMMAND([${CC-cc} -o conftest.${ac_objext} $CFLAGS $MOZ_DEBUG_FLAGS -c conftest.${ac_ext} 1>&2]) && + AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS $MOZ_DEBUG_FLAGS -Wl,--gc-sections conftest.${ac_objext} $LIBS 1>&2]) && + test -s conftest${ac_exeext} -a -s conftest.${ac_objext}; then + if test "`$PYTHON3 -m mozbuild.configure.check_debug_ranges conftest.${ac_objext} conftest.${ac_ext}`" = \ + "`$PYTHON3 -m mozbuild.configure.check_debug_ranges conftest${ac_exeext} conftest.${ac_ext}`"; then + moz_cv_opt_gc_sections_breaks_debug_ranges=no + else + moz_cv_opt_gc_sections_breaks_debug_ranges=yes + fi + else + dnl We really don't expect to get here, but just in case + moz_cv_opt_gc_sections_breaks_debug_ranges="no, but it's broken in some other way" + fi + rm -rf conftest*]) + if test "$moz_cv_opt_gc_sections_breaks_debug_ranges" = no; then + DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections" + fi + else + DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections" + fi +fi + +if test "$GNU_CC$CLANG_CC"; then + case "${OS_TARGET}" in + Darwin|WASI) + # It's the default on those targets, and clang complains about -pie + # being unused if passed. + ;; + *) + MOZ_PROGRAM_LDFLAGS="$MOZ_PROGRAM_LDFLAGS -pie" + ;; + esac +fi + +AC_SUBST(MOZ_PROGRAM_LDFLAGS) + + +]) diff --git a/build/autoconf/config.guess b/build/autoconf/config.guess new file mode 100755 index 0000000000..7f76b6228f --- /dev/null +++ b/build/autoconf/config.guess @@ -0,0 +1,1754 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2022 Free Software Foundation, Inc. + +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2022-01-09' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess +# +# Please send patches to <config-patches@gnu.org>. + + +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2022 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# Just in case it came from the environment. +GUESS= + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD=$driver + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if test -f /.attbin/uname ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case $UNAME_SYSTEM in +Linux|GNU|GNU/*) + LIBC=unknown + + set_cc_for_build + cat <<-EOF > "$dummy.c" + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #elif defined(__GLIBC__) + LIBC=gnu + #else + #include <stdarg.h> + /* First heuristic to detect musl libc. */ + #ifdef __DEFINED_va_list + LIBC=musl + #endif + #endif + EOF + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "$cc_set_libc" + + # Second heuristic to detect musl libc. + if [ "$LIBC" = unknown ] && + command -v ldd >/dev/null && + ldd --version 2>&1 | grep -q ^musl; then + LIBC=musl + fi + + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + if [ "$LIBC" = unknown ]; then + LIBC=gnu + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + echo unknown)` + case $UNAME_MACHINE_ARCH in + aarch64eb) machine=aarch64_be-unknown ;; + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=$UNAME_MACHINE_ARCH-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case $UNAME_MACHINE_ARCH in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case $UNAME_MACHINE_ARCH in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case $UNAME_VERSION in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + GUESS=$machine-${os}${release}${abi-} + ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE + ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE + ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE + ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE + ;; + *:MidnightBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE + ;; + *:ekkoBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE + ;; + *:SolidBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE + ;; + *:OS108:*:*) + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE + ;; + macppc:MirBSD:*:*) + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE + ;; + *:MirBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE + ;; + *:Sortix:*:*) + GUESS=$UNAME_MACHINE-unknown-sortix + ;; + *:Twizzler:*:*) + GUESS=$UNAME_MACHINE-unknown-twizzler + ;; + *:Redox:*:*) + GUESS=$UNAME_MACHINE-unknown-redox + ;; + mips:OSF1:*.*) + GUESS=mips-dec-osf1 + ;; + alpha:OSF1:*:*) + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + trap '' 0 + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case $ALPHA_CPU_TYPE in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL + ;; + Amiga*:UNIX_System_V:4.0:*) + GUESS=m68k-unknown-sysv4 + ;; + *:[Aa]miga[Oo][Ss]:*:*) + GUESS=$UNAME_MACHINE-unknown-amigaos + ;; + *:[Mm]orph[Oo][Ss]:*:*) + GUESS=$UNAME_MACHINE-unknown-morphos + ;; + *:OS/390:*:*) + GUESS=i370-ibm-openedition + ;; + *:z/VM:*:*) + GUESS=s390-ibm-zvmoe + ;; + *:OS400:*:*) + GUESS=powerpc-ibm-os400 + ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + GUESS=arm-acorn-riscix$UNAME_RELEASE + ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + GUESS=arm-unknown-riscos + ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + GUESS=hppa1.1-hitachi-hiuxmpp + ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + case `(/bin/universe) 2>/dev/null` in + att) GUESS=pyramid-pyramid-sysv3 ;; + *) GUESS=pyramid-pyramid-bsd ;; + esac + ;; + NILE*:*:*:dcosx) + GUESS=pyramid-pyramid-svr4 + ;; + DRS?6000:unix:4.0:6*) + GUESS=sparc-icl-nx6 + ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) GUESS=sparc-icl-nx7 ;; + esac + ;; + s390x:SunOS:*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL + ;; + sun4H:SunOS:5.*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-hal-solaris2$SUN_REL + ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris2$SUN_REL + ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + GUESS=i386-pc-auroraux$UNAME_RELEASE + ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL + ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris3$SUN_REL + ;; + sun4*:SunOS:*:*) + case `/usr/bin/arch -k` in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` + GUESS=sparc-sun-sunos$SUN_REL + ;; + sun3*:SunOS:*:*) + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case `/bin/arch` in + sun3) + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; + sun4) + GUESS=sparc-sun-sunos$UNAME_RELEASE + ;; + esac + ;; + aushp:SunOS:*:*) + GUESS=sparc-auspex-sunos$UNAME_RELEASE + ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + GUESS=m68k-milan-mint$UNAME_RELEASE + ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + GUESS=m68k-hades-mint$UNAME_RELEASE + ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + GUESS=m68k-unknown-mint$UNAME_RELEASE + ;; + m68k:machten:*:*) + GUESS=m68k-apple-machten$UNAME_RELEASE + ;; + powerpc:machten:*:*) + GUESS=powerpc-apple-machten$UNAME_RELEASE + ;; + RISC*:Mach:*:*) + GUESS=mips-dec-mach_bsd4.3 + ;; + RISC*:ULTRIX:*:*) + GUESS=mips-dec-ultrix$UNAME_RELEASE + ;; + VAX*:ULTRIX*:*:*) + GUESS=vax-dec-ultrix$UNAME_RELEASE + ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + GUESS=clipper-intergraph-clix$UNAME_RELEASE + ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + GUESS=mips-mips-riscos$UNAME_RELEASE + ;; + Motorola:PowerMAX_OS:*:*) + GUESS=powerpc-motorola-powermax + ;; + Motorola:*:4.3:PL8-*) + GUESS=powerpc-harris-powermax + ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + GUESS=powerpc-harris-powermax + ;; + Night_Hawk:Power_UNIX:*:*) + GUESS=powerpc-harris-powerunix + ;; + m88k:CX/UX:7*:*) + GUESS=m88k-harris-cxux7 + ;; + m88k:*:4*:R4*) + GUESS=m88k-motorola-sysv4 + ;; + m88k:*:3*:R3*) + GUESS=m88k-motorola-sysv3 + ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 + then + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ + test "$TARGET_BINARY_INTERFACE"x = x + then + GUESS=m88k-dg-dgux$UNAME_RELEASE + else + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE + fi + else + GUESS=i586-dg-dgux$UNAME_RELEASE + fi + ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + GUESS=m88k-dolphin-sysv3 + ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + GUESS=m88k-motorola-sysv3 + ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + GUESS=m88k-tektronix-sysv3 + ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + GUESS=m68k-tektronix-bsd + ;; + *:IRIX*:*:*) + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` + GUESS=mips-sgi-irix$IRIX_REL + ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + GUESS=i386-ibm-aix + ;; + ia64:AIX:*:*) + if test -x /usr/bin/oslevel ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE + fi + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV + ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + GUESS=$SYSTEM_NAME + else + GUESS=rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + GUESS=rs6000-ibm-aix3.2.4 + else + GUESS=rs6000-ibm-aix3.2 + fi + ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if test -x /usr/bin/lslpp ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE + fi + GUESS=$IBM_ARCH-ibm-aix$IBM_REV + ;; + *:AIX:*:*) + GUESS=rs6000-ibm-aix + ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + GUESS=romp-ibm-bsd4.4 + ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to + ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + GUESS=rs6000-bull-bosx + ;; + DPX/2?00:B.O.S.:*:*) + GUESS=m68k-bull-sysv3 + ;; + 9000/[34]??:4.3bsd:1.*:*) + GUESS=m68k-hp-bsd + ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + GUESS=m68k-hp-bsd4.4 + ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + case $UNAME_MACHINE in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if test -x /usr/bin/getconf; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case $sc_cpu_version in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case $sc_kernel_bits in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if test "$HP_ARCH" = ""; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if test "$HP_ARCH" = hppa2.0w + then + set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + GUESS=$HP_ARCH-hp-hpux$HPUX_REV + ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + GUESS=ia64-hp-hpux$HPUX_REV + ;; + 3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + GUESS=unknown-hitachi-hiuxwe2 + ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + GUESS=hppa1.1-hp-bsd + ;; + 9000/8??:4.3bsd:*:*) + GUESS=hppa1.0-hp-bsd + ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + GUESS=hppa1.0-hp-mpeix + ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + GUESS=hppa1.1-hp-osf + ;; + hp8??:OSF1:*:*) + GUESS=hppa1.0-hp-osf + ;; + i*86:OSF1:*:*) + if test -x /usr/sbin/sysversion ; then + GUESS=$UNAME_MACHINE-unknown-osf1mk + else + GUESS=$UNAME_MACHINE-unknown-osf1 + fi + ;; + parisc*:Lites*:*:*) + GUESS=hppa1.1-hp-lites + ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + GUESS=c1-convex-bsd + ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + GUESS=c34-convex-bsd + ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + GUESS=c38-convex-bsd + ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + GUESS=c4-convex-bsd + ;; + CRAY*Y-MP:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=ymp-cray-unicos$CRAY_REL + ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=t90-cray-unicos$CRAY_REL + ;; + CRAY*T3E:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=alphaev5-cray-unicosmk$CRAY_REL + ;; + CRAY*SV1:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=sv1-cray-unicos$CRAY_REL + ;; + *:UNICOS/mp:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=craynv-cray-unicosmp$CRAY_REL + ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE + ;; + sparc*:BSD/OS:*:*) + GUESS=sparc-unknown-bsdi$UNAME_RELEASE + ;; + *:BSD/OS:*:*) + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE + ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi + else + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf + fi + ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case $UNAME_PROCESSOR in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL + ;; + i*:CYGWIN*:*) + GUESS=$UNAME_MACHINE-pc-cygwin + ;; + *:MINGW64*:*) + GUESS=$UNAME_MACHINE-pc-mingw64 + ;; + *:MINGW*:*) + GUESS=$UNAME_MACHINE-pc-mingw32 + ;; + *:MSYS*:*) + GUESS=$UNAME_MACHINE-pc-msys + ;; + i*:PW*:*) + GUESS=$UNAME_MACHINE-pc-pw32 + ;; + *:SerenityOS:*:*) + GUESS=$UNAME_MACHINE-pc-serenity + ;; + *:Interix*:*) + case $UNAME_MACHINE in + x86) + GUESS=i586-pc-interix$UNAME_RELEASE + ;; + authenticamd | genuineintel | EM64T) + GUESS=x86_64-unknown-interix$UNAME_RELEASE + ;; + IA64) + GUESS=ia64-unknown-interix$UNAME_RELEASE + ;; + esac ;; + i*:UWIN*:*) + GUESS=$UNAME_MACHINE-pc-uwin + ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + GUESS=x86_64-pc-cygwin + ;; + prep*:SunOS:5.*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=powerpcle-unknown-solaris2$SUN_REL + ;; + *:GNU:*:*) + # the GNU system + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL + ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC + ;; + *:Minix:*:*) + GUESS=$UNAME_MACHINE-unknown-minix + ;; + aarch64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi + else + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf + fi + fi + ;; + avr32*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + cris:Linux:*:*) + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; + crisv32:Linux:*:*) + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; + e2k:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + frv:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + hexagon:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + i*86:Linux:*:*) + GUESS=$UNAME_MACHINE-pc-linux-$LIBC + ;; + ia64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + k1om:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + m32r*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + m68*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + MIPS_ENDIAN=el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + MIPS_ENDIAN= + #else + MIPS_ENDIAN= + #endif + #endif +EOF + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` + eval "$cc_set_vars" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + openrisc*:Linux:*:*) + GUESS=or1k-unknown-linux-$LIBC + ;; + or32:Linux:*:* | or1k*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + padre:Linux:*:*) + GUESS=sparc-unknown-linux-$LIBC + ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + GUESS=hppa64-unknown-linux-$LIBC + ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; + *) GUESS=hppa-unknown-linux-$LIBC ;; + esac + ;; + ppc64:Linux:*:*) + GUESS=powerpc64-unknown-linux-$LIBC + ;; + ppc:Linux:*:*) + GUESS=powerpc-unknown-linux-$LIBC + ;; + ppc64le:Linux:*:*) + GUESS=powerpc64le-unknown-linux-$LIBC + ;; + ppcle:Linux:*:*) + GUESS=powerpcle-unknown-linux-$LIBC + ;; + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + s390:Linux:*:* | s390x:Linux:*:*) + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC + ;; + sh64*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + sh*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + tile*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + vax:Linux:*:*) + GUESS=$UNAME_MACHINE-dec-linux-$LIBC + ;; + x86_64:Linux:*:*) + set_cc_for_build + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_X32 >/dev/null + then + LIBCABI=${LIBC}x32 + fi + fi + GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI + ;; + xtensa*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + GUESS=i386-sequent-sysv4 + ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION + ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + GUESS=$UNAME_MACHINE-pc-os2-emx + ;; + i*86:XTS-300:*:STOP) + GUESS=$UNAME_MACHINE-unknown-stop + ;; + i*86:atheos:*:*) + GUESS=$UNAME_MACHINE-unknown-atheos + ;; + i*86:syllable:*:*) + GUESS=$UNAME_MACHINE-pc-syllable + ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + GUESS=i386-unknown-lynxos$UNAME_RELEASE + ;; + i*86:*DOS:*:*) + GUESS=$UNAME_MACHINE-pc-msdosdjgpp + ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL + else + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL + fi + ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL + else + GUESS=$UNAME_MACHINE-pc-sysv32 + fi + ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + GUESS=i586-pc-msdosdjgpp + ;; + Intel:Mach:3*:*) + GUESS=i386-pc-mach3 + ;; + paragon:*:*:*) + GUESS=i860-intel-osf1 + ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 + fi + ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + GUESS=m68010-convergent-sysv + ;; + mc68k:UNIX:SYSTEM5:3.51m) + GUESS=m68k-convergent-sysv + ;; + M680?0:D-NIX:5.3:*) + GUESS=m68k-diab-dnix + ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + GUESS=m68k-unknown-lynxos$UNAME_RELEASE + ;; + mc68030:UNIX_System_V:4.*:*) + GUESS=m68k-atari-sysv4 + ;; + TSUNAMI:LynxOS:2.*:*) + GUESS=sparc-unknown-lynxos$UNAME_RELEASE + ;; + rs6000:LynxOS:2.*:*) + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE + ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE + ;; + SM[BE]S:UNIX_SV:*:*) + GUESS=mips-dde-sysv$UNAME_RELEASE + ;; + RM*:ReliantUNIX-*:*:*) + GUESS=mips-sni-sysv4 + ;; + RM*:SINIX-*:*:*) + GUESS=mips-sni-sysv4 + ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + GUESS=$UNAME_MACHINE-sni-sysv4 + else + GUESS=ns32k-sni-sysv + fi + ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + GUESS=i586-unisys-sysv4 + ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + GUESS=hppa1.1-stratus-sysv4 + ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + GUESS=i860-stratus-sysv4 + ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + GUESS=$UNAME_MACHINE-stratus-vos + ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + GUESS=hppa1.1-stratus-vos + ;; + mc68*:A/UX:*:*) + GUESS=m68k-apple-aux$UNAME_RELEASE + ;; + news*:NEWS-OS:6*:*) + GUESS=mips-sony-newsos6 + ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if test -d /usr/nec; then + GUESS=mips-nec-sysv$UNAME_RELEASE + else + GUESS=mips-unknown-sysv$UNAME_RELEASE + fi + ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + GUESS=powerpc-be-beos + ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + GUESS=powerpc-apple-beos + ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + GUESS=i586-pc-beos + ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + GUESS=i586-pc-haiku + ;; + x86_64:Haiku:*:*) + GUESS=x86_64-unknown-haiku + ;; + SX-4:SUPER-UX:*:*) + GUESS=sx4-nec-superux$UNAME_RELEASE + ;; + SX-5:SUPER-UX:*:*) + GUESS=sx5-nec-superux$UNAME_RELEASE + ;; + SX-6:SUPER-UX:*:*) + GUESS=sx6-nec-superux$UNAME_RELEASE + ;; + SX-7:SUPER-UX:*:*) + GUESS=sx7-nec-superux$UNAME_RELEASE + ;; + SX-8:SUPER-UX:*:*) + GUESS=sx8-nec-superux$UNAME_RELEASE + ;; + SX-8R:SUPER-UX:*:*) + GUESS=sx8r-nec-superux$UNAME_RELEASE + ;; + SX-ACE:SUPER-UX:*:*) + GUESS=sxace-nec-superux$UNAME_RELEASE + ;; + Power*:Rhapsody:*:*) + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE + ;; + *:Rhapsody:*:*) + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE + ;; + arm64:Darwin:*:*) + GUESS=aarch64-apple-darwin$UNAME_RELEASE + ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE + ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE + ;; + *:QNX:*:4*) + GUESS=i386-pc-qnx + ;; + NEO-*:NONSTOP_KERNEL:*:*) + GUESS=neo-tandem-nsk$UNAME_RELEASE + ;; + NSE-*:NONSTOP_KERNEL:*:*) + GUESS=nse-tandem-nsk$UNAME_RELEASE + ;; + NSR-*:NONSTOP_KERNEL:*:*) + GUESS=nsr-tandem-nsk$UNAME_RELEASE + ;; + NSV-*:NONSTOP_KERNEL:*:*) + GUESS=nsv-tandem-nsk$UNAME_RELEASE + ;; + NSX-*:NONSTOP_KERNEL:*:*) + GUESS=nsx-tandem-nsk$UNAME_RELEASE + ;; + *:NonStop-UX:*:*) + GUESS=mips-compaq-nonstopux + ;; + BS2000:POSIX*:*:*) + GUESS=bs2000-siemens-sysv + ;; + DS/*:UNIX_System_V:*:*) + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE + ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "${cputype-}" = 386; then + UNAME_MACHINE=i386 + elif test "x${cputype-}" != x; then + UNAME_MACHINE=$cputype + fi + GUESS=$UNAME_MACHINE-unknown-plan9 + ;; + *:TOPS-10:*:*) + GUESS=pdp10-unknown-tops10 + ;; + *:TENEX:*:*) + GUESS=pdp10-unknown-tenex + ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + GUESS=pdp10-dec-tops20 + ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + GUESS=pdp10-xkl-tops20 + ;; + *:TOPS-20:*:*) + GUESS=pdp10-unknown-tops20 + ;; + *:ITS:*:*) + GUESS=pdp10-unknown-its + ;; + SEI:*:*:SEIUX) + GUESS=mips-sei-seiux$UNAME_RELEASE + ;; + *:DragonFly:*:*) + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL + ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case $UNAME_MACHINE in + A*) GUESS=alpha-dec-vms ;; + I*) GUESS=ia64-dec-vms ;; + V*) GUESS=vax-dec-vms ;; + esac ;; + *:XENIX:*:SysV) + GUESS=i386-pc-xenix + ;; + i*86:skyos:*:*) + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL + ;; + i*86:rdos:*:*) + GUESS=$UNAME_MACHINE-pc-rdos + ;; + i*86:Fiwix:*:*) + GUESS=$UNAME_MACHINE-pc-fiwix + ;; + *:AROS:*:*) + GUESS=$UNAME_MACHINE-unknown-aros + ;; + x86_64:VMkernel:*:*) + GUESS=$UNAME_MACHINE-unknown-esx + ;; + amd64:Isilon\ OneFS:*:*) + GUESS=x86_64-unknown-onefs + ;; + *:Unleashed:*:*) + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE + ;; +esac + +# Do we have a guess based on uname results? +if test "x$GUESS" != x; then + echo "$GUESS" + exit +fi + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" <<EOF +#ifdef _SEQUENT_ +#include <sys/types.h> +#include <sys/utsname.h> +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include <signal.h> +#if defined(_SIZE_T_) || defined(SIGLOST) +#include <sys/utsname.h> +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include <sys/param.h> +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + +echo "$0: unable to guess system type" >&2 + +case $UNAME_MACHINE:$UNAME_SYSTEM in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <<EOF + +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. +EOF + ;; +esac + +cat >&2 <<EOF + +This script (version $timestamp), has failed to recognize the +operating system you are using. If your script is old, overwrite *all* +copies of config.guess and config.sub with the latest versions from: + + https://git.savannah.gnu.org/cgit/config.git/plain/config.guess +and + https://git.savannah.gnu.org/cgit/config.git/plain/config.sub +EOF + +our_year=`echo $timestamp | sed 's,-.*,,'` +thisyear=`date +%Y` +# shellcheck disable=SC2003 +script_age=`expr "$thisyear" - "$our_year"` +if test "$script_age" -lt 3 ; then + cat >&2 <<EOF + +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF +fi + +exit 1 + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build/autoconf/config.status.m4 b/build/autoconf/config.status.m4 new file mode 100644 index 0000000000..41571a414b --- /dev/null +++ b/build/autoconf/config.status.m4 @@ -0,0 +1,154 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl For use in AC_SUBST replacement +define([MOZ_DIVERSION_SUBST], 11) + +dnl Replace AC_SUBST to store values in a format suitable for python. +dnl The necessary comma after the tuple can't be put here because it +dnl can mess around with things like: +dnl AC_SOMETHING(foo,AC_SUBST(),bar) +define([AC_SUBST], +[ifdef([AC_SUBST_SET_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_SET on the same variable ($1)])], +[ifdef([AC_SUBST_LIST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_LIST on the same variable ($1)])], +[ifdef([AC_SUBST_$1], , +[define([AC_SUBST_$1], )dnl +AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl + (''' $1 ''', r''' [$]$1 ''') +AC_DIVERT_POP()dnl +])])])])]) + +dnl Like AC_SUBST, but makes the value available as a set in python, +dnl with values got from the value of the environment variable, split on +dnl whitespaces. +define([AC_SUBST_SET], +[ifdef([AC_SUBST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_SET on the same variable ($1)])], +[ifdef([AC_SUBST_LIST_$1], [m4_fatal([Cannot use AC_SUBST_LIST and AC_SUBST_SET on the same variable ($1)])], +[ifdef([AC_SUBST_SET_$1], , +[define([AC_SUBST_SET_$1], )dnl +AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl + (''' $1 ''', unique_list(split(r''' [$]$1 '''))) +AC_DIVERT_POP()dnl +])])])])]) + +dnl Like AC_SUBST, but makes the value available as a list in python, +dnl with values got from the value of the environment variable, split on +dnl whitespaces. +define([AC_SUBST_LIST], +[ifdef([AC_SUBST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_LIST on the same variable ($1)])], +[ifdef([AC_SUBST_SET_$1], [m4_fatal([Cannot use AC_SUBST_SET and AC_SUBST_LIST on the same variable ($1)])], +[ifdef([AC_SUBST_LIST_$1], , +[define([AC_SUBST_LIST_$1], )dnl +AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl + (''' $1 ''', list(split(r''' [$]$1 '''))) +AC_DIVERT_POP()dnl +])])])])]) + +dnl Ignore AC_SUBSTs for variables we don't have use for but that autoconf +dnl itself exports. +define([AC_SUBST_CFLAGS], ) +define([AC_SUBST_CPPFLAGS], ) +define([AC_SUBST_CXXFLAGS], ) +define([AC_SUBST_FFLAGS], ) +define([AC_SUBST_DEFS], ) +define([AC_SUBST_LDFLAGS], ) +define([AC_SUBST_LIBS], ) + +dnl Wrap AC_DEFINE to store values in a format suitable for python. +dnl autoconf's AC_DEFINE still needs to be used to fill confdefs.h, +dnl which is #included during some compile checks. +dnl The necessary comma after the tuple can't be put here because it +dnl can mess around with things like: +dnl AC_SOMETHING(foo,AC_DEFINE(),bar) +define([_MOZ_AC_DEFINE], defn([AC_DEFINE])) +define([AC_DEFINE], +[cat >> confdefs.pytmp <<\EOF + (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 ')) +EOF +ifelse($#, 2, _MOZ_AC_DEFINE([$1], [$2]), $#, 3, _MOZ_AC_DEFINE([$1], [$2], [$3]),_MOZ_AC_DEFINE([$1]))dnl +]) + +dnl Wrap AC_DEFINE_UNQUOTED to store values in a format suitable for +dnl python. +define([_MOZ_AC_DEFINE_UNQUOTED], defn([AC_DEFINE_UNQUOTED])) +define([AC_DEFINE_UNQUOTED], +[cat >> confdefs.pytmp <<EOF + (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 ')) +EOF +ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl +]) + +dnl Replace AC_OUTPUT to create and call a python config.status +define([MOZ_CREATE_CONFIG_STATUS], +[dnl Used in all Makefile.in files +top_srcdir=$srcdir +AC_SUBST(top_srcdir) + +dnl Picked from autoconf 2.13 +trap '' 1 2 15 +AC_CACHE_SAVE + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 +: ${CONFIG_STATUS=./config.data} + +dnl We're going to need [ ] for python syntax. +changequote(<<<, >>>)dnl +echo creating $CONFIG_STATUS + +cat > $CONFIG_STATUS <<EOF + +dnl All defines and substs are stored with an additional space at the beginning +dnl and at the end of the string, to avoid any problem with values starting or +dnl ending with quotes. +defines = [ +EOF + +dnl confdefs.pytmp contains AC_DEFINEs, in the expected format, but +dnl lacks the final comma (see above). +sed 's/$/,/' confdefs.pytmp >> $CONFIG_STATUS +rm confdefs.pytmp confdefs.h + +cat >> $CONFIG_STATUS <<\EOF +] + +substs = [ +EOF + +dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the +dnl expected format, but lacks the final comma (see above). +sed 's/$/,/' >> $CONFIG_STATUS <<EOF +undivert(MOZ_DIVERSION_SUBST)dnl +EOF + +dnl Add in the output from the subconfigure script +for ac_subst_arg in $_subconfigure_ac_subst_args; do + variable='$'$ac_subst_arg + echo " (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS +done + +cat >> $CONFIG_STATUS <<\EOF +] + +flags = [ +undivert(MOZ_DIVERSION_ARGS)dnl +] +EOF + +changequote([, ]) +]) + +define([m4_fatal],[ +errprint([$1 +]) +m4exit(1) +]) + +define([AC_OUTPUT], [ifelse($#_$1, 1_, [MOZ_CREATE_CONFIG_STATUS() +MOZ_RUN_CONFIG_STATUS()], +[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])] +)]) + +define([AC_CONFIG_HEADER], +[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.]) +]) diff --git a/build/autoconf/config.sub b/build/autoconf/config.sub new file mode 100755 index 0000000000..dba16e84c7 --- /dev/null +++ b/build/autoconf/config.sub @@ -0,0 +1,1890 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2022 Free Software Foundation, Inc. + +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2022-01-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to <config-patches@gnu.org>. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2022 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Split fields of configuration type +# shellcheck disable=SC2162 +saved_IFS=$IFS +IFS="-" read field1 field2 field3 field4 <<EOF +$1 +EOF +IFS=$saved_IFS + +# Separate into logical components for further validation +case $1 in + *-*-*-*-*) + echo Invalid configuration \`"$1"\': more than four components >&2 + exit 1 + ;; + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 + ;; + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac + ;; + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac + ;; + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac + ;; +esac + +# Decode 1-component or ad-hoc basic machines +case $basic_machine in + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond + ;; + op50n) + cpu=hppa1.1 + vendor=oki + ;; + op60c) + cpu=hppa1.1 + vendor=oki + ;; + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple + ;; + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + basic_os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + basic_os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + basic_os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $basic_os in + irix*) + ;; + *) + basic_os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + basic_os=nextstep2 + ;; + *) + basic_os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + basic_os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` + ;; + + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read cpu vendor <<EOF +$basic_machine +EOF + IFS=$saved_IFS + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + cpu=$basic_machine + vendor=pc + ;; + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" + pc98) + cpu=i386 + vendor=pc + ;; + x64 | amd64) + cpu=x86_64 + vendor=pc + ;; + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown + ;; +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + basic_os=${basic_os:-unicosmp} + ;; + c90-unknown | c90-cray) + vendor=cray + basic_os=${Basic_os:-unicos} + ;; + fx80-unknown) + vendor=alliant + ;; + romp-unknown) + vendor=ibm + ;; + mmix-unknown) + vendor=knuth + ;; + microblaze-unknown | microblazeel-unknown) + vendor=xilinx + ;; + rs6000-unknown) + vendor=ibm + ;; + vax-unknown) + vendor=dec + ;; + pdp11-unknown) + vendor=dec + ;; + we32k-unknown) + vendor=att + ;; + cydra-unknown) + vendor=cydrome + ;; + i370-ibm*) + vendor=ibm + ;; + orion-unknown) + vendor=highlevel + ;; + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell + ;; + + # Here we normalize CPU types with a missing or matching vendor + armh-unknown | armh-alt) + cpu=armv7l + vendor=alt + basic_os=${basic_os:-linux-gnueabihf} + ;; + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + basic_os=${basic_os:-bosx} + ;; + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 + ;; + blackfin-*) + cpu=bfin + basic_os=linux + ;; + c54x-*) + cpu=tic54x + ;; + c55x-*) + cpu=tic55x + ;; + c6x-*) + cpu=tic6x + ;; + e500v[12]-*) + cpu=powerpc + basic_os=${basic_os}"spe" + ;; + mips3*-*) + cpu=mips64 + ;; + ms1-*) + cpu=mt + ;; + m68knommu-*) + cpu=m68k + basic_os=linux + ;; + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z + ;; + openrisc-*) + cpu=or32 + ;; + parisc-*) + cpu=hppa + basic_os=linux + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 + ;; + pentium4-*) + cpu=i786 + ;; + pc98-*) + cpu=i386 + ;; + ppc-* | ppcbe-*) + cpu=powerpc + ;; + ppcle-* | powerpclittle-*) + cpu=powerpcle + ;; + ppc64-*) + cpu=powerpc64 + ;; + ppc64le-* | powerpc64little-*) + cpu=powerpc64le + ;; + sb1-*) + cpu=mipsisa64sb1 + ;; + sb1el-*) + cpu=mipsisa64sb1el + ;; + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` + ;; + spur-*) + cpu=spur + ;; + strongarm-* | thumb-*) + cpu=arm + ;; + tx39-*) + cpu=mipstx39 + ;; + tx39el-*) + cpu=mipstx39el + ;; + x64-*) + cpu=x86_64 + ;; + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` + ;; + arm64-* | aarch64le-*) + cpu=aarch64 + ;; + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + basic_os=${basic_os:-elf} + ;; + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis + ;; + cris-* | etrax*-*) + cpu=cris + vendor=axis + ;; + crx-*) + basic_os=${basic_os:-elf} + ;; + neo-tandem) + cpu=neo + vendor=tandem + ;; + nse-tandem) + cpu=nse + vendor=tandem + ;; + nsr-tandem) + cpu=nsr + vendor=tandem + ;; + nsv-tandem) + cpu=nsv + vendor=tandem + ;; + nsx-tandem) + cpu=nsx + vendor=tandem + ;; + mipsallegrexel-sony) + cpu=mipsallegrexel + vendor=sony + ;; + tile*-*) + basic_os=${basic_os:-linux-gnu} + ;; + + *) + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb | arc32 | arc64 \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ + | rl78 | romp | rs6000 | rx \ + | s390 | s390x \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $vendor in + digital*) + vendor=dec + ;; + commodore*) + vendor=cbm + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if test x$basic_os != x +then + +# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read kernel os <<EOF +$basic_os +EOF + IFS=$saved_IFS + ;; + # Default OS when just kernel was specified + nto*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto|qnx|'` + ;; + linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|linux|gnu|'` + ;; + *) + kernel= + os=$basic_os + ;; +esac + +# Now, normalize the OS (knowing we just have one component, it's not a kernel, +# etc.) +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux + ;; + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) + os=`echo "$os" | sed -e 's|solaris1|sunos4|'` + ;; + solaris) + os=solaris2 + ;; + unixware*) + os=sysv4.2uw + ;; + # es1800 is here to avoid being matched by es* (a different OS) + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'` + ;; + sco*v* | scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos + ;; + qnx*) + os=qnx + ;; + hiux*) + os=hiuxwe2 + ;; + lynx*178) + os=lynxos178 + ;; + lynx*5) + os=lynxos5 + ;; + lynxos*) + # don't get caught up in next wildcard + ;; + lynx*) + os=lynxos + ;; + mac[0-9]*) + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + opened*) + os=openedition + ;; + os400*) + os=os400 + ;; + sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` + ;; + sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` + ;; + wince*) + os=wince + ;; + utek*) + os=bsd + ;; + dynix*) + os=bsd + ;; + acis*) + os=aos + ;; + atheos*) + os=atheos + ;; + syllable*) + os=syllable + ;; + 386bsd) + os=bsd + ;; + ctix* | uts*) + os=sysv + ;; + nova*) + os=rtmk-nova + ;; + ns2) + os=nextstep2 + ;; + # Preserve the version number of sinix5. + sinix5.*) + os=`echo "$os" | sed -e 's|sinix|sysv|'` + ;; + sinix*) + os=sysv4 + ;; + tpf*) + os=tpf + ;; + triton*) + os=sysv3 + ;; + oss*) + os=sysv3 + ;; + svr4*) + os=sysv4 + ;; + svr3) + os=sysv3 + ;; + sysvr4) + os=sysv4 + ;; + ose*) + os=ose + ;; + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint + ;; + dicos*) + os=dicos + ;; + pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $cpu in + arm*) + os=eabi + ;; + *) + os=elf + ;; + esac + ;; + *) + # No normalization, but not necessarily accepted, that comes below. + ;; +esac + +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +kernel= +case $cpu-$vendor in + score-*) + os=elf + ;; + spu-*) + os=elf + ;; + *-acorn) + os=riscix1.2 + ;; + arm*-rebel) + kernel=linux + os=gnu + ;; + arm*-semi) + os=aout + ;; + c4x-* | tic4x-*) + os=coff + ;; + c8051-*) + os=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) + os=elf + ;; + tic54x-*) + os=coff + ;; + tic55x-*) + os=coff + ;; + tic6x-*) + os=coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=tops20 + ;; + pdp11-*) + os=none + ;; + *-dec | vax-*) + os=ultrix4.2 + ;; + m68*-apollo) + os=domain + ;; + i386-sun) + os=sunos4.0.2 + ;; + m68000-sun) + os=sunos3 + ;; + m68*-cisco) + os=aout + ;; + mep-*) + os=elf + ;; + mips*-cisco) + os=elf + ;; + mips*-*) + os=elf + ;; + or32-*) + os=coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=sysv3 + ;; + sparc-* | *-sun) + os=sunos4.1.1 + ;; + pru-*) + os=elf + ;; + *-be) + os=beos + ;; + *-ibm) + os=aix + ;; + *-knuth) + os=mmixware + ;; + *-wec) + os=proelf + ;; + *-winbond) + os=proelf + ;; + *-oki) + os=proelf + ;; + *-hp) + os=hpux + ;; + *-hitachi) + os=hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=sysv + ;; + *-cbm) + os=amigaos + ;; + *-dg) + os=dgux + ;; + *-dolphin) + os=sysv3 + ;; + m68k-ccur) + os=rtu + ;; + m88k-omron*) + os=luna + ;; + *-next) + os=nextstep + ;; + *-sequent) + os=ptx + ;; + *-crds) + os=unos + ;; + *-ns) + os=genix + ;; + i370-*) + os=mvs + ;; + *-gould) + os=sysv + ;; + *-highlevel) + os=bsd + ;; + *-encore) + os=bsd + ;; + *-sgi) + os=irix + ;; + *-siemens) + os=sysv4 + ;; + *-masscomp) + os=rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=uxpv + ;; + *-rom68k) + os=coff + ;; + *-*bug) + os=coff + ;; + *-apple) + os=macos + ;; + *-atari*) + os=mint + ;; + *-wrs) + os=vxworks + ;; + *) + os=none + ;; +esac + +fi + +# Now, validate our (potentially fixed-up) OS. +case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. + musl* | newlib* | relibc* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) + ;; + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ + | os9* | macos* | osx* | ios* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ + | fiwix* ) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + none) + ;; + *) + echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* ) + ;; + uclinux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) + vendor=acorn + ;; + *-sunos*) + vendor=sun + ;; + *-cnk* | *-aix*) + vendor=ibm + ;; + *-beos*) + vendor=be + ;; + *-hpux*) + vendor=hp + ;; + *-mpeix*) + vendor=hp + ;; + *-hiux*) + vendor=hitachi + ;; + *-unos*) + vendor=crds + ;; + *-dgux*) + vendor=dg + ;; + *-luna*) + vendor=omron + ;; + *-genix*) + vendor=ns + ;; + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) + vendor=ibm + ;; + s390-* | s390x-*) + vendor=ibm + ;; + *-ptx*) + vendor=sequent + ;; + *-tpf*) + vendor=ibm + ;; + *-vxsim* | *-vxworks* | *-windiss*) + vendor=wrs + ;; + *-aux*) + vendor=apple + ;; + *-hms*) + vendor=hitachi + ;; + *-mpw* | *-macos*) + vendor=apple + ;; + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) + vendor=atari + ;; + *-vos*) + vendor=stratus + ;; + esac + ;; +esac + +echo "$cpu-$vendor-${kernel:+$kernel-}$os" +exit + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build/autoconf/expandlibs.m4 b/build/autoconf/expandlibs.m4 new file mode 100644 index 0000000000..70bc153e66 --- /dev/null +++ b/build/autoconf/expandlibs.m4 @@ -0,0 +1,53 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +AC_DEFUN([MOZ_EXPAND_LIBS], +[ +dnl ======================================================== +dnl = +dnl = Check what kind of list files are supported by the +dnl = linker +dnl = +dnl ======================================================== + +AC_CACHE_CHECK(what kind of list files are supported by the linker, + moz_cv_expand_libs_list_style, + [echo "int main() {return 0;}" > conftest.${ac_ext} + dnl Because BFD ld doesn't work with LTO + linker scripts, we + dnl must pass the LTO CFLAGS to the compile command, and the LTO + dnl LDFLAGS to all subsequent link commands. + dnl https://sourceware.org/bugzilla/show_bug.cgi?id=23600 + if AC_TRY_COMMAND(${CC-cc} -o conftest.${OBJ_SUFFIX} -c $MOZ_LTO_CFLAGS $CFLAGS $CPPFLAGS conftest.${ac_ext} 1>&5) && test -s conftest.${OBJ_SUFFIX}; then + echo "INPUT(conftest.${OBJ_SUFFIX})" > conftest.list + if test "$CC_TYPE" = "clang-cl"; then + link="$LINKER -OUT:conftest${ac_exeext}" + else + link="${CC-cc} -o conftest${ac_exeext}" + fi + if AC_TRY_COMMAND($link $MOZ_LTO_LDFLAGS $LDFLAGS conftest.list $LIBS 1>&5) && test -s conftest${ac_exeext}; then + moz_cv_expand_libs_list_style=linkerscript + else + echo "conftest.${OBJ_SUFFIX}" > conftest.list + dnl -filelist is for the OS X linker. We need to try -filelist + dnl first because clang understands @file, but may pass an + dnl oversized argument list to the linker depending on the + dnl contents of @file. + if AC_TRY_COMMAND($link $MOZ_LTO_LDFLAGS $LDFLAGS [-Wl,-filelist,conftest.list] $LIBS 1>&5) && test -s conftest${ac_exeext}; then + moz_cv_expand_libs_list_style=filelist + elif AC_TRY_COMMAND($link $MOZ_LTO_LDFLAGS $LDFLAGS @conftest.list $LIBS 1>&5) && test -s conftest${ac_exeext}; then + moz_cv_expand_libs_list_style=list + else + AC_ERROR([Couldn't find one that works]) + fi + fi + else + dnl We really don't expect to get here, but just in case + AC_ERROR([couldn't compile a simple C file]) + fi + rm -rf conftest*]) + +EXPAND_LIBS_LIST_STYLE=$moz_cv_expand_libs_list_style +AC_SUBST(EXPAND_LIBS_LIST_STYLE) + +]) diff --git a/build/autoconf/hooks.m4 b/build/autoconf/hooks.m4 new file mode 100644 index 0000000000..84d58205c1 --- /dev/null +++ b/build/autoconf/hooks.m4 @@ -0,0 +1,31 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl Wrap AC_INIT_PREPARE to add the above trap. +define([_MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE])) +define([AC_INIT_PREPARE], +[_MOZ_AC_INIT_PREPARE($1) + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' +]) + +dnl Print error messages in config.log as well as stderr +define([AC_MSG_ERROR], +[{ echo "configure: error: $1" 1>&2; echo "configure: error: $1" 1>&5; exit 1; }]) + +dnl Divert AC_TRY_COMPILER to make ac_cv_prog_*_works actually cached. +dnl This will allow to just skip the test when python configure has set +dnl the value for us. But since ac_cv_prog_*_cross is calculated at the same +dnl time, and has a different meaning as in python configure, we only want to +dnl use its value to display whether a cross-compile is happening. We forbid +dnl configure tests that would rely on ac_cv_prog_*_cross autoconf meaning +dnl (being able to execute the product of compilation), which are already bad +dnl for cross compiles anyways, so it's a win to get rid of them. +define([_MOZ_AC_TRY_COMPILER], defn([AC_TRY_COMPILER])) +define([AC_TRY_COMPILER], [AC_CACHE_VAL($2, _MOZ_AC_TRY_COMPILER($1, $2, $3))]) + +define([AC_TRY_RUN], [m4_fatal([AC_TRY_RUN is forbidden])]) +define([AC_CHECK_FILE], [m4_fatal([AC_CHECK_FILE is forbidden])]) diff --git a/build/autoconf/install-sh b/build/autoconf/install-sh new file mode 100755 index 0000000000..a4be13e59f --- /dev/null +++ b/build/autoconf/install-sh @@ -0,0 +1,123 @@ +#!/bin/sh +# 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/. + + +# +# install - install a program, script, or datafile +# This comes from X11R5; it is not part of GNU. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +instcmd="$mvprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +fi + +if [ x"$dst" = x ] +then + echo "install: no destination specified" + exit 1 +fi + + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + +if [ -d $dst ] +then + dst="$dst"/`basename $src` +fi + +# Make a temp file name in the proper directory. + +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + +$doit $instcmd $src $dsttmp + +# and set any options; do chmod last to preserve setuid bits + +if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi +if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi +if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi +if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. + +$doit $rmcmd $dst +$doit $mvcmd $dsttmp $dst + + +exit 0 diff --git a/build/autoconf/mozheader.m4 b/build/autoconf/mozheader.m4 new file mode 100644 index 0000000000..e99e35a403 --- /dev/null +++ b/build/autoconf/mozheader.m4 @@ -0,0 +1,32 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]]) +AC_DEFUN([MOZ_CHECK_HEADER], +[ dnl Do the transliteration at runtime so arg 1 can be a shell variable. + ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` + AC_MSG_CHECKING([for $1]) + AC_CACHE_VAL(ac_cv_header_$ac_safe, + [ AC_TRY_COMPILE([$4 +#include <$1>], , + eval "ac_cv_header_$ac_safe=yes", + eval "ac_cv_header_$ac_safe=no") ]) + if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) + fi +]) + +dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]]) +AC_DEFUN([MOZ_CHECK_HEADERS], +[ for ac_hdr in $1 + do + MOZ_CHECK_HEADER($ac_hdr, + [ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3, [$4]) + done +]) diff --git a/build/autoconf/mozprog.m4 b/build/autoconf/mozprog.m4 new file mode 100644 index 0000000000..00e357a807 --- /dev/null +++ b/build/autoconf/mozprog.m4 @@ -0,0 +1,42 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +AC_DEFUN([MOZ_PROG_CHECKMSYS], +[AC_REQUIRE([AC_INIT_BINSH])dnl +if test `uname -s | grep -c "MINGW\|MSYS" 2>/dev/null` != "0"; then + msyshost=1 +fi +]) + +AC_DEFUN([MOZ_PATH_PROG], +[ AC_PATH_PROG($1,$2,$3,$4) + if test "$msyshost"; then + case "[$]$1" in + /*) + tmp_DIRNAME=`dirname "[$]$1"` + tmp_BASENAME=`basename "[$]$1"` + tmp_PWD=`cd "$tmp_DIRNAME" && pwd -W` + $1="$tmp_PWD/$tmp_BASENAME" + if test -e "[$]$1.exe"; then + $1="[$]$1.exe" + fi + esac + fi +]) + +AC_DEFUN([MOZ_PATH_PROGS], +[ AC_PATH_PROGS($1,$2,$3,$4) + if test "$msyshost"; then + case "[$]$1" in + /*) + tmp_DIRNAME=`dirname "[$]$1"` + tmp_BASENAME=`basename "[$]$1"` + tmp_PWD=`cd "$tmp_DIRNAME" && pwd -W` + $1="$tmp_PWD/$tmp_BASENAME" + if test -e "[$]$1.exe"; then + $1="[$]$1.exe" + fi + esac + fi +]) diff --git a/build/autoconf/sanitize.m4 b/build/autoconf/sanitize.m4 new file mode 100644 index 0000000000..becdf0295d --- /dev/null +++ b/build/autoconf/sanitize.m4 @@ -0,0 +1,143 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +AC_DEFUN([MOZ_CONFIG_SANITIZE], [ + +dnl ======================================================== +dnl = Use Address Sanitizer +dnl ======================================================== +if test -n "$MOZ_ASAN"; then + if test -n "$CLANG_CL"; then + # Look for the ASan runtime binary + if test "$TARGET_CPU" = "x86_64"; then + MOZ_CLANG_RT_ASAN_LIB=clang_rt.asan_dynamic-x86_64.dll + else + MOZ_CLANG_RT_ASAN_LIB=clang_rt.asan_dynamic-i386.dll + fi + # We use MOZ_PATH_PROG in order to get a Windows style path. + MOZ_PATH_PROG(MOZ_CLANG_RT_ASAN_LIB_PATH, $MOZ_CLANG_RT_ASAN_LIB) + if test -z "$MOZ_CLANG_RT_ASAN_LIB_PATH"; then + AC_MSG_ERROR([Couldn't find $MOZ_CLANG_RT_ASAN_LIB. It should be available in the same location as clang-cl.]) + fi + AC_SUBST(MOZ_CLANG_RT_ASAN_LIB_PATH) + # Suppressing errors in recompiled code. + if test "$OS_ARCH" = "WINNT"; then + CFLAGS="-fsanitize-blacklist=$_topsrcdir/build/sanitizers/asan_blacklist_win.txt $CFLAGS" + CXXFLAGS="-fsanitize-blacklist=$_topsrcdir/build/sanitizers/asan_blacklist_win.txt $CXXFLAGS" + fi + fi + ASAN_FLAGS="-fsanitize=address" + if test "$OS_TARGET" = Linux; then + # -fno-sanitize-address-globals-dead-stripping is used to work around + # https://github.com/rust-lang/rust/issues/113404 + # It forces clang not to use __asan_register_elf_globals/__asan_globals_registered, + # avoiding the conflict with rust. + ASAN_FLAGS="$ASAN_FLAGS -fno-sanitize-address-globals-dead-stripping" + fi + CFLAGS="$ASAN_FLAGS $CFLAGS" + CXXFLAGS="$ASAN_FLAGS $CXXFLAGS" + if test -z "$CLANG_CL"; then + LDFLAGS="-fsanitize=address -rdynamic $LDFLAGS" + fi + AC_DEFINE(MOZ_ASAN) + MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer) +fi +AC_SUBST(MOZ_ASAN) + +dnl ======================================================== +dnl = Use Memory Sanitizer +dnl ======================================================== +if test -n "$MOZ_MSAN"; then + CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $CFLAGS" + CXXFLAGS="-fsanitize=memory -fsanitize-memory-track-origins $CXXFLAGS" + if test -z "$CLANG_CL"; then + LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -rdynamic $LDFLAGS" + fi + AC_DEFINE(MOZ_MSAN) + MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer) +fi +AC_SUBST(MOZ_MSAN) + +dnl ======================================================== +dnl = Use Thread Sanitizer +dnl ======================================================== +if test -n "$MOZ_TSAN"; then + CFLAGS="-fsanitize=thread $CFLAGS" + CXXFLAGS="-fsanitize=thread $CXXFLAGS" + if test -z "$CLANG_CL"; then + LDFLAGS="-fsanitize=thread -rdynamic $LDFLAGS" + fi + AC_DEFINE(MOZ_TSAN) + MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer) +fi +AC_SUBST(MOZ_TSAN) + +dnl ======================================================== +dnl = Use UndefinedBehavior Sanitizer (with custom checks) +dnl ======================================================== +if test -n "$MOZ_UBSAN_CHECKS"; then + MOZ_UBSAN=1 + UBSAN_TXT="$_objdir/ubsan_blacklist.txt" + cat $_topsrcdir/build/sanitizers/ubsan_*_blacklist.txt > $UBSAN_TXT + UBSAN_FLAGS="-fsanitize=$MOZ_UBSAN_CHECKS -fno-sanitize-recover=$MOZ_UBSAN_CHECKS -fsanitize-blacklist=$UBSAN_TXT" + CFLAGS="$UBSAN_FLAGS $CFLAGS" + CXXFLAGS="$UBSAN_FLAGS $CXXFLAGS" + if test -z "$CLANG_CL"; then + LDFLAGS="-fsanitize=undefined -rdynamic $LDFLAGS" + fi + AC_DEFINE(MOZ_UBSAN) + MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer) +fi +AC_SUBST(MOZ_UBSAN) + +dnl ======================================================== +dnl = Use UndefinedBehavior Sanitizer to find integer overflows +dnl ======================================================== +if test -n "$MOZ_SIGNED_OVERFLOW_SANITIZE$MOZ_UNSIGNED_OVERFLOW_SANITIZE"; then + MOZ_UBSAN=1 + SANITIZER_BLACKLISTS="" + if test -n "$MOZ_SIGNED_OVERFLOW_SANITIZE"; then + SANITIZER_BLACKLISTS="-fsanitize-blacklist=$_topsrcdir/build/sanitizers/ubsan_signed_overflow_blacklist.txt $SANITIZER_BLACKLISTS" + CFLAGS="-fsanitize=signed-integer-overflow $CFLAGS" + CXXFLAGS="-fsanitize=signed-integer-overflow $CXXFLAGS" + if test -z "$CLANG_CL"; then + LDFLAGS="-fsanitize=signed-integer-overflow -rdynamic $LDFLAGS" + fi + AC_DEFINE(MOZ_SIGNED_OVERFLOW_SANITIZE) + fi + if test -n "$MOZ_UNSIGNED_OVERFLOW_SANITIZE"; then + SANITIZER_BLACKLISTS="-fsanitize-blacklist=$_topsrcdir/build/sanitizers/ubsan_unsigned_overflow_blacklist.txt $SANITIZER_BLACKLISTS" + CFLAGS="-fsanitize=unsigned-integer-overflow $CFLAGS" + CXXFLAGS="-fsanitize=unsigned-integer-overflow $CXXFLAGS" + if test -z "$CLANG_CL"; then + LDFLAGS="-fsanitize=unsigned-integer-overflow -rdynamic $LDFLAGS" + fi + AC_DEFINE(MOZ_UNSIGNED_OVERFLOW_SANITIZE) + fi + CFLAGS="$SANITIZER_BLACKLISTS $CFLAGS" + CXXFLAGS="$SANITIZER_BLACKLISTS $CXXFLAGS" + AC_DEFINE(MOZ_UBSAN) + MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer) +fi +AC_SUBST(MOZ_SIGNED_OVERFLOW_SANITIZE) +AC_SUBST(MOZ_UNSIGNED_OVERFLOW_SANITIZE) +AC_SUBST(MOZ_UBSAN) + +dnl ======================================================= +dnl = Required for stand-alone (sanitizer-less) libFuzzer. +dnl ======================================================= +if test -n "$LIBFUZZER"; then + LDFLAGS="$LIBFUZZER_FLAGS -rdynamic $LDFLAGS" +fi + +# The LLVM symbolizer is used by all sanitizers +AC_SUBST(LLVM_SYMBOLIZER) + +dnl ======================================================== +dnl = Test for whether the compiler is compatible with the +dnl = given sanitize options. +dnl ======================================================== +AC_TRY_LINK(,,,AC_MSG_ERROR([compiler is incompatible with sanitize options])) + +]) diff --git a/build/autoconf/toolchain.m4 b/build/autoconf/toolchain.m4 new file mode 100644 index 0000000000..270738f4d5 --- /dev/null +++ b/build/autoconf/toolchain.m4 @@ -0,0 +1,117 @@ +dnl This Source Code Form is subject to the terms of the Mozilla Public +dnl License, v. 2.0. If a copy of the MPL was not distributed with this +dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. + +dnl Several autoconf functions AC_REQUIRE AC_PROG_CPP/AC_PROG_CXXCPP +dnl or AC_HEADER_STDC, meaning they are called even when we don't call +dnl them explicitly. +dnl However, theses checks are not necessary and python configure sets +dnl the corresponding variables already, so just skip those tests +dnl entirely. +define([AC_PROG_CPP],[]) +define([AC_PROG_CXXCPP],[]) +define([AC_HEADER_STDC], []) + +dnl AC_LANG_* set ac_link to the C/C++ compiler, which works fine with +dnl gcc and clang, but not great with clang-cl, where the build system +dnl currently expects to run the linker independently. So LDFLAGS are not +dnl really adapted to be used with clang-cl, which then proceeds to +dnl execute link.exe rather than lld-link.exe. +dnl So when the compiler is clang-cl, we modify ac_link to use a separate +dnl linker call. +define([_MOZ_AC_LANG_C], defn([AC_LANG_C])) +define([AC_LANG_C], +[_MOZ_AC_LANG_C +if test "$CC_TYPE" = "clang-cl"; then + ac_link="$ac_compile"' && ${LINKER} -OUT:conftest${ac_exeext} $LDFLAGS conftest.obj $LIBS 1>&AC_FD_CC' +fi +]) + +define([_MOZ_AC_LANG_CPLUSPLUS], defn([AC_LANG_CPLUSPLUS])) +define([AC_LANG_CPLUSPLUS], +[_MOZ_AC_LANG_CPLUSPLUS +if test "$CC_TYPE" = "clang-cl"; then + ac_link="$ac_compile"' && ${LINKER} -OUT:conftest${ac_exeext} $LDFLAGS conftest.obj $LIBS 1>&AC_FD_CC' +fi +]) + +AC_DEFUN([MOZ_TOOL_VARIABLES], +[ +GNU_CC= +GNU_CXX= +if test "$CC_TYPE" = "gcc"; then + GNU_CC=1 + GNU_CXX=1 +fi + +CLANG_CC= +CLANG_CXX= +CLANG_CL= +if test "$CC_TYPE" = "clang"; then + GNU_CC=1 + GNU_CXX=1 + CLANG_CC=1 + CLANG_CXX=1 +fi +if test "$CC_TYPE" = "clang-cl"; then + CLANG_CL=1 +fi + +AC_SUBST(CLANG_CXX) +AC_SUBST(CLANG_CL) +]) + +AC_DEFUN([MOZ_CROSS_COMPILER], +[ +echo "cross compiling from $host to $target" + +dnl AC_CHECK_PROGS manually goes through $PATH, and as such fails to handle +dnl absolute or relative paths. Relative paths wouldn't work anyways, but +dnl absolute paths would. Trick AC_CHECK_PROGS into working in that case by +dnl adding / to PATH. This is temporary until this moves to moz.configure +dnl (soon). +_SAVE_PATH=$PATH +case "${TOOLCHAIN_PREFIX}" in +/*) + PATH="/:$PATH" + ;; +esac +AC_PROG_CC +AC_PROG_CXX + +PATH=$_SAVE_PATH +]) + +AC_DEFUN([MOZ_CXX11], +[ +dnl Updates to the test below should be duplicated further below for the +dnl cross-compiling case. +AC_LANG_CPLUSPLUS +if test "$GNU_CXX"; then + AC_CACHE_CHECK([whether 64-bits std::atomic requires -latomic], + ac_cv_needs_atomic, + AC_TRY_LINK( + [#include <cstdint> + #include <atomic>], + [ std::atomic<uint64_t> foo; foo = 1; ], + ac_cv_needs_atomic=no, + _SAVE_LIBS="$LIBS" + LIBS="$LIBS -latomic" + AC_TRY_LINK( + [#include <cstdint> + #include <atomic>], + [ std::atomic<uint64_t> foo; foo = 1; ], + ac_cv_needs_atomic=yes, + ac_cv_needs_atomic="do not know; assuming no") + LIBS="$_SAVE_LIBS" + ) + ) + if test "$ac_cv_needs_atomic" = yes; then + MOZ_NEEDS_LIBATOMIC=1 + else + MOZ_NEEDS_LIBATOMIC= + fi + AC_SUBST(MOZ_NEEDS_LIBATOMIC) +fi +AC_LANG_C +]) diff --git a/build/binary-location.mk b/build/binary-location.mk new file mode 100644 index 0000000000..19ae4b55f3 --- /dev/null +++ b/build/binary-location.mk @@ -0,0 +1,19 @@ +# 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/. + +# finds the location of the browser and puts it in the variable $(browser_path) + +ifneq (,$(filter WINNT,$(OS_ARCH))) +program = $(MOZ_APP_NAME)$(BIN_SUFFIX) +else +program = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX) +endif + +TARGET_DIST = $(TARGET_DEPTH)/dist + +ifeq ($(OS_ARCH),Darwin) +browser_path = $(TARGET_DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/$(program) +else +browser_path = $(TARGET_DIST)/bin/$(program) +endif diff --git a/build/build-clang/1stage.json b/build/build-clang/1stage.json new file mode 100644 index 0000000000..4633a3e93e --- /dev/null +++ b/build/build-clang/1stage.json @@ -0,0 +1,4 @@ +{ + "stages": "1", + "targets": "X86;ARM;AArch64;WebAssembly" +} diff --git a/build/build-clang/2stages.json b/build/build-clang/2stages.json new file mode 100644 index 0000000000..e34226758d --- /dev/null +++ b/build/build-clang/2stages.json @@ -0,0 +1,3 @@ +{ + "stages": "2" +} diff --git a/build/build-clang/4stages-pgo.json b/build/build-clang/4stages-pgo.json new file mode 100644 index 0000000000..8f0c5aa97d --- /dev/null +++ b/build/build-clang/4stages-pgo.json @@ -0,0 +1,7 @@ +{ + "stages": "4", + "targets": "X86;ARM;AArch64;WebAssembly", + "pgo": true, + "ranlib": "{MOZ_FETCHES_DIR}/clang/bin/llvm-ranlib", + "ar": "{MOZ_FETCHES_DIR}/clang/bin/llvm-ar" +} diff --git a/build/build-clang/D146664.patch b/build/build-clang/D146664.patch new file mode 100644 index 0000000000..9813c6c86e --- /dev/null +++ b/build/build-clang/D146664.patch @@ -0,0 +1,99 @@ +From b57ff6da9c8b281ae9312e245fd3372e7ffaff28 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Thu, 23 Mar 2023 06:52:28 +0900 +Subject: [PATCH] Apply the same fallbacks as runtimes search for stdlib search + +When building clang with e.g. LLVM_ENABLE_RUNTIMES=libcxx;libunwind, +those runtimes end up in the stdlib search directory, and when +LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is set, that ends up in a +target-specific subdirectory. The stdlib search does handle the +situation, but when the target in question is Android, the same issues +as those that required fallbacks for runtimes search apply. + +Traditionally, those libraries are shipped as part of the Android NDK, +but when one builds their own clang for Android, they may want to use +the runtimes from the same version rather than the ones from the NDK. + +Differential Revision: https://reviews.llvm.org/D146664 +--- + clang/lib/Driver/ToolChain.cpp | 42 +++++++++++++++++++--------------- + 1 file changed, 24 insertions(+), 18 deletions(-) + +diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp +index 2dba975a5a8f..9052099cad5e 100644 +--- a/clang/lib/Driver/ToolChain.cpp ++++ b/clang/lib/Driver/ToolChain.cpp +@@ -569,15 +569,9 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, + return Args.MakeArgString(getCompilerRT(Args, Component, Type)); + } + +-ToolChain::path_list ToolChain::getRuntimePaths() const { +- path_list Paths; +- auto addPathForTriple = [this, &Paths](const llvm::Triple &Triple) { +- SmallString<128> P(D.ResourceDir); +- llvm::sys::path::append(P, "lib", Triple.str()); +- Paths.push_back(std::string(P.str())); +- }; +- +- addPathForTriple(getTriple()); ++template <typename F> ++static void fillPaths(const ToolChain &TC, F addPathForTriple) { ++ addPathForTriple(TC.getTriple()); + + // When building with per target runtime directories, various ways of naming + // the Arm architecture may have been normalised to simply "arm". +@@ -594,30 +588,42 @@ ToolChain::path_list ToolChain::getRuntimePaths() const { + // + // M profile Arm is bare metal and we know they will not be using the per + // target runtime directory layout. +- if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) { +- llvm::Triple ArmTriple = getTriple(); ++ if (TC.getTriple().getArch() == Triple::arm && ++ !TC.getTriple().isArmMClass()) { ++ llvm::Triple ArmTriple = TC.getTriple(); + ArmTriple.setArch(Triple::arm); + addPathForTriple(ArmTriple); + } + + // Android targets may include an API level at the end. We still want to fall + // back on a path without the API level. +- if (getTriple().isAndroid() && +- getTriple().getEnvironmentName() != "android") { +- llvm::Triple TripleWithoutLevel = getTriple(); ++ if (TC.getTriple().isAndroid() && ++ TC.getTriple().getEnvironmentName() != "android") { ++ llvm::Triple TripleWithoutLevel = TC.getTriple(); + TripleWithoutLevel.setEnvironmentName("android"); + addPathForTriple(TripleWithoutLevel); + } ++} + ++ToolChain::path_list ToolChain::getRuntimePaths() const { ++ path_list Paths; ++ auto addPathForTriple = [this, &Paths](const llvm::Triple &Triple) { ++ SmallString<128> P(D.ResourceDir); ++ llvm::sys::path::append(P, "lib", Triple.str()); ++ Paths.push_back(std::string(P.str())); ++ }; ++ fillPaths(*this, addPathForTriple); + return Paths; + } + + ToolChain::path_list ToolChain::getStdlibPaths() const { + path_list Paths; +- SmallString<128> P(D.Dir); +- llvm::sys::path::append(P, "..", "lib", getTripleString()); +- Paths.push_back(std::string(P.str())); +- ++ auto addPathForTriple = [this, &Paths](const llvm::Triple &Triple) { ++ SmallString<128> P(D.Dir); ++ llvm::sys::path::append(P, "..", "lib", Triple.str()); ++ Paths.push_back(std::string(P.str())); ++ }; ++ fillPaths(*this, addPathForTriple); + return Paths; + } + +-- +2.39.0.1.g6739ec1790 + diff --git a/build/build-clang/README b/build/build-clang/README new file mode 100644 index 0000000000..5b13edeeb9 --- /dev/null +++ b/build/build-clang/README @@ -0,0 +1,53 @@ +build-clang.py +============== + +A script to build clang from source. + +``` +usage: build-clang.py [-h] -c CONFIG [--clean] + +optional arguments: + -h, --help show this help message and exit + -c CONFIG, --config CONFIG + Clang configuration file + --clean Clean the build directory +``` + +Pre-requisites +-------------- +* Working build toolchain. +* git +* CMake +* Ninja +* Python 2.7 and 3 + +Please use the latest available CMake for your platform to avoid surprises. + +Config file format +------------------ + +build-clang.py accepts a JSON config format with the following fields: + +* stages: Use 1, 2, 3 or 4 to select different compiler stages. The default is 2. +* cc: Path to the bootsraping C Compiler. +* cxx: Path to the bootsraping C++ Compiler. +* as: Path to the assembler tool. +* ar: Path to the library archiver tool. +* ranlib: Path to the ranlib tool (optional). +* ld: Path to the linker. +* patches: Optional list of patches to apply. +* build_type: The type of build to make. Supported types: Release, Debug, RelWithDebInfo or MinSizeRel. +* targets: The targets supported by the final stage LLVM/clang. +* build_clang_tidy: Whether to build clang-tidy with the Mozilla checks imported. The default is false. +* osx_cross_compile: Whether to invoke CMake for OS X cross compile builds. +* assertions: Whether to enable LLVM assertions. The default is false. +* pgo: Whether to build with PGO (requires stages == 4). The default is false. + +The revisions are defined in taskcluster/ci/fetch/toolchains.yml. They are usually commit sha1s corresponding to upstream tags. + +Environment Variables +--------------------- + +The following environment variables are used for cross-compile builds targeting OS X on Linux. + +* CROSS_SYSROOT: Path to the OS X SDK directory for cross compile builds. diff --git a/build/build-clang/Remove-FlushViewOfFile-when-unmaping-gcda-files.patch b/build/build-clang/Remove-FlushViewOfFile-when-unmaping-gcda-files.patch new file mode 100644 index 0000000000..a3ea2d75f9 --- /dev/null +++ b/build/build-clang/Remove-FlushViewOfFile-when-unmaping-gcda-files.patch @@ -0,0 +1,31 @@ +From 78a6bcfed4b73f13b9973afd69b76067dd4a5dde Mon Sep 17 00:00:00 2001 +From: Calixte Denizet <calixte.denizet@gmail.com> +Date: Mon, 4 Oct 2021 11:07:56 +0200 +Subject: [PATCH] Remove FlushViewOfFile when unmaping gcda files - it can + causes bad performances with slow disks; - MS docs say that it's mainly + useful in case of hard failures (OS crash, electrical failure, ...): so it's + useless to call this function when ccov builds run on CI. + +--- + compiler-rt/lib/profile/GCDAProfiling.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c +index 4293e8f7b5bf..83650d33c95d 100644 +--- a/compiler-rt/lib/profile/GCDAProfiling.c ++++ b/compiler-rt/lib/profile/GCDAProfiling.c +@@ -286,11 +286,6 @@ static int map_file() { + + static void unmap_file() { + #if defined(_WIN32) +- if (!FlushViewOfFile(write_buffer, file_size)) { +- fprintf(stderr, "profiling: %s: cannot flush mapped view: %lu\n", filename, +- GetLastError()); +- } +- + if (!UnmapViewOfFile(write_buffer)) { + fprintf(stderr, "profiling: %s: cannot unmap mapped view: %lu\n", filename, + GetLastError()); +-- +2.33.0 + diff --git a/build/build-clang/allow-unversioned-android.patch b/build/build-clang/allow-unversioned-android.patch new file mode 100644 index 0000000000..afd82bfc25 --- /dev/null +++ b/build/build-clang/allow-unversioned-android.patch @@ -0,0 +1,36 @@ +diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp +index 31245964c4ba..dbdccd95bb4f 100644 +--- a/clang/lib/Driver/ToolChain.cpp ++++ b/clang/lib/Driver/ToolChain.cpp +@@ -689,7 +689,6 @@ ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const { + unsigned BestVersion = 0; + + SmallString<32> TripleDir; +- bool UsingUnversionedDir = false; + std::error_code EC; + for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { +@@ -698,14 +697,12 @@ ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const { + if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) { + if (DirNameSuffix.empty() && TripleDir.empty()) { + TripleDir = DirName; +- UsingUnversionedDir = true; + } else { + unsigned Version; + if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion && + Version < TripleVersion) { + BestVersion = Version; + TripleDir = DirName; +- UsingUnversionedDir = false; + } + } + } +@@ -716,8 +713,6 @@ ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const { + + SmallString<128> P(BaseDir); + llvm::sys::path::append(P, TripleDir); +- if (UsingUnversionedDir) +- D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString(); + return std::string(P); + } + diff --git a/build/build-clang/android-mangling-error_clang_12.patch b/build/build-clang/android-mangling-error_clang_12.patch new file mode 100644 index 0000000000..315756d30b --- /dev/null +++ b/build/build-clang/android-mangling-error_clang_12.patch @@ -0,0 +1,24 @@ +Workaround segfault in clang's mangling code that is tickled when +attempting to mangle the declaration: + std:__ndk1::__find_detail::__find_exactly_one_checked::__matches +in the <tuple> header in the Android NDK. +This codepath is exercised by MozsearchIndexer.cpp (the searchfox +indexer) when indexing on Android. See also +https://bugs.llvm.org/show_bug.cgi?id=40747 + +diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp +index 4420f6a2c1c3..39792e6b7350 100644 +--- a/clang/lib/AST/ItaniumMangle.cpp ++++ b/clang/lib/AST/ItaniumMangle.cpp +@@ -3954,6 +3954,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, + // produces no output, where ImplicitlyConvertedToType and AsTemplateArg need + // to be preserved. + recurse: ++ if (!E) { ++ Out << "MOZ_WE_HACKED_AROUND_BUG_1500941"; ++ return; ++ } ++ + switch (E->getStmtClass()) { + case Expr::NoStmtClass: + #define ABSTRACT_STMT(Type) diff --git a/build/build-clang/build-clang.py b/build/build-clang/build-clang.py new file mode 100755 index 0000000000..08e05483f5 --- /dev/null +++ b/build/build-clang/build-clang.py @@ -0,0 +1,843 @@ +#!/usr/bin/python3 +# 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/. + +# Only necessary for flake8 to be happy... +import argparse +import errno +import fnmatch +import glob +import json +import os +import os.path +import platform +import re +import shutil +import subprocess +import sys +import tarfile +from contextlib import contextmanager +from shutil import which + +import zstandard + +SUPPORTED_TARGETS = { + "x86_64-unknown-linux-gnu": ("Linux", "x86_64"), + "x86_64-pc-windows-msvc": ("Windows", "AMD64"), + "x86_64-apple-darwin": ("Darwin", "x86_64"), + "aarch64-apple-darwin": ("Darwin", "arm64"), +} + + +def is_llvm_toolchain(cc, cxx): + return "clang" in cc and "clang" in cxx + + +def check_run(args): + print(" ".join(args), file=sys.stderr, flush=True) + if args[0] == "cmake": + # CMake `message(STATUS)` messages, as appearing in failed source code + # compiles, appear on stdout, so we only capture that. + p = subprocess.Popen(args, stdout=subprocess.PIPE) + lines = [] + for line in p.stdout: + lines.append(line) + sys.stdout.write(line.decode()) + sys.stdout.flush() + r = p.wait() + if r != 0 and os.environ.get("UPLOAD_DIR"): + cmake_output_re = re.compile(b'See also "(.*/CMakeOutput.log)"') + cmake_error_re = re.compile(b'See also "(.*/CMakeError.log)"') + + def find_first_match(re): + for l in lines: + match = re.search(l) + if match: + return match + + output_match = find_first_match(cmake_output_re) + error_match = find_first_match(cmake_error_re) + + upload_dir = os.environ["UPLOAD_DIR"].encode("utf-8") + if output_match or error_match: + mkdir_p(upload_dir) + if output_match: + shutil.copy2(output_match.group(1), upload_dir) + if error_match: + shutil.copy2(error_match.group(1), upload_dir) + else: + r = subprocess.call(args) + assert r == 0 + + +def run_in(path, args): + with chdir(path): + check_run(args) + + +@contextmanager +def chdir(path): + d = os.getcwd() + print('cd "%s"' % path, file=sys.stderr) + os.chdir(path) + try: + yield + finally: + print('cd "%s"' % d, file=sys.stderr) + os.chdir(d) + + +def patch(patch, srcdir): + patch = os.path.realpath(patch) + check_run(["patch", "-d", srcdir, "-p1", "-i", patch, "--fuzz=0", "-s"]) + + +def import_clang_tidy(source_dir, build_clang_tidy_alpha, build_clang_tidy_external): + clang_plugin_path = os.path.join(os.path.dirname(sys.argv[0]), "..", "clang-plugin") + clang_tidy_path = os.path.join(source_dir, "clang-tools-extra/clang-tidy") + sys.path.append(clang_plugin_path) + from import_mozilla_checks import do_import + + import_options = { + "alpha": build_clang_tidy_alpha, + "external": build_clang_tidy_external, + } + do_import(clang_plugin_path, clang_tidy_path, import_options) + + +def build_package(package_build_dir, cmake_args): + if not os.path.exists(package_build_dir): + os.mkdir(package_build_dir) + # If CMake has already been run, it may have been run with different + # arguments, so we need to re-run it. Make sure the cached copy of the + # previous CMake run is cleared before running it again. + if os.path.exists(package_build_dir + "/CMakeCache.txt"): + os.remove(package_build_dir + "/CMakeCache.txt") + if os.path.exists(package_build_dir + "/CMakeFiles"): + shutil.rmtree(package_build_dir + "/CMakeFiles") + + run_in(package_build_dir, ["cmake"] + cmake_args) + run_in(package_build_dir, ["ninja", "install", "-v"]) + + +@contextmanager +def updated_env(env): + old_env = os.environ.copy() + os.environ.update(env) + yield + os.environ.clear() + os.environ.update(old_env) + + +def build_tar_package(name, base, directory): + name = os.path.realpath(name) + print("tarring {} from {}/{}".format(name, base, directory), file=sys.stderr) + assert name.endswith(".tar.zst") + + cctx = zstandard.ZstdCompressor() + with open(name, "wb") as f, cctx.stream_writer(f) as z: + with tarfile.open(mode="w|", fileobj=z) as tf: + with chdir(base): + tf.add(directory) + + +def mkdir_p(path): + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST or not os.path.isdir(path): + raise + + +def delete(path): + if os.path.isdir(path): + shutil.rmtree(path) + else: + try: + os.unlink(path) + except Exception: + pass + + +def install_import_library(build_dir, clang_dir): + shutil.copy2( + os.path.join(build_dir, "lib", "clang.lib"), os.path.join(clang_dir, "lib") + ) + + +def is_darwin(target): + return "-apple-darwin" in target + + +def is_linux(target): + return "-linux-gnu" in target + + +def is_windows(target): + return "-windows-msvc" in target + + +def is_cross_compile(target): + return SUPPORTED_TARGETS[target] != (platform.system(), platform.machine()) + + +def build_one_stage( + cc, + cxx, + asm, + ar, + ranlib, + ldflags, + src_dir, + stage_dir, + package_name, + build_type, + assertions, + target, + targets, + is_final_stage=False, + profile=None, +): + if not os.path.exists(stage_dir): + os.mkdir(stage_dir) + + build_dir = stage_dir + "/build" + inst_dir = stage_dir + "/" + package_name + + # cmake doesn't deal well with backslashes in paths. + def slashify_path(path): + return path.replace("\\", "/") + + def cmake_base_args(cc, cxx, asm, ar, ranlib, ldflags, inst_dir): + machine_targets = targets if is_final_stage and targets else "X86" + + cmake_args = [ + "-GNinja", + "-DCMAKE_C_COMPILER=%s" % slashify_path(cc[0]), + "-DCMAKE_CXX_COMPILER=%s" % slashify_path(cxx[0]), + "-DCMAKE_ASM_COMPILER=%s" % slashify_path(asm[0]), + "-DCMAKE_AR=%s" % slashify_path(ar), + "-DCMAKE_C_FLAGS_INIT=%s" % " ".join(cc[1:]), + "-DCMAKE_CXX_FLAGS_INIT=%s" % " ".join(cxx[1:]), + "-DCMAKE_ASM_FLAGS_INIT=%s" % " ".join(asm[1:]), + "-DCMAKE_EXE_LINKER_FLAGS_INIT=%s" % " ".join(ldflags), + "-DCMAKE_SHARED_LINKER_FLAGS_INIT=%s" % " ".join(ldflags), + "-DCMAKE_BUILD_TYPE=%s" % build_type, + "-DCMAKE_INSTALL_PREFIX=%s" % inst_dir, + "-DLLVM_TARGETS_TO_BUILD=%s" % machine_targets, + "-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF", + "-DLLVM_ENABLE_ASSERTIONS=%s" % ("ON" if assertions else "OFF"), + "-DLLVM_ENABLE_BINDINGS=OFF", + "-DLLVM_ENABLE_CURL=OFF", + "-DLLVM_INCLUDE_TESTS=OFF", + ] + if is_llvm_toolchain(cc[0], cxx[0]): + cmake_args += ["-DLLVM_ENABLE_LLD=ON"] + elif is_windows(target) and is_cross_compile(target): + raise Exception( + "Cannot cross-compile for Windows with a compiler that is not clang" + ) + + if "TASK_ID" in os.environ: + cmake_args += [ + "-DCLANG_REPOSITORY_STRING=taskcluster-%s" % os.environ["TASK_ID"], + ] + projects = ["clang", "lld"] + if is_final_stage: + projects.append("clang-tools-extra") + else: + cmake_args.append("-DLLVM_TOOL_LLI_BUILD=OFF") + + cmake_args.append("-DLLVM_ENABLE_PROJECTS=%s" % ";".join(projects)) + + # There is no libxml2 on Windows except if we build one ourselves. + # libxml2 is only necessary for llvm-mt, but Windows can just use the + # native MT tool. + if not is_windows(target) and is_final_stage: + cmake_args += ["-DLLVM_ENABLE_LIBXML2=FORCE_ON"] + if is_linux(target) and is_final_stage: + sysroot = os.path.join(os.environ.get("MOZ_FETCHES_DIR", ""), "sysroot") + if os.path.exists(sysroot): + cmake_args += ["-DLLVM_BINUTILS_INCDIR=/usr/include"] + cmake_args += ["-DCMAKE_SYSROOT=%s" % sysroot] + # Work around the LLVM build system not building the i386 compiler-rt + # because it doesn't allow to use a sysroot for that during the cmake + # checks. + cmake_args += ["-DCAN_TARGET_i386=1"] + cmake_args += ["-DLLVM_ENABLE_TERMINFO=OFF"] + if is_windows(target): + cmake_args.insert(-1, "-DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON") + cmake_args.insert(-1, "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded") + if is_cross_compile(target): + cmake_args += [ + f"-DCMAKE_TOOLCHAIN_FILE={src_dir}/cmake/platforms/WinMsvc.cmake", + f"-DLLVM_NATIVE_TOOLCHAIN={os.path.dirname(os.path.dirname(cc[0]))}", + f"-DHOST_ARCH={target[: -len('-pc-windows-msvc')]}", + f"-DLLVM_WINSYSROOT={os.environ['VSINSTALLDIR']}", + "-DLLVM_DISABLE_ASSEMBLY_FILES=ON", + ] + else: + # libllvm as a shared library is not supported on Windows + cmake_args += ["-DLLVM_LINK_LLVM_DYLIB=ON"] + if ranlib is not None: + cmake_args += ["-DCMAKE_RANLIB=%s" % slashify_path(ranlib)] + if is_darwin(target) and is_cross_compile(target): + arch = "arm64" if target.startswith("aarch64") else "x86_64" + cmake_args += [ + "-DCMAKE_SYSTEM_NAME=Darwin", + "-DCMAKE_SYSTEM_VERSION=%s" % os.environ["MACOSX_DEPLOYMENT_TARGET"], + "-DCMAKE_OSX_SYSROOT=%s" % slashify_path(os.getenv("CROSS_SYSROOT")), + "-DCMAKE_FIND_ROOT_PATH=%s" % slashify_path(os.getenv("CROSS_SYSROOT")), + "-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER", + "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY", + "-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY", + "-DCMAKE_MACOSX_RPATH=ON", + "-DCMAKE_OSX_ARCHITECTURES=%s" % arch, + "-DDARWIN_osx_ARCHS=%s" % arch, + "-DDARWIN_osx_SYSROOT=%s" % slashify_path(os.getenv("CROSS_SYSROOT")), + "-DLLVM_DEFAULT_TARGET_TRIPLE=%s" % target, + "-DCMAKE_C_COMPILER_TARGET=%s" % target, + "-DCMAKE_CXX_COMPILER_TARGET=%s" % target, + "-DCMAKE_ASM_COMPILER_TARGET=%s" % target, + ] + if arch == "arm64": + cmake_args += [ + "-DDARWIN_osx_BUILTIN_ARCHS=arm64", + ] + # Starting in LLVM 11 (which requires SDK 10.12) the build tries to + # detect the SDK version by calling xcrun. Cross-compiles don't have + # an xcrun, so we have to set the version explicitly. + cmake_args += [ + "-DDARWIN_macosx_OVERRIDE_SDK_VERSION=%s" + % os.environ["MACOSX_DEPLOYMENT_TARGET"], + ] + + if profile == "gen": + # Per https://releases.llvm.org/10.0.0/docs/HowToBuildWithPGO.html + cmake_args += [ + "-DLLVM_BUILD_INSTRUMENTED=IR", + "-DLLVM_BUILD_RUNTIME=No", + ] + elif profile: + cmake_args += [ + "-DLLVM_PROFDATA_FILE=%s" % profile, + ] + + # Using LTO for both profile generation and usage to avoid most + # "function control flow change detected (hash mismatch)" error. + if profile and not is_windows(target): + cmake_args.append("-DLLVM_ENABLE_LTO=Thin") + return cmake_args + + cmake_args = [] + cmake_args += cmake_base_args(cc, cxx, asm, ar, ranlib, ldflags, inst_dir) + cmake_args += [src_dir] + build_package(build_dir, cmake_args) + + # For some reasons the import library clang.lib of clang.exe is not + # installed, so we copy it by ourselves. + if is_windows(target) and is_final_stage: + install_import_library(build_dir, inst_dir) + + +# Return the absolute path of a build tool. We first look to see if the +# variable is defined in the config file, and if so we make sure it's an +# absolute path to an existing tool, otherwise we look for a program in +# $PATH named "key". +# +# This expects the name of the key in the config file to match the name of +# the tool in the default toolchain on the system (for example, "ld" on Unix +# and "link" on Windows). +def get_tool(config, key): + f = None + if key in config: + f = config[key].format(**os.environ) + if os.path.isabs(f): + if not os.path.exists(f): + raise ValueError("%s must point to an existing path" % key) + return f + + # Assume that we have the name of some program that should be on PATH. + tool = which(f) if f else which(key) + if not tool: + raise ValueError("%s not found on PATH" % (f or key)) + return tool + + +# This function is intended to be called on the final build directory when +# building clang-tidy. Also clang-format binaries are included that can be used +# in conjunction with clang-tidy. +# As a separate binary we also ship clangd for the language server protocol that +# can be used as a plugin in `vscode`. +# Its job is to remove all of the files which won't be used for clang-tidy or +# clang-format to reduce the download size. Currently when this function +# finishes its job, it will leave final_dir with a layout like this: +# +# clang/ +# bin/ +# clang-apply-replacements +# clang-format +# clang-tidy +# clangd +# run-clang-tidy +# include/ +# * (nothing will be deleted here) +# lib/ +# clang/ +# 4.0.0/ +# include/ +# * (nothing will be deleted here) +# share/ +# clang/ +# clang-format-diff.py +# clang-tidy-diff.py +# run-clang-tidy.py +def prune_final_dir_for_clang_tidy(final_dir, target): + # Make sure we only have what we expect. + dirs = [ + "bin", + "include", + "lib", + "lib32", + "libexec", + "msbuild-bin", + "share", + "tools", + ] + if is_linux(target): + dirs.append("x86_64-unknown-linux-gnu") + for f in glob.glob("%s/*" % final_dir): + if os.path.basename(f) not in dirs: + raise Exception("Found unknown file %s in the final directory" % f) + if not os.path.isdir(f): + raise Exception("Expected %s to be a directory" % f) + + kept_binaries = [ + "clang-apply-replacements", + "clang-format", + "clang-tidy", + "clangd", + "clang-query", + "run-clang-tidy", + ] + re_clang_tidy = re.compile(r"^(" + "|".join(kept_binaries) + r")(\.exe)?$", re.I) + for f in glob.glob("%s/bin/*" % final_dir): + if re_clang_tidy.search(os.path.basename(f)) is None: + delete(f) + + # Keep include/ intact. + + # Remove the target-specific files. + if is_linux(target): + if os.path.exists(os.path.join(final_dir, "x86_64-unknown-linux-gnu")): + shutil.rmtree(os.path.join(final_dir, "x86_64-unknown-linux-gnu")) + + # In lib/, only keep lib/clang/N.M.O/include and the LLVM shared library. + re_ver_num = re.compile(r"^\d+(?:\.\d+\.\d+)?$", re.I) + for f in glob.glob("%s/lib/*" % final_dir): + name = os.path.basename(f) + if name == "clang": + continue + if is_darwin(target) and name in ["libLLVM.dylib", "libclang-cpp.dylib"]: + continue + if is_linux(target) and ( + fnmatch.fnmatch(name, "libLLVM*.so") + or fnmatch.fnmatch(name, "libclang-cpp.so*") + ): + continue + delete(f) + for f in glob.glob("%s/lib/clang/*" % final_dir): + if re_ver_num.search(os.path.basename(f)) is None: + delete(f) + for f in glob.glob("%s/lib/clang/*/*" % final_dir): + if os.path.basename(f) != "include": + delete(f) + + # Completely remove libexec/, msbuild-bin and tools, if it exists. + shutil.rmtree(os.path.join(final_dir, "libexec")) + for d in ("msbuild-bin", "tools"): + d = os.path.join(final_dir, d) + if os.path.exists(d): + shutil.rmtree(d) + + # In share/, only keep share/clang/*tidy* + re_clang_tidy = re.compile(r"format|tidy", re.I) + for f in glob.glob("%s/share/*" % final_dir): + if os.path.basename(f) != "clang": + delete(f) + for f in glob.glob("%s/share/clang/*" % final_dir): + if re_clang_tidy.search(os.path.basename(f)) is None: + delete(f) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--config", + action="append", + required=True, + type=argparse.FileType("r"), + help="Clang configuration file", + ) + parser.add_argument( + "--clean", required=False, action="store_true", help="Clean the build directory" + ) + parser.add_argument( + "--skip-tar", + required=False, + action="store_true", + help="Skip tar packaging stage", + ) + parser.add_argument( + "--skip-patch", + required=False, + action="store_true", + help="Do not patch source", + ) + + args = parser.parse_args() + + if not os.path.exists("llvm/README.txt"): + raise Exception( + "The script must be run from the root directory of the llvm-project tree" + ) + source_dir = os.getcwd() + build_dir = source_dir + "/build" + + if args.clean: + shutil.rmtree(build_dir) + os.sys.exit(0) + + llvm_source_dir = source_dir + "/llvm" + + config = {} + # Merge all the configs we got from the command line. + for c in args.config: + this_config_dir = os.path.dirname(c.name) + this_config = json.load(c) + patches = this_config.get("patches") + if patches: + this_config["patches"] = [os.path.join(this_config_dir, p) for p in patches] + for key, value in this_config.items(): + old_value = config.get(key) + if old_value is None: + config[key] = value + elif value is None: + if key in config: + del config[key] + elif type(old_value) != type(value): + raise Exception( + "{} is overriding `{}` with a value of the wrong type".format( + c.name, key + ) + ) + elif isinstance(old_value, list): + for v in value: + if v not in old_value: + old_value.append(v) + elif isinstance(old_value, dict): + raise Exception("{} is setting `{}` to a dict?".format(c.name, key)) + else: + config[key] = value + + stages = 2 + if "stages" in config: + stages = int(config["stages"]) + if stages not in (1, 2, 3, 4): + raise ValueError("We only know how to build 1, 2, 3, or 4 stages.") + skip_stages = 0 + if "skip_stages" in config: + # The assumption here is that the compiler given in `cc` and other configs + # is the result of the last skip stage, built somewhere else. + skip_stages = int(config["skip_stages"]) + if skip_stages >= stages: + raise ValueError("Cannot skip more stages than are built.") + pgo = False + if "pgo" in config: + pgo = config["pgo"] + if pgo not in (True, False): + raise ValueError("Only boolean values are accepted for pgo.") + build_type = "Release" + if "build_type" in config: + build_type = config["build_type"] + if build_type not in ("Release", "Debug", "RelWithDebInfo", "MinSizeRel"): + raise ValueError( + "We only know how to do Release, Debug, RelWithDebInfo or " + "MinSizeRel builds" + ) + targets = config.get("targets") + build_clang_tidy = False + if "build_clang_tidy" in config: + build_clang_tidy = config["build_clang_tidy"] + if build_clang_tidy not in (True, False): + raise ValueError("Only boolean values are accepted for build_clang_tidy.") + build_clang_tidy_alpha = False + # check for build_clang_tidy_alpha only if build_clang_tidy is true + if build_clang_tidy and "build_clang_tidy_alpha" in config: + build_clang_tidy_alpha = config["build_clang_tidy_alpha"] + if build_clang_tidy_alpha not in (True, False): + raise ValueError( + "Only boolean values are accepted for build_clang_tidy_alpha." + ) + build_clang_tidy_external = False + # check for build_clang_tidy_external only if build_clang_tidy is true + if build_clang_tidy and "build_clang_tidy_external" in config: + build_clang_tidy_external = config["build_clang_tidy_external"] + if build_clang_tidy_external not in (True, False): + raise ValueError( + "Only boolean values are accepted for build_clang_tidy_external." + ) + assertions = False + if "assertions" in config: + assertions = config["assertions"] + if assertions not in (True, False): + raise ValueError("Only boolean values are accepted for assertions.") + + for t in SUPPORTED_TARGETS: + if not is_cross_compile(t): + host = t + break + else: + raise Exception( + f"Cannot use this script on {platform.system()} {platform.machine()}" + ) + + target = config.get("target", host) + if target not in SUPPORTED_TARGETS: + raise ValueError(f"{target} is not a supported target.") + + if is_cross_compile(target) and not is_linux(host): + raise Exception("Cross-compilation is only supported on Linux") + + if is_darwin(target): + os.environ["MACOSX_DEPLOYMENT_TARGET"] = ( + "11.0" if target.startswith("aarch64") else "10.12" + ) + + if is_windows(target): + exe_ext = ".exe" + cc_name = "clang-cl" + cxx_name = "clang-cl" + else: + exe_ext = "" + cc_name = "clang" + cxx_name = "clang++" + + cc = get_tool(config, "cc") + cxx = get_tool(config, "cxx") + asm = get_tool(config, "ml" if is_windows(target) else "as") + # Not using lld here as default here because it's not in PATH. But clang + # knows how to find it when they are installed alongside each others. + ar = get_tool(config, "lib" if is_windows(target) else "ar") + ranlib = None if is_windows(target) else get_tool(config, "ranlib") + + if not os.path.exists(source_dir): + os.makedirs(source_dir) + + if not args.skip_patch: + for p in config.get("patches", []): + patch(p, source_dir) + + package_name = "clang" + if build_clang_tidy: + package_name = "clang-tidy" + if not args.skip_patch: + import_clang_tidy( + source_dir, build_clang_tidy_alpha, build_clang_tidy_external + ) + + if not os.path.exists(build_dir): + os.makedirs(build_dir) + + stage1_dir = build_dir + "/stage1" + stage1_inst_dir = stage1_dir + "/" + package_name + + final_stage_dir = stage1_dir + + if is_darwin(target): + extra_cflags = [] + extra_cxxflags = [] + extra_cflags2 = [] + extra_cxxflags2 = [] + extra_asmflags = [] + # It's unfortunately required to specify the linker used here because + # the linker flags are used in LLVM's configure step before + # -DLLVM_ENABLE_LLD is actually processed. + extra_ldflags = [ + "-fuse-ld=lld", + "-Wl,-dead_strip", + ] + elif is_linux(target): + extra_cflags = [] + extra_cxxflags = [] + extra_cflags2 = ["-fPIC"] + # Silence clang's warnings about arguments not being used in compilation. + extra_cxxflags2 = [ + "-fPIC", + "-Qunused-arguments", + ] + extra_asmflags = [] + # Avoid libLLVM internal function calls going through the PLT. + extra_ldflags = ["-Wl,-Bsymbolic-functions"] + # For whatever reason, LLVM's build system will set things up to turn + # on -ffunction-sections and -fdata-sections, but won't turn on the + # corresponding option to strip unused sections. We do it explicitly + # here. LLVM's build system is also picky about turning on ICF, so + # we do that explicitly here, too. + + # It's unfortunately required to specify the linker used here because + # the linker flags are used in LLVM's configure step before + # -DLLVM_ENABLE_LLD is actually processed. + if is_llvm_toolchain(cc, cxx): + extra_ldflags += ["-fuse-ld=lld", "-Wl,--icf=safe"] + extra_ldflags += ["-Wl,--gc-sections"] + elif is_windows(target): + extra_cflags = [] + extra_cxxflags = [] + # clang-cl would like to figure out what it's supposed to be emulating + # by looking at an MSVC install, but we don't really have that here. + # Force things on based on WinMsvc.cmake. + # Ideally, we'd just use WinMsvc.cmake as a toolchain file, but it only + # really works for cross-compiles, which this is not. + with open(os.path.join(llvm_source_dir, "cmake/platforms/WinMsvc.cmake")) as f: + compat = [ + item + for line in f + for item in line.split() + if "-fms-compatibility-version=" in item + ][0] + extra_cflags2 = [compat] + extra_cxxflags2 = [compat] + extra_asmflags = [] + extra_ldflags = [] + + upload_dir = os.getenv("UPLOAD_DIR") + if assertions and upload_dir: + extra_cflags2 += ["-fcrash-diagnostics-dir=%s" % upload_dir] + extra_cxxflags2 += ["-fcrash-diagnostics-dir=%s" % upload_dir] + + if skip_stages < 1: + build_one_stage( + [cc] + extra_cflags, + [cxx] + extra_cxxflags, + [asm] + extra_asmflags, + ar, + ranlib, + extra_ldflags, + llvm_source_dir, + stage1_dir, + package_name, + build_type, + assertions, + target, + targets, + is_final_stage=(stages == 1), + ) + + if stages >= 2 and skip_stages < 2: + stage2_dir = build_dir + "/stage2" + stage2_inst_dir = stage2_dir + "/" + package_name + final_stage_dir = stage2_dir + if skip_stages < 1: + cc = stage1_inst_dir + "/bin/%s%s" % (cc_name, exe_ext) + cxx = stage1_inst_dir + "/bin/%s%s" % (cxx_name, exe_ext) + asm = stage1_inst_dir + "/bin/%s%s" % (cc_name, exe_ext) + build_one_stage( + [cc] + extra_cflags2, + [cxx] + extra_cxxflags2, + [asm] + extra_asmflags, + ar, + ranlib, + extra_ldflags, + llvm_source_dir, + stage2_dir, + package_name, + build_type, + assertions, + target, + targets, + is_final_stage=(stages == 2), + profile="gen" if pgo else None, + ) + + if stages >= 3 and skip_stages < 3: + stage3_dir = build_dir + "/stage3" + stage3_inst_dir = stage3_dir + "/" + package_name + final_stage_dir = stage3_dir + if skip_stages < 2: + cc = stage2_inst_dir + "/bin/%s%s" % (cc_name, exe_ext) + cxx = stage2_inst_dir + "/bin/%s%s" % (cxx_name, exe_ext) + asm = stage2_inst_dir + "/bin/%s%s" % (cc_name, exe_ext) + build_one_stage( + [cc] + extra_cflags2, + [cxx] + extra_cxxflags2, + [asm] + extra_asmflags, + ar, + ranlib, + extra_ldflags, + llvm_source_dir, + stage3_dir, + package_name, + build_type, + assertions, + target, + targets, + (stages == 3), + ) + if pgo: + llvm_profdata = stage2_inst_dir + "/bin/llvm-profdata%s" % exe_ext + merge_cmd = [llvm_profdata, "merge", "-o", "merged.profdata"] + profraw_files = glob.glob( + os.path.join(stage2_dir, "build", "profiles", "*.profraw") + ) + run_in(stage3_dir, merge_cmd + profraw_files) + if stages == 3: + mkdir_p(upload_dir) + shutil.copy2(os.path.join(stage3_dir, "merged.profdata"), upload_dir) + return + + if stages >= 4 and skip_stages < 4: + stage4_dir = build_dir + "/stage4" + final_stage_dir = stage4_dir + profile = None + if pgo: + if skip_stages == 3: + profile_dir = os.environ.get("MOZ_FETCHES_DIR", "") + else: + profile_dir = stage3_dir + profile = os.path.join(profile_dir, "merged.profdata") + if skip_stages < 3: + cc = stage3_inst_dir + "/bin/%s%s" % (cc_name, exe_ext) + cxx = stage3_inst_dir + "/bin/%s%s" % (cxx_name, exe_ext) + asm = stage3_inst_dir + "/bin/%s%s" % (cc_name, exe_ext) + build_one_stage( + [cc] + extra_cflags2, + [cxx] + extra_cxxflags2, + [asm] + extra_asmflags, + ar, + ranlib, + extra_ldflags, + llvm_source_dir, + stage4_dir, + package_name, + build_type, + assertions, + target, + targets, + (stages == 4), + profile=profile, + ) + + if build_clang_tidy: + prune_final_dir_for_clang_tidy( + os.path.join(final_stage_dir, package_name), target + ) + + if not args.skip_tar: + build_tar_package("%s.tar.zst" % package_name, final_stage_dir, package_name) + + +if __name__ == "__main__": + main() diff --git a/build/build-clang/clang-14.json b/build/build-clang/clang-14.json new file mode 100644 index 0000000000..b565fefc74 --- /dev/null +++ b/build/build-clang/clang-14.json @@ -0,0 +1,13 @@ +{ + "patches": [ + "find_symbolizer_linux_clang_10.patch", + "android-mangling-error_clang_12.patch", + "unpoison-thread-stacks_clang_10.patch", + "downgrade-mangling-error_clang_12.patch", + "Remove-FlushViewOfFile-when-unmaping-gcda-files.patch", + "fuzzing_ccov_build_clang_12.patch", + "llvmorg-15-init-16512-g4b1e3d193706.patch", + "win64-ret-null-on-commitment-limit_clang_14.patch", + "compiler-rt-rss-limit-heap-profile.patch" + ] +} diff --git a/build/build-clang/clang-17.json b/build/build-clang/clang-17.json new file mode 100644 index 0000000000..960c7c6754 --- /dev/null +++ b/build/build-clang/clang-17.json @@ -0,0 +1,18 @@ +{ + "patches": [ + "find_symbolizer_linux_clang_15.patch", + "android-mangling-error_clang_12.patch", + "unpoison-thread-stacks_clang_10.patch", + "downgrade-mangling-error_clang_12.patch", + "fuzzing_ccov_build_clang_12.patch", + "partial-revert-llvmorg-17-init-17713-gc8e055d485ea.patch", + "revert-llvmorg-17-init-4120-g02e8eb1a438b.patch", + "partial-revert-llvmorg-16-init-17151-gaa0883b59ae1_clang_17.patch", + "revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_17.patch", + "revert-llvmorg-15-init-13446-g7524fe962e47.patch", + "revert-llvmorg-15-init-11205-gcead4eceb01b_clang_16.patch", + "D146664.patch", + "win64-ret-null-on-commitment-limit_clang_14.patch", + "compiler-rt-rss-limit-heap-profile.patch" + ] +} diff --git a/build/build-clang/clang-18.json b/build/build-clang/clang-18.json new file mode 100644 index 0000000000..5f66e58947 --- /dev/null +++ b/build/build-clang/clang-18.json @@ -0,0 +1,21 @@ +{ + "patches": [ + "allow-unversioned-android.patch", + "find_symbolizer_linux_clang_15.patch", + "android-mangling-error_clang_12.patch", + "unpoison-thread-stacks_clang_10.patch", + "downgrade-mangling-error_clang_12.patch", + "fuzzing_ccov_build_clang_12.patch", + "revert-llvmorg-18-init-6208-g2baf4a06ef06.patch", + "revert-llvmorg-18-init-6193-gb88cffeafd39.patch", + "revert-llvmorg-18-init-6188-gc649f29c24c9.patch", + "partial-revert-llvmorg-17-init-17713-gc8e055d485ea.patch", + "revert-llvmorg-17-init-4120-g02e8eb1a438b_clang_18.patch", + "partial-revert-llvmorg-16-init-17151-gaa0883b59ae1_clang_17.patch", + "revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_18.patch", + "revert-llvmorg-15-init-13446-g7524fe962e47.patch", + "revert-llvmorg-15-init-11205-gcead4eceb01b_clang_18.patch", + "win64-ret-null-on-commitment-limit_clang_14.patch", + "compiler-rt-rss-limit-heap-profile.patch" + ] +} diff --git a/build/build-clang/clang-8-missing-header.patch b/build/build-clang/clang-8-missing-header.patch new file mode 100644 index 0000000000..a6f1fac040 --- /dev/null +++ b/build/build-clang/clang-8-missing-header.patch @@ -0,0 +1,12 @@ +diff --git a/llvm/utils/benchmark/src/benchmark_register.h b/llvm/utils/benchmark/src/benchmark_register.h +index 0705e219f2fa..4caa5ad4da07 100644 +--- a/llvm/utils/benchmark/src/benchmark_register.h ++++ b/llvm/utils/benchmark/src/benchmark_register.h +@@ -1,6 +1,7 @@ + #ifndef BENCHMARK_REGISTER_H + #define BENCHMARK_REGISTER_H + ++#include <limits> + #include <vector> + + #include "check.h" diff --git a/build/build-clang/clang-8.0.json b/build/build-clang/clang-8.0.json new file mode 100644 index 0000000000..77e71e837f --- /dev/null +++ b/build/build-clang/clang-8.0.json @@ -0,0 +1,10 @@ +{ + "cc": "/usr/bin/gcc", + "cxx": "/usr/bin/g++", + "as": "/usr/bin/gcc", + "targets": "X86;WebAssembly", + "patches": [ + "clang-8-missing-header.patch", + "llvmorg-10-init-136-gb288d90b39f4.patch" + ] +} diff --git a/build/build-clang/clang-tidy-ci.patch b/build/build-clang/clang-tidy-ci.patch new file mode 100644 index 0000000000..6c31752136 --- /dev/null +++ b/build/build-clang/clang-tidy-ci.patch @@ -0,0 +1,34 @@ +diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp +index 7de313ad4da6..697f98c362d1 100644 +--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp ++++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp +@@ -432,6 +432,7 @@ ClangTidyASTConsumerFactory::createASTConsumer( + + for (auto &Check : Checks) { + Check->registerMatchers(&*Finder); ++ Check->registerPPCallbacks(Compiler); + Check->registerPPCallbacks(*SM, PP, ModuleExpanderPP); + } + +diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h +index 9b41e5836de7..d8938b8fe05e 100644 +--- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h ++++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h +@@ -20,6 +20,7 @@ + + namespace clang { + ++class CompilerInstance; + class SourceManager; + + namespace tidy { +@@ -69,6 +70,9 @@ public: + return true; + } + ++ /// This has been deprecated in clang 9 - needed by mozilla-must-override ++ virtual void registerPPCallbacks(CompilerInstance &Compiler) {} ++ + /// Override this to register ``PPCallbacks`` in the preprocessor. + /// + /// This should be used for clang-tidy checks that analyze preprocessor- diff --git a/build/build-clang/clang-tidy-external-linux64.json b/build/build-clang/clang-tidy-external-linux64.json new file mode 100644 index 0000000000..897911d3e3 --- /dev/null +++ b/build/build-clang/clang-tidy-external-linux64.json @@ -0,0 +1,11 @@ +{ + "stages": "1", + "build_clang_tidy": true, + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++", + "as": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "patches": [ + "clang-tidy-ci.patch" + ], + "build_clang_tidy_external": true +} diff --git a/build/build-clang/clang-tidy-linux64.json b/build/build-clang/clang-tidy-linux64.json new file mode 100644 index 0000000000..e654aeef92 --- /dev/null +++ b/build/build-clang/clang-tidy-linux64.json @@ -0,0 +1,10 @@ +{ + "stages": "1", + "build_clang_tidy": true, + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++", + "as": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "patches": [ + "clang-tidy-ci.patch" + ] +} diff --git a/build/build-clang/clang-tidy-macosx64.json b/build/build-clang/clang-tidy-macosx64.json new file mode 100644 index 0000000000..6da85803f5 --- /dev/null +++ b/build/build-clang/clang-tidy-macosx64.json @@ -0,0 +1,7 @@ +{ + "stages": "1", + "build_clang_tidy": true, + "patches": [ + "clang-tidy-ci.patch" + ] +} diff --git a/build/build-clang/clang-tidy-win64.json b/build/build-clang/clang-tidy-win64.json new file mode 100644 index 0000000000..6da85803f5 --- /dev/null +++ b/build/build-clang/clang-tidy-win64.json @@ -0,0 +1,7 @@ +{ + "stages": "1", + "build_clang_tidy": true, + "patches": [ + "clang-tidy-ci.patch" + ] +} diff --git a/build/build-clang/clang-trunk.json b/build/build-clang/clang-trunk.json new file mode 100644 index 0000000000..5f66e58947 --- /dev/null +++ b/build/build-clang/clang-trunk.json @@ -0,0 +1,21 @@ +{ + "patches": [ + "allow-unversioned-android.patch", + "find_symbolizer_linux_clang_15.patch", + "android-mangling-error_clang_12.patch", + "unpoison-thread-stacks_clang_10.patch", + "downgrade-mangling-error_clang_12.patch", + "fuzzing_ccov_build_clang_12.patch", + "revert-llvmorg-18-init-6208-g2baf4a06ef06.patch", + "revert-llvmorg-18-init-6193-gb88cffeafd39.patch", + "revert-llvmorg-18-init-6188-gc649f29c24c9.patch", + "partial-revert-llvmorg-17-init-17713-gc8e055d485ea.patch", + "revert-llvmorg-17-init-4120-g02e8eb1a438b_clang_18.patch", + "partial-revert-llvmorg-16-init-17151-gaa0883b59ae1_clang_17.patch", + "revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_18.patch", + "revert-llvmorg-15-init-13446-g7524fe962e47.patch", + "revert-llvmorg-15-init-11205-gcead4eceb01b_clang_18.patch", + "win64-ret-null-on-commitment-limit_clang_14.patch", + "compiler-rt-rss-limit-heap-profile.patch" + ] +} diff --git a/build/build-clang/compiler-rt-rss-limit-heap-profile.patch b/build/build-clang/compiler-rt-rss-limit-heap-profile.patch new file mode 100644 index 0000000000..f7dfdfcdae --- /dev/null +++ b/build/build-clang/compiler-rt-rss-limit-heap-profile.patch @@ -0,0 +1,49 @@ +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp +index 8fd398564280..b7c4820971bb 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp +@@ -29,6 +29,7 @@ void *BackgroundThread(void *arg) { + const uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb; + const uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb; + const bool heap_profile = common_flags()->heap_profile; ++ const bool rss_limit_heap_profile = common_flags()->rss_limit_heap_profile; + uptr prev_reported_rss = 0; + uptr prev_reported_stack_depot_size = 0; + bool reached_soft_rss_limit = false; +@@ -56,6 +57,10 @@ void *BackgroundThread(void *arg) { + Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n", + SanitizerToolName, hard_rss_limit_mb, current_rss_mb); + DumpProcessMap(); ++ if (rss_limit_heap_profile) { ++ Printf("\n\nHEAP PROFILE at RSS %zdMb\n", current_rss_mb); ++ __sanitizer_print_memory_profile(90, 20); ++ } + Die(); + } + if (soft_rss_limit_mb) { +@@ -63,6 +68,11 @@ void *BackgroundThread(void *arg) { + reached_soft_rss_limit = true; + Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n", + SanitizerToolName, soft_rss_limit_mb, current_rss_mb); ++ if (rss_limit_heap_profile) { ++ Printf("\n\nHEAP PROFILE at RSS %zdMb\n", current_rss_mb); ++ __sanitizer_print_memory_profile(90, 20); ++ rss_during_last_reported_profile = current_rss_mb; ++ } + SetRssLimitExceeded(true); + } else if (soft_rss_limit_mb >= current_rss_mb && + reached_soft_rss_limit) { +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +index 6148ae56067c..a0fbb8e14bd5 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +@@ -147,6 +147,9 @@ COMMON_FLAG(uptr, max_allocation_size_mb, 0, + "If non-zero, malloc/new calls larger than this size will return " + "nullptr (or crash if allocator_may_return_null=false).") + COMMON_FLAG(bool, heap_profile, false, "Experimental heap profiler, asan-only") ++COMMON_FLAG(bool, rss_limit_heap_profile, false, ++ "Experimental heap profiler (only when hard/soft rss limit " ++ "exceeded, asan-only") + COMMON_FLAG(s32, allocator_release_to_os_interval_ms, + ((bool)SANITIZER_FUCHSIA || (bool)SANITIZER_WINDOWS) ? -1 : 5000, + "Only affects a 64-bit allocator. If set, tries to release unused " diff --git a/build/build-clang/downgrade-mangling-error_clang_12.patch b/build/build-clang/downgrade-mangling-error_clang_12.patch new file mode 100644 index 0000000000..ad31306ff3 --- /dev/null +++ b/build/build-clang/downgrade-mangling-error_clang_12.patch @@ -0,0 +1,23 @@ +Downgrade unimplemented mangling diagnostic from error to note. +This codepath is exercised by MozsearchIndexer.cpp (the searchfox +indexer) when indexing on Windows. We can do without having the +unimplemented bits for now as long the compiler doesn't fail the +build. See also https://bugs.llvm.org/show_bug.cgi?id=39294 + +diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp +index 4420f6a2c1c3..4d9a6434d245 100644 +--- a/clang/lib/AST/ItaniumMangle.cpp ++++ b/clang/lib/AST/ItaniumMangle.cpp +@@ -4028,10 +4028,11 @@ recurse: + if (!NullOut) { + // As bad as this diagnostic is, it's better than crashing. + DiagnosticsEngine &Diags = Context.getDiags(); +- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, ++ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Remark, + "cannot yet mangle expression type %0"); + Diags.Report(E->getExprLoc(), DiagID) + << E->getStmtClassName() << E->getSourceRange(); ++ Out << "MOZ_WE_HACKED_AROUND_BUG_1418415"; + return; + } + break; diff --git a/build/build-clang/find_symbolizer_linux_clang_10.patch b/build/build-clang/find_symbolizer_linux_clang_10.patch new file mode 100644 index 0000000000..1ddb02024d --- /dev/null +++ b/build/build-clang/find_symbolizer_linux_clang_10.patch @@ -0,0 +1,58 @@ +We currently need this patch because ASan only searches PATH to find the +llvm-symbolizer binary to symbolize ASan traces. On testing machines, this +can be installed in PATH easily. However, for e.g. the ASan Nightly Project, +where we ship an ASan build, including llvm-symbolizer, to the user, we +cannot expect llvm-symbolizer to be on PATH. Instead, we should try to look +it up next to the binary. This patch implements the functionality for Linux +only until there is similar functionality provided upstream. + +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +index 79930d79425..cfb4f90c0d5 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +@@ -20,6 +20,10 @@ + #include "sanitizer_common.h" + #include "sanitizer_file.h" + ++#if SANITIZER_LINUX ++#include "sanitizer_posix.h" ++#endif ++ + namespace __sanitizer { + + void CatastrophicErrorWrite(const char *buffer, uptr length) { +@@ -194,6 +198,34 @@ char *FindPathToBinary(const char *name) { + if (*end == '\0') break; + beg = end + 1; + } ++ ++#if SANITIZER_LINUX ++ // If we cannot find the requested binary in PATH, we should try to locate ++ // it next to the binary, in case it is shipped with the build itself ++ // (e.g. llvm-symbolizer shipped with sanitizer build to symbolize on client. ++ if (internal_readlink("/proc/self/exe", buffer.data(), kMaxPathLength) < 0) ++ return nullptr; ++ ++ uptr buf_len = internal_strlen(buffer.data()); ++ ++ /* Avoid using dirname() here */ ++ while (buf_len > 0) { ++ if (buffer[buf_len - 1] == '/') ++ break; ++ buf_len--; ++ } ++ ++ if (!buf_len) ++ return nullptr; ++ ++ if (buf_len + name_len + 1 <= kMaxPathLength) { ++ internal_memcpy(&buffer[buf_len], name, name_len); ++ buffer[buf_len + name_len] = '\0'; ++ if (FileExists(buffer.data())) ++ return internal_strdup(buffer.data()); ++ } ++#endif ++ + return nullptr; + } + diff --git a/build/build-clang/find_symbolizer_linux_clang_15.patch b/build/build-clang/find_symbolizer_linux_clang_15.patch new file mode 100644 index 0000000000..63309e8f00 --- /dev/null +++ b/build/build-clang/find_symbolizer_linux_clang_15.patch @@ -0,0 +1,53 @@ +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +index 7ef499ce07b1..8fd682f943fe 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +@@ -21,6 +21,10 @@ + #include "sanitizer_file.h" + # include "sanitizer_interface_internal.h" + ++#if SANITIZER_LINUX ++#include "sanitizer_posix.h" ++#endif ++ + namespace __sanitizer { + + void CatastrophicErrorWrite(const char *buffer, uptr length) { +@@ -206,11 +210,35 @@ char *FindPathToBinary(const char *name) { + return internal_strdup(name); + } + ++ uptr name_len = internal_strlen(name); ++ InternalMmapVector<char> buffer(kMaxPathLength); ++ ++#if SANITIZER_LINUX ++ // If we cannot find the requested binary in PATH, we should try to locate ++ // it next to the binary, in case it is shipped with the build itself ++ // (e.g. llvm-symbolizer shipped with sanitizer build to symbolize on client. ++ if (internal_readlink("/proc/self/exe", buffer.data(), kMaxPathLength) >= 0) { ++ uptr buf_len = internal_strlen(buffer.data()); ++ ++ /* Avoid using dirname() here */ ++ while (buf_len > 0) { ++ if (buffer[buf_len - 1] == '/') ++ break; ++ buf_len--; ++ } ++ ++ if (buf_len && buf_len + name_len + 1 <= kMaxPathLength) { ++ internal_memcpy(&buffer[buf_len], name, name_len); ++ buffer[buf_len + name_len] = '\0'; ++ if (FileExists(buffer.data())) ++ return internal_strdup(buffer.data()); ++ } ++ } ++#endif ++ + const char *path = GetEnv("PATH"); + if (!path) + return nullptr; +- uptr name_len = internal_strlen(name); +- InternalMmapVector<char> buffer(kMaxPathLength); + const char *beg = path; + while (true) { + const char *end = internal_strchrnul(beg, kPathSeparator); diff --git a/build/build-clang/fuzzing_ccov_build_clang_12.patch b/build/build-clang/fuzzing_ccov_build_clang_12.patch new file mode 100644 index 0000000000..1b60a95b91 --- /dev/null +++ b/build/build-clang/fuzzing_ccov_build_clang_12.patch @@ -0,0 +1,27 @@ +From 98bf90ef5ea3dd848ce7d81a662eb7499d11c91c Mon Sep 17 00:00:00 2001 +From: Calixte Denizet <calixte.denizet@gmail.com> +Date: Fri, 16 Apr 2021 10:05:34 +0200 +Subject: [PATCH] [Gcov] Don't run global destructor in ccov builds when env + MOZ_FUZZING_CCOV is existing + +--- + compiler-rt/lib/profile/GCDAProfiling.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c +index 4293e8f7b5bf..6cda4bc7601f 100644 +--- a/compiler-rt/lib/profile/GCDAProfiling.c ++++ b/compiler-rt/lib/profile/GCDAProfiling.c +@@ -586,6 +586,9 @@ void llvm_writeout_files(void) { + __attribute__((destructor(100))) + #endif + static void llvm_writeout_and_clear(void) { ++ if (getenv("MOZ_FUZZING_CCOV")) { ++ return; ++ } + llvm_writeout_files(); + fn_list_remove(&writeout_fn_list); + } +-- +2.30.2 + diff --git a/build/build-clang/linux64.json b/build/build-clang/linux64.json new file mode 100644 index 0000000000..48690dbdaa --- /dev/null +++ b/build/build-clang/linux64.json @@ -0,0 +1,5 @@ +{ + "cc": "/usr/lib/llvm-13/bin/clang", + "cxx": "/usr/lib/llvm-13/bin/clang++", + "as": "/usr/lib/llvm-13/bin/clang" +} diff --git a/build/build-clang/llvmorg-10-init-136-gb288d90b39f4.patch b/build/build-clang/llvmorg-10-init-136-gb288d90b39f4.patch new file mode 100644 index 0000000000..c5ca0ba0ee --- /dev/null +++ b/build/build-clang/llvmorg-10-init-136-gb288d90b39f4.patch @@ -0,0 +1,37 @@ +From 79e6696d121b978b4482ce74119c6bbc7a9ce30f Mon Sep 17 00:00:00 2001 +From: Than McIntosh <thanm@google.com> +Date: Fri, 19 Jul 2019 13:13:54 +0000 +Subject: [PATCH] [NFC] include cstdint/string prior to using uint8_t/string + +Summary: include proper header prior to use of uint8_t typedef +and std::string. + +Subscribers: llvm-commits + +Reviewers: cherry + +Tags: #llvm + +Differential Revision: https://reviews.llvm.org/D64937 + +llvm-svn: 366572 +--- + llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +index 9e3478e9fd29..efd55339418b 100644 +--- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h ++++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +@@ -4,6 +4,8 @@ + #include "llvm/Demangle/Compiler.h" + #include "llvm/Demangle/StringView.h" + #include <array> ++#include <cstdint> ++#include <string> + + class OutputStream; + +-- +2.41.0.3.g1cb8d410ac + diff --git a/build/build-clang/llvmorg-15-init-16512-g4b1e3d193706.patch b/build/build-clang/llvmorg-15-init-16512-g4b1e3d193706.patch new file mode 100644 index 0000000000..5ddb6a52de --- /dev/null +++ b/build/build-clang/llvmorg-15-init-16512-g4b1e3d193706.patch @@ -0,0 +1,138 @@ +From 8482662676a4b6ef79a718c8c09943cb15241664 Mon Sep 17 00:00:00 2001 +From: Tom Stellard <tstellar@redhat.com> +Date: Tue, 21 Jun 2022 22:22:11 -0700 +Subject: [PATCH] [gold] Ignore bitcode from sections inside object files + +-fembed-bitcode will put bitcode into special sections within object +files, but this is not meant to be used by LTO, so the gold plugin +should ignore it. + +https://github.com/llvm/llvm-project/issues/47216 + +Reviewed By: tejohnson, MaskRay + +Differential Revision: https://reviews.llvm.org/D116995 +--- + llvm/docs/BitCodeFormat.rst | 3 ++- + llvm/docs/GoldPlugin.rst | 4 ++++ + .../tools/gold/X86/Inputs/bcsection-lib.ll | 6 +++++ + llvm/test/tools/gold/X86/Inputs/bcsection.s | 5 ++++ + llvm/test/tools/gold/X86/bcsection.ll | 23 +++++++++++++++---- + llvm/tools/gold/gold-plugin.cpp | 8 +++++++ + 6 files changed, 43 insertions(+), 6 deletions(-) + create mode 100644 llvm/test/tools/gold/X86/Inputs/bcsection-lib.ll + +diff --git a/llvm/docs/BitCodeFormat.rst b/llvm/docs/BitCodeFormat.rst +index 8e81a7daa459..df1f6915d7d5 100644 +--- a/llvm/docs/BitCodeFormat.rst ++++ b/llvm/docs/BitCodeFormat.rst +@@ -475,7 +475,8 @@ formats. This wrapper format is useful for accommodating LTO in compilation + pipelines where intermediate objects must be native object files which contain + metadata in other sections. + +-Not all tools support this format. ++Not all tools support this format. For example, lld and the gold plugin will ++ignore these sections when linking object files. + + .. _encoding of LLVM IR: + +diff --git a/llvm/docs/GoldPlugin.rst b/llvm/docs/GoldPlugin.rst +index ce310bc2cf3c..07d2fc203eba 100644 +--- a/llvm/docs/GoldPlugin.rst ++++ b/llvm/docs/GoldPlugin.rst +@@ -17,6 +17,10 @@ and above also supports LTO via plugins. However, usage of the LLVM + gold plugin with ld.bfd is not tested and therefore not officially + supported or recommended. + ++As of LLVM 15, the gold plugin will ignore bitcode from the ``.llvmbc`` ++section inside of ELF object files. However, LTO with bitcode files ++is still supported. ++ + .. _`gold linker`: http://sourceware.org/binutils + .. _`GCC LTO`: http://gcc.gnu.org/wiki/LinkTimeOptimization + .. _`gold plugin interface`: http://gcc.gnu.org/wiki/whopr/driver +diff --git a/llvm/test/tools/gold/X86/Inputs/bcsection-lib.ll b/llvm/test/tools/gold/X86/Inputs/bcsection-lib.ll +new file mode 100644 +index 000000000000..ef3557c19cdc +--- /dev/null ++++ b/llvm/test/tools/gold/X86/Inputs/bcsection-lib.ll +@@ -0,0 +1,6 @@ ++declare void @elf_func() ++ ++define i32 @lib_func() { ++ call void @elf_func() ++ ret i32 0 ++} +diff --git a/llvm/test/tools/gold/X86/Inputs/bcsection.s b/llvm/test/tools/gold/X86/Inputs/bcsection.s +index ede1e5c532dd..c523612563b4 100644 +--- a/llvm/test/tools/gold/X86/Inputs/bcsection.s ++++ b/llvm/test/tools/gold/X86/Inputs/bcsection.s +@@ -1,2 +1,7 @@ ++.global elf_func ++ ++elf_func: ++ ret ++ + .section .llvmbc + .incbin "bcsection.bc" +diff --git a/llvm/test/tools/gold/X86/bcsection.ll b/llvm/test/tools/gold/X86/bcsection.ll +index 6d3481f8f966..09882d83fe91 100644 +--- a/llvm/test/tools/gold/X86/bcsection.ll ++++ b/llvm/test/tools/gold/X86/bcsection.ll +@@ -2,16 +2,29 @@ + ; RUN: llvm-as -o %t/bcsection.bc %s + + ; RUN: llvm-mc -I=%t -filetype=obj -triple=x86_64-unknown-unknown -o %t/bcsection.bco %p/Inputs/bcsection.s +-; RUN: llvm-nm --no-llvm-bc %t/bcsection.bco 2>&1 | FileCheck %s -check-prefix=NO-SYMBOLS +-; NO-SYMBOLS: no symbols ++; RUN: llc -filetype=obj -mtriple=x86_64-unknown-unknown -o %t/bcsection-lib.o %p/Inputs/bcsection-lib.ll + +-; RUN: %gold -r -o %t/bcsection.o -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold%shlibext %t/bcsection.bco +-; RUN: llvm-nm --no-llvm-bc %t/bcsection.o | FileCheck %s ++; RUN: %gold -shared --no-undefined -o %t/bcsection.so -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold%shlibext %t/bcsection.bco %t/bcsection-lib.o ++ ++; This test checks that the gold plugin does not attempt to use the bitcode ++; in the .llvmbc section for LTO. bcsection-lib.o calls a function that is ++; present the symbol table of bcsection.bco, but not included in the embedded ++; bitcode. If the linker were to use the bitcode, then the symbols in the ++; symbol table of bcsection.bco will be ignored and the link will fail. ++; ++; bcsection.bco: ++; .text: ++; elf_func ++; .llvmbc: ++; bitcode_func ++; ++; bcsection-lib.o: ++; calls elf_func() + + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-unknown-unknown" + + ; CHECK: main +-define i32 @main() { ++define i32 @bitcode_func() { + ret i32 0 + } +diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp +index 180c181368e3..294c7a3d6178 100644 +--- a/llvm/tools/gold/gold-plugin.cpp ++++ b/llvm/tools/gold/gold-plugin.cpp +@@ -540,6 +540,14 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, + BufferRef = Buffer->getMemBufferRef(); + } + ++ // Only use bitcode files for LTO. InputFile::create() will load bitcode ++ // from the .llvmbc section within a binary object, this bitcode is typically ++ // generated by -fembed-bitcode and is not to be used by LLVMgold.so for LTO. ++ if (identify_magic(BufferRef.getBuffer()) != file_magic::bitcode) { ++ *claimed = 0; ++ return LDPS_OK; ++ } ++ + *claimed = 1; + + Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef); +-- +2.37.1.1.g659da70093 + diff --git a/build/build-clang/macosx64-aarch64.json b/build/build-clang/macosx64-aarch64.json new file mode 100644 index 0000000000..ecbb483e77 --- /dev/null +++ b/build/build-clang/macosx64-aarch64.json @@ -0,0 +1,3 @@ +{ + "target": "aarch64-apple-darwin" +} diff --git a/build/build-clang/macosx64.json b/build/build-clang/macosx64.json new file mode 100644 index 0000000000..2576c0c05f --- /dev/null +++ b/build/build-clang/macosx64.json @@ -0,0 +1,9 @@ +{ + "target": "x86_64-apple-darwin", + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++", + "as": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "ar": "{MOZ_FETCHES_DIR}/clang/bin/llvm-ar", + "ranlib": "{MOZ_FETCHES_DIR}/clang/bin/llvm-ranlib", + "ld": "{MOZ_FETCHES_DIR}/clang/bin/clang" +} diff --git a/build/build-clang/partial-revert-llvmorg-16-init-17151-gaa0883b59ae1_clang_17.patch b/build/build-clang/partial-revert-llvmorg-16-init-17151-gaa0883b59ae1_clang_17.patch new file mode 100644 index 0000000000..f95caa508b --- /dev/null +++ b/build/build-clang/partial-revert-llvmorg-16-init-17151-gaa0883b59ae1_clang_17.patch @@ -0,0 +1,13 @@ +diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp +index fdae7e4bd1b7..ac607cfb1100 100644 +--- a/lld/MachO/LTO.cpp ++++ b/lld/MachO/LTO.cpp +@@ -64,8 +64,6 @@ static lto::Config createConfig() { + pm.add(createObjCARCContractPass()); + }; + +- c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty(); +- + c.TimeTraceEnabled = config->timeTraceEnabled; + c.TimeTraceGranularity = config->timeTraceGranularity; + c.DebugPassManager = config->ltoDebugPassManager; diff --git a/build/build-clang/partial-revert-llvmorg-17-init-17713-gc8e055d485ea.patch b/build/build-clang/partial-revert-llvmorg-17-init-17713-gc8e055d485ea.patch new file mode 100644 index 0000000000..96ac988380 --- /dev/null +++ b/build/build-clang/partial-revert-llvmorg-17-init-17713-gc8e055d485ea.patch @@ -0,0 +1,33 @@ +Revert the parts of c8e055d485eabf1c8830d77797e3686ced0f7754 that require +cead4eceb01b935fae07bf4a7e91911b344d2fec, which we revert. + +diff --git a/llvm/include/llvm/DebugInfo/BTF/BTFContext.h b/llvm/include/llvm/DebugInfo/BTF/BTFContext.h +index c16bee613322..7b0412b91c2e 100644 +--- a/llvm/include/llvm/DebugInfo/BTF/BTFContext.h ++++ b/llvm/include/llvm/DebugInfo/BTF/BTFContext.h +@@ -34,9 +34,6 @@ public: + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + +- DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) override; +- + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +diff --git a/llvm/lib/DebugInfo/BTF/BTFContext.cpp b/llvm/lib/DebugInfo/BTF/BTFContext.cpp +index 24898739b824..da0f9982881f 100644 +--- a/llvm/lib/DebugInfo/BTF/BTFContext.cpp ++++ b/llvm/lib/DebugInfo/BTF/BTFContext.cpp +@@ -34,11 +34,6 @@ DILineInfo BTFContext::getLineInfoForAddress(SectionedAddress Address, + return Result; + } + +-DILineInfo BTFContext::getLineInfoForDataAddress(SectionedAddress Address) { +- // BTF does not convey such information. +- return {}; +-} +- + DILineInfoTable + BTFContext::getLineInfoForAddressRange(SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier) { diff --git a/build/build-clang/profile.json b/build/build-clang/profile.json new file mode 100644 index 0000000000..746aa92452 --- /dev/null +++ b/build/build-clang/profile.json @@ -0,0 +1,6 @@ +{ + "stages": "3", + "pgo": true, + "ranlib": "{MOZ_FETCHES_DIR}/clang/bin/llvm-ranlib", + "ar": "{MOZ_FETCHES_DIR}/clang/bin/llvm-ar" +} diff --git a/build/build-clang/revert-llvmorg-15-init-11205-gcead4eceb01b_clang_16.patch b/build/build-clang/revert-llvmorg-15-init-11205-gcead4eceb01b_clang_16.patch new file mode 100644 index 0000000000..93c7e7d767 --- /dev/null +++ b/build/build-clang/revert-llvmorg-15-init-11205-gcead4eceb01b_clang_16.patch @@ -0,0 +1,1027 @@ +From cb411520cb7cd5e6e25966911ca55feb5de779e0 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Fri, 4 Nov 2022 14:51:38 +0900 +Subject: [PATCH] Revert "[symbolizer] Parse DW_TAG_variable DIs to show line + info for globals" + +This reverts commit cead4eceb01b935fae07bf4a7e91911b344d2fec for causing +yet unidentified problems on some webrtc tests under TSan (bug 1798613). +--- + llvm/include/llvm/DebugInfo/DIContext.h | 4 - + .../llvm/DebugInfo/DWARF/DWARFContext.h | 2 - + llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 7 - + llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 14 - + llvm/include/llvm/DebugInfo/PDB/PDBContext.h | 2 - + llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 97 ++-- + llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 60 --- + llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 97 ---- + llvm/lib/DebugInfo/PDB/PDBContext.cpp | 7 - + llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp | 4 - + .../Symbolize/SymbolizableObjectFile.cpp | 8 - + .../Symbolize/ELF/data-command-symtab.yaml | 3 - + .../tools/llvm-symbolizer/data-location.yaml | 450 ------------------ + llvm/test/tools/llvm-symbolizer/data.s | 3 - + 14 files changed, 61 insertions(+), 697 deletions(-) + delete mode 100644 llvm/test/tools/llvm-symbolizer/data-location.yaml + +diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h +index 9b278b696073..a9f98588cf2d 100644 +--- a/llvm/include/llvm/DebugInfo/DIContext.h ++++ b/llvm/include/llvm/DebugInfo/DIContext.h +@@ -114,8 +114,6 @@ struct DIGlobal { + std::string Name; + uint64_t Start = 0; + uint64_t Size = 0; +- std::string DeclFile; +- uint64_t DeclLine = 0; + + DIGlobal() : Name(DILineInfo::BadString) {} + }; +@@ -241,8 +239,6 @@ public: + virtual DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +- virtual DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) = 0; + virtual DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +index bf591ed554c6..3365ef8d8ee3 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +@@ -364,8 +364,6 @@ public: + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +- DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) override; + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +index 149c5ef4e493..4a4d105a2b23 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +@@ -280,13 +280,6 @@ public: + /// \returns an iterator range for the attributes of the current DIE. + iterator_range<attribute_iterator> attributes() const; + +- /// Gets the type size (in bytes) for this DIE. +- /// +- /// \param PointerSize the pointer size of the containing CU. +- /// \returns if this is a type DIE, or this DIE contains a DW_AT_type, returns +- /// the size of the type. +- std::optional<uint64_t> getTypeSize(uint64_t PointerSize); +- + class iterator; + + iterator begin() const; +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +index 9188865b4d77..0341344bc7b8 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +@@ -9,7 +9,6 @@ + #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H + #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H + +-#include "llvm/ADT/DenseSet.h" + #include "llvm/ADT/STLExtras.h" + #include "llvm/ADT/SmallVector.h" + #include "llvm/ADT/StringRef.h" +@@ -28,7 +27,6 @@ + #include <cstdint> + #include <map> + #include <memory> +-#include <set> + #include <utility> + #include <vector> + +@@ -242,11 +240,6 @@ class DWARFUnit { + /// std::map::upper_bound for address range lookup. + std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap; + +- /// Map from the location (interpreted DW_AT_location) of a DW_TAG_variable, +- /// to the end address and the corresponding DIE. +- std::map<uint64_t, std::pair<uint64_t, DWARFDie>> VariableDieMap; +- DenseSet<uint64_t> RootsParsedForVariables; +- + using die_iterator_range = + iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>; + +@@ -329,9 +322,6 @@ public: + /// Recursively update address to Die map. + void updateAddressDieMap(DWARFDie Die); + +- /// Recursively update address to variable Die map. +- void updateVariableDieMap(DWARFDie Die); +- + void setRangesSection(const DWARFSection *RS, uint64_t Base) { + RangeSection = RS; + RangeSectionBase = Base; +@@ -446,10 +436,6 @@ public: + /// cleared. + DWARFDie getSubroutineForAddress(uint64_t Address); + +- /// Returns variable DIE for the address provided. The pointer is alive as +- /// long as parsed compile unit DIEs are not cleared. +- DWARFDie getVariableForAddress(uint64_t Address); +- + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. +diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBContext.h b/llvm/include/llvm/DebugInfo/PDB/PDBContext.h +index 3163c0a1dae0..7b6793f0a639 100644 +--- a/llvm/include/llvm/DebugInfo/PDB/PDBContext.h ++++ b/llvm/include/llvm/DebugInfo/PDB/PDBContext.h +@@ -45,8 +45,6 @@ namespace pdb { + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +- DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) override; + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +index 19d7d659a86a..1bcfdecfd588 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +@@ -1053,25 +1053,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { + // First, get the offset of the compile unit. + uint64_t CUOffset = getDebugAranges()->findAddress(Address); + // Retrieve the compile unit. +- if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset)) +- return OffsetCU; +- +- // Global variables are often not found by the above search, for one of two +- // reasons: +- // 1. .debug_aranges may not include global variables. On clang, it seems we +- // put the globals in the aranges, but this isn't true for gcc. +- // 2. Even if the global variable is in a .debug_arange, global variables +- // may not be captured in the [start, end) addresses described by the +- // parent compile unit. +- // +- // So, we walk the CU's and their child DI's manually, looking for the +- // specific global variable. +- for (std::unique_ptr<DWARFUnit> &CU : compile_units()) { +- if (DWARFDie Die = CU->getVariableForAddress(Address)) { +- return static_cast<DWARFCompileUnit *>(CU.get()); +- } +- } +- return nullptr; ++ return getCompileUnitForOffset(CUOffset); + } + + DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { +@@ -1141,6 +1123,64 @@ static bool getFunctionNameAndStartLineForAddress( + return FoundResult; + } + ++static std::optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) { ++ if (auto SizeAttr = Type.find(DW_AT_byte_size)) ++ if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) ++ return Size; ++ ++ switch (Type.getTag()) { ++ case DW_TAG_pointer_type: ++ case DW_TAG_reference_type: ++ case DW_TAG_rvalue_reference_type: ++ return PointerSize; ++ case DW_TAG_ptr_to_member_type: { ++ if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) ++ if (BaseType.getTag() == DW_TAG_subroutine_type) ++ return 2 * PointerSize; ++ return PointerSize; ++ } ++ case DW_TAG_const_type: ++ case DW_TAG_immutable_type: ++ case DW_TAG_volatile_type: ++ case DW_TAG_restrict_type: ++ case DW_TAG_typedef: { ++ if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) ++ return getTypeSize(BaseType, PointerSize); ++ break; ++ } ++ case DW_TAG_array_type: { ++ DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type); ++ if (!BaseType) ++ return std::optional<uint64_t>(); ++ std::optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize); ++ if (!BaseSize) ++ return std::optional<uint64_t>(); ++ uint64_t Size = *BaseSize; ++ for (DWARFDie Child : Type) { ++ if (Child.getTag() != DW_TAG_subrange_type) ++ continue; ++ ++ if (auto ElemCountAttr = Child.find(DW_AT_count)) ++ if (std::optional<uint64_t> ElemCount = ++ ElemCountAttr->getAsUnsignedConstant()) ++ Size *= *ElemCount; ++ if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) ++ if (std::optional<int64_t> UpperBound = ++ UpperBoundAttr->getAsSignedConstant()) { ++ int64_t LowerBound = 0; ++ if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) ++ LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0); ++ Size *= *UpperBound - LowerBound + 1; ++ } ++ } ++ return Size; ++ } ++ default: ++ break; ++ } ++ return std::optional<uint64_t>(); ++} ++ + static std::optional<int64_t> + getExpressionFrameOffset(ArrayRef<uint8_t> Expr, + std::optional<unsigned> FrameBaseReg) { +@@ -1201,7 +1241,7 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, + if (std::optional<const char *> Name = dwarf::toString(*NameAttr)) + Local.Name = *Name; + if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) +- Local.Size = Type.getTypeSize(getCUAddrSize()); ++ Local.Size = getTypeSize(Type, getCUAddrSize()); + if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) { + if (const auto *LT = CU->getContext().getLineTableForUnit(CU)) + LT->getFileNameByIndex( +@@ -1242,6 +1282,7 @@ DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + DILineInfoSpecifier Spec) { + DILineInfo Result; ++ + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; +@@ -1256,22 +1297,6 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + Spec.FLIKind, Result); + } + } +- +- return Result; +-} +- +-DILineInfo +-DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { +- DILineInfo Result; +- DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); +- if (!CU) +- return Result; +- +- if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) { +- Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath); +- Result.Line = Die.getDeclLine(); +- } +- + return Result; + } + +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +index 15a2d23c4fd2..9bf15c30f714 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +@@ -492,66 +492,6 @@ void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, + CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); + } + +-std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) { +- if (auto SizeAttr = find(DW_AT_byte_size)) +- if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) +- return Size; +- +- switch (getTag()) { +- case DW_TAG_pointer_type: +- case DW_TAG_reference_type: +- case DW_TAG_rvalue_reference_type: +- return PointerSize; +- case DW_TAG_ptr_to_member_type: { +- if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) +- if (BaseType.getTag() == DW_TAG_subroutine_type) +- return 2 * PointerSize; +- return PointerSize; +- } +- case DW_TAG_const_type: +- case DW_TAG_immutable_type: +- case DW_TAG_volatile_type: +- case DW_TAG_restrict_type: +- case DW_TAG_typedef: { +- if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) +- return BaseType.getTypeSize(PointerSize); +- break; +- } +- case DW_TAG_array_type: { +- DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type); +- if (!BaseType) +- return std::nullopt; +- std::optional<uint64_t> BaseSize = BaseType.getTypeSize(PointerSize); +- if (!BaseSize) +- return std::nullopt; +- uint64_t Size = *BaseSize; +- for (DWARFDie Child : *this) { +- if (Child.getTag() != DW_TAG_subrange_type) +- continue; +- +- if (auto ElemCountAttr = Child.find(DW_AT_count)) +- if (std::optional<uint64_t> ElemCount = +- ElemCountAttr->getAsUnsignedConstant()) +- Size *= *ElemCount; +- if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) +- if (std::optional<int64_t> UpperBound = +- UpperBoundAttr->getAsSignedConstant()) { +- int64_t LowerBound = 0; +- if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) +- LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0); +- Size *= *UpperBound - LowerBound + 1; +- } +- } +- return Size; +- } +- default: +- if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) +- return BaseType.getTypeSize(PointerSize); +- break; +- } +- return std::nullopt; +-} +- + /// Helper to dump a DIE with all of its parents, but no siblings. + static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, + DIDumpOptions DumpOpts, unsigned Depth = 0) { +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +index 74667fcb92bc..148711f0246f 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +@@ -9,7 +9,6 @@ + #include "llvm/DebugInfo/DWARF/DWARFUnit.h" + #include "llvm/ADT/SmallString.h" + #include "llvm/ADT/StringRef.h" +-#include "llvm/BinaryFormat/Dwarf.h" + #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" + #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" + #include "llvm/DebugInfo/DWARF/DWARFContext.h" +@@ -19,13 +18,11 @@ + #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" + #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" + #include "llvm/DebugInfo/DWARF/DWARFDie.h" +-#include "llvm/DebugInfo/DWARF/DWARFExpression.h" + #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" + #include "llvm/DebugInfo/DWARF/DWARFListTable.h" + #include "llvm/DebugInfo/DWARF/DWARFObject.h" + #include "llvm/DebugInfo/DWARF/DWARFSection.h" + #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +-#include "llvm/Object/ObjectFile.h" + #include "llvm/Support/DataExtractor.h" + #include "llvm/Support/Errc.h" + #include "llvm/Support/Path.h" +@@ -752,100 +749,6 @@ DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { + return R->second.second; + } + +-void DWARFUnit::updateVariableDieMap(DWARFDie Die) { +- for (DWARFDie Child : Die) { +- if (isType(Child.getTag())) +- continue; +- updateVariableDieMap(Child); +- } +- +- if (Die.getTag() != DW_TAG_variable) +- return; +- +- Expected<DWARFLocationExpressionsVector> Locations = +- Die.getLocations(DW_AT_location); +- if (!Locations) { +- // Missing DW_AT_location is fine here. +- consumeError(Locations.takeError()); +- return; +- } +- +- uint64_t Address = UINT64_MAX; +- +- for (const DWARFLocationExpression &Location : *Locations) { +- uint8_t AddressSize = getAddressByteSize(); +- DataExtractor Data(Location.Expr, /*IsLittleEndian=*/true, AddressSize); +- DWARFExpression Expr(Data, AddressSize); +- auto It = Expr.begin(); +- if (It == Expr.end()) +- continue; +- +- // Match exactly the main sequence used to describe global variables: +- // `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence +- // that LLVM produces for DILocalVariables and DIGlobalVariables. If, in +- // future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is +- // a good starting point) is extended to use further expressions, this code +- // needs to be updated. +- uint64_t LocationAddr; +- if (It->getCode() == dwarf::DW_OP_addr) { +- LocationAddr = It->getRawOperand(0); +- } else if (It->getCode() == dwarf::DW_OP_addrx) { +- uint64_t DebugAddrOffset = It->getRawOperand(0); +- if (auto Pointer = getAddrOffsetSectionItem(DebugAddrOffset)) { +- LocationAddr = Pointer->Address; +- } +- } else { +- continue; +- } +- +- // Read the optional 2nd operand, a DW_OP_plus_uconst. +- if (++It != Expr.end()) { +- if (It->getCode() != dwarf::DW_OP_plus_uconst) +- continue; +- +- LocationAddr += It->getRawOperand(0); +- +- // Probe for a 3rd operand, if it exists, bail. +- if (++It != Expr.end()) +- continue; +- } +- +- Address = LocationAddr; +- break; +- } +- +- // Get the size of the global variable. If all else fails (i.e. the global has +- // no type), then we use a size of one to still allow symbolization of the +- // exact address. +- uint64_t GVSize = 1; +- if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type)) +- if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize())) +- GVSize = *Size; +- +- if (Address != UINT64_MAX) +- VariableDieMap[Address] = {Address + GVSize, Die}; +-} +- +-DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) { +- extractDIEsIfNeeded(false); +- +- auto RootDie = getUnitDIE(); +- +- auto RootLookup = RootsParsedForVariables.insert(RootDie.getOffset()); +- if (RootLookup.second) +- updateVariableDieMap(RootDie); +- +- auto R = VariableDieMap.upper_bound(Address); +- if (R == VariableDieMap.begin()) +- return DWARFDie(); +- +- // upper_bound's previous item contains Address. +- --R; +- if (Address >= R->second.first) +- return DWARFDie(); +- return R->second.second; +-} +- + void + DWARFUnit::getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl<DWARFDie> &InlinedChain) { +diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp +index e600fb7385f1..0444093d7622 100644 +--- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp ++++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp +@@ -64,13 +64,6 @@ DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address, + return Result; + } + +-DILineInfo +-PDBContext::getLineInfoForDataAddress(object::SectionedAddress Address) { +- // Unimplemented. S_GDATA and S_LDATA in CodeView (used to describe global +- // variables) aren't capable of carrying line information. +- return DILineInfo(); +-} +- + DILineInfoTable + PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address, + uint64_t Size, +diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +index 877380213f21..496c8149782e 100644 +--- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp ++++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +@@ -206,10 +206,6 @@ void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) { + Name = DILineInfo::Addr2LineBadString; + OS << Name << "\n"; + OS << Global.Start << " " << Global.Size << "\n"; +- if (Global.DeclFile.empty()) +- OS << "??:?\n"; +- else +- OS << Global.DeclFile << ":" << Global.DeclLine << "\n"; + printFooter(); + } + +diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +index d8ee9264b64f..fcff531895a2 100644 +--- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp ++++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +@@ -327,14 +327,6 @@ DIGlobal SymbolizableObjectFile::symbolizeData( + std::string FileName; + getNameFromSymbolTable(ModuleOffset.Address, Res.Name, Res.Start, Res.Size, + FileName); +- Res.DeclFile = FileName; +- +- // Try and get a better filename:lineno pair from the debuginfo, if present. +- DILineInfo DL = DebugInfoContext->getLineInfoForDataAddress(ModuleOffset); +- if (DL.Line != 0) { +- Res.DeclFile = DL.FileName; +- Res.DeclLine = DL.Line; +- } + return Res; + } + +diff --git a/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml b/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml +index 83af3111c5dd..984e444b2fda 100644 +--- a/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml ++++ b/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml +@@ -7,15 +7,12 @@ + + # CHECK: func + # CHECK-NEXT: 4096 1 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + # CHECK-NEXT: data + # CHECK-NEXT: 8192 2 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + # CHECK-NEXT: notype + # CHECK-NEXT: 8194 3 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + + --- !ELF +diff --git a/llvm/test/tools/llvm-symbolizer/data-location.yaml b/llvm/test/tools/llvm-symbolizer/data-location.yaml +deleted file mode 100644 +index 54f7d9be44a1..000000000000 +--- a/llvm/test/tools/llvm-symbolizer/data-location.yaml ++++ /dev/null +@@ -1,450 +0,0 @@ +-## Show that when "DATA" is used with an address, it forces the found location +-## to be symbolized as data, including the source information. +- +-# RUN: yaml2obj %s -o %t.so +- +-# RUN: llvm-symbolizer 'DATA 0x304d0' 'DATA 0x304d1' 'DATA 0x304d3' \ +-# RUN: 'DATA 0x304c0' 'DATA 0x304c8' 'DATA 0x304d4' 'DATA 0x304dc' \ +-# RUN: 'DATA 0x304d8' --obj=%t.so | FileCheck %s +- +-# CHECK: bss_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:1 +-# CHECK-EMPTY: +- +-## Check that lookups in the middle of the symbol are also resolved correctly. +-# CHECK: bss_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:1 +-# CHECK-EMPTY: +-# CHECK: bss_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:1 +-# CHECK-EMPTY: +- +-## Now, the remainder of the symbols. +-# CHECK-NEXT: data_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:2 +-# CHECK-EMPTY: +-# CHECK-NEXT: str +-# CHECK-NEXT: {{[0-9]+}} 8 +-# CHECK-NEXT: /tmp/file.cpp:4 +-# CHECK-EMPTY: +-# CHECK-NEXT: f()::function_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:8 +-# CHECK-EMPTY: +- +-## Including the one that includes an addend. +-# CHECK-NEXT: alpha +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:12 +-# CHECK-EMPTY: +-# CHECK-NEXT: beta +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:13 +-# CHECK-EMPTY: +- +-## Ensure there's still a global that's offset-based. +-# RUN: llvm-dwarfdump --debug-info %t.so | FileCheck %s --check-prefix=OFFSET +- +-# OFFSET: DW_AT_location (DW_OP_addrx 0x4, DW_OP_plus_uconst 0x4) +- +-################################################################################ +-## File below was generated using: +-## +-## $ clang++ -g -O3 /tmp/file.cpp -shared -fuse-ld=lld -nostdlib \ +-## -target aarch64-linux-gnuabi -mllvm -global-merge-ignore-single-use \ +-## -o /tmp/file.so +-## +-## With /tmp/file.cpp as: +-## 1: int bss_global; +-## 2: int data_global = 2; +-## 3: +-## 4: const char* str = +-## 5: "12345678"; +-## 6: +-## 7: int* f() { +-## 8: static int function_global; +-## 9: return &function_global; +-## 10: } +-## 11: +-## 12: static int alpha; +-## 13: static int beta; +-## 14: int *f(bool b) { return beta ? &alpha : β } +-## 15: +-## +-## ... then, one can get the offsets using `nm`, like: +-## $ nm out.so | grep bss_global +-## 00000000000038fc B bss_global +-## +-## Note the use of the aarch64 target (with -nostdlib in order to allow linkage +-## without libraries for cross-compilation) as well as -O3 and +-## -global-merge-ignore-single-use. This is a specific combination that makes +-## the compiler emit the `alpha` global variable with a more complex +-## DW_AT_location than just a DW_OP_addr/DW_OP_addrx. In this instance, it +-## outputs a `DW_AT_location (DW_OP_addrx 0x4, DW_OP_plus_uconst 0x4)`. +-## +-## Ideally, this would be tested by invoking clang directly on a C source file, +-## but unfortunately there's no way to do that for LLVM tests. The other option +-## is to compile IR to an objfile, but llvm-symbolizer doesn't understand that +-## two symbols can have the same address in different sections. In the code +-## above, for example, we'd have bss_global at .bss+0x0, and data_global at +-## .data+0x0, and so the symbolizer would only print one of them. Hence, we have +-## the ugly dso-to-yaml blob below. +-## +-## For now, constant strings don't have a debuginfo entry, and so can't be +-## symbolized correctly. In future (if D123534 gets merged), this can be updated +-## to include a check that llvm-symbolizer can also symbolize constant strings, +-## like `str` above (basically that &"12345678" should be symbolizable) +-## to the specific line. Then, you can find the address of the constant string +-## from the relocation: +-## +-## $ nm out.so | grep str +-## 00000000000038c0 D str +-## $ llvm-objdump -R out.so | grep 38c0 +-## 00000000000038c0 R_X86_64_RELATIVE *ABS*+0x4f8 # <-- 0x4f8 +-################################################################################ +- +---- !ELF +-FileHeader: +- Class: ELFCLASS64 +- Data: ELFDATA2LSB +- Type: ET_DYN +- Machine: EM_AARCH64 +-ProgramHeaders: +- - Type: PT_PHDR +- Flags: [ PF_R ] +- VAddr: 0x40 +- Align: 0x8 +- - Type: PT_LOAD +- Flags: [ PF_R ] +- FirstSec: .dynsym +- LastSec: .eh_frame +- Align: 0x10000 +- - Type: PT_LOAD +- Flags: [ PF_X, PF_R ] +- FirstSec: .text +- LastSec: .text +- VAddr: 0x103E4 +- Align: 0x10000 +- - Type: PT_LOAD +- Flags: [ PF_W, PF_R ] +- FirstSec: .dynamic +- LastSec: .dynamic +- VAddr: 0x20410 +- Align: 0x10000 +- - Type: PT_LOAD +- Flags: [ PF_W, PF_R ] +- FirstSec: .data +- LastSec: .bss +- VAddr: 0x304C0 +- Align: 0x10000 +- - Type: PT_DYNAMIC +- Flags: [ PF_W, PF_R ] +- FirstSec: .dynamic +- LastSec: .dynamic +- VAddr: 0x20410 +- Align: 0x8 +- - Type: PT_GNU_RELRO +- Flags: [ PF_R ] +- FirstSec: .dynamic +- LastSec: .dynamic +- VAddr: 0x20410 +- - Type: PT_GNU_EH_FRAME +- Flags: [ PF_R ] +- FirstSec: .eh_frame_hdr +- LastSec: .eh_frame_hdr +- VAddr: 0x37C +- Align: 0x4 +- - Type: PT_GNU_STACK +- Flags: [ PF_W, PF_R ] +- Align: 0x0 +-Sections: +- - Name: .dynsym +- Type: SHT_DYNSYM +- Flags: [ SHF_ALLOC ] +- Address: 0x238 +- Link: .dynstr +- AddressAlign: 0x8 +- - Name: .gnu.hash +- Type: SHT_GNU_HASH +- Flags: [ SHF_ALLOC ] +- Address: 0x2C8 +- Link: .dynsym +- AddressAlign: 0x8 +- Header: +- SymNdx: 0x1 +- Shift2: 0x1A +- BloomFilter: [ 0x400188002180000C ] +- HashBuckets: [ 0x1 ] +- HashValues: [ 0xEE8502A, 0xEE85016, 0xC033991C, 0x61F7372E, 0xB88AB7F ] +- - Name: .hash +- Type: SHT_HASH +- Flags: [ SHF_ALLOC ] +- Address: 0x2F8 +- Link: .dynsym +- AddressAlign: 0x4 +- Bucket: [ 5, 0, 4, 0, 3, 0 ] +- Chain: [ 0, 0, 0, 1, 2, 0 ] +- - Name: .dynstr +- Type: SHT_STRTAB +- Flags: [ SHF_ALLOC ] +- Address: 0x330 +- AddressAlign: 0x1 +- - Name: .rela.dyn +- Type: SHT_RELA +- Flags: [ SHF_ALLOC ] +- Address: 0x358 +- Link: .dynsym +- AddressAlign: 0x8 +- Relocations: +- - Offset: 0x304C8 +- Type: R_AARCH64_RELATIVE +- Addend: 880 +- - Name: .rodata +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ] +- Address: 0x370 +- AddressAlign: 0x1 +- EntSize: 0x1 +- Content: '313233343536373800' +- - Name: .eh_frame_hdr +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC ] +- Address: 0x37C +- AddressAlign: 0x4 +- Content: 011B033B18000000020000006800010034000000740001004C000000 +- - Name: .eh_frame +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC ] +- Address: 0x398 +- AddressAlign: 0x8 +- Content: 1400000000000000017A5200017C1E011B0C1F0000000000140000001C0000002C0001000C00000000000000000000001400000034000000200001001C000000000000000000000000000000 +- - Name: .text +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC, SHF_EXECINSTR ] +- Address: 0x103E4 +- AddressAlign: 0x4 +- Content: 0001009000501391C0035FD60801009008611391E90308AA2A4540B85F0100710001899AC0035FD6 +- - Name: .dynamic +- Type: SHT_DYNAMIC +- Flags: [ SHF_WRITE, SHF_ALLOC ] +- Address: 0x20410 +- Link: .dynstr +- AddressAlign: 0x8 +- Entries: +- - Tag: DT_RELA +- Value: 0x358 +- - Tag: DT_RELASZ +- Value: 0x18 +- - Tag: DT_RELAENT +- Value: 0x18 +- - Tag: DT_RELACOUNT +- Value: 0x1 +- - Tag: DT_SYMTAB +- Value: 0x238 +- - Tag: DT_SYMENT +- Value: 0x18 +- - Tag: DT_STRTAB +- Value: 0x330 +- - Tag: DT_STRSZ +- Value: 0x28 +- - Tag: DT_GNU_HASH +- Value: 0x2C8 +- - Tag: DT_HASH +- Value: 0x2F8 +- - Tag: DT_NULL +- Value: 0x0 +- - Name: .data +- Type: SHT_PROGBITS +- Flags: [ SHF_WRITE, SHF_ALLOC ] +- Address: 0x304C0 +- AddressAlign: 0x8 +- Content: '02000000000000000000000000000000' +- - Name: .bss +- Type: SHT_NOBITS +- Flags: [ SHF_WRITE, SHF_ALLOC ] +- Address: 0x304D0 +- AddressAlign: 0x4 +- Size: 0x10 +- - Name: .debug_abbrev +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: 011101252513050325721710171B25111B120673170000023400032549133F193A0B3B0B0218000003240003253E0B0B0B0000040F004913000005260049130000062E01111B120640187A196E2503253A0B3B0B49133F190000073400032549133A0B3B0B02180000083400032549133A0B3B0B02186E25000009050003253A0B3B0B4913000000 +- - Name: .debug_info +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: AB0000000500010800000000010021000108000000000000000205280000000800000002032E000000000102A1000304050402052E000000000202A101020648000000000402A102044D00000005520000000307080106050C000000016F0D0E0007A500000007082E000000000802A1030008092E000000000D02A1040A080B2E000000000C04A10423040C06061C000000016F0F0E000EA50000000910000EAA00000000042E0000000311020100 +- - Name: .debug_str_offsets +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: 4C00000005000000A2000000000000002C00000059000000280000001C00000072000000640000008C0000008700000069000000140000007B0000009C0000001A0000000E0000008500000076000000 +- - Name: .comment +- Type: SHT_PROGBITS +- Flags: [ SHF_MERGE, SHF_STRINGS ] +- AddressAlign: 0x1 +- EntSize: 0x1 +- Content: 4C696E6B65723A204C4C442031352E302E300000636C616E672076657273696F6E2031352E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A6563742E67697420306462616566363162353666306566306162306366333865613932666663316633356265653366662900 +- - Name: .debug_line +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: 620000000500080037000000010101FB0E0D00010101010000000100000101011F010E00000003011F020F051E0100000000006C97BBE59F7DC6A9EA956633431DA63E0400000902E4030100000000001805030A140500BF05190A0105120608740204000101 +- - Name: .debug_line_str +- Type: SHT_PROGBITS +- Flags: [ SHF_MERGE, SHF_STRINGS ] +- AddressAlign: 0x1 +- EntSize: 0x1 +- Content: 2F746D702F66696C652E637070002F7573722F6C6F63616C2F676F6F676C652F686F6D652F6D69746368702F6C6C766D2D6275696C642F6F707400 +-Symbols: +- - Name: file.cpp +- Type: STT_FILE +- Index: SHN_ABS +- - Name: '$x.0' +- Section: .text +- Value: 0x103E4 +- - Name: _ZZ1fvE15function_global +- Type: STT_OBJECT +- Section: .bss +- Value: 0x304D4 +- Size: 0x4 +- - Name: '$d.1' +- Section: .bss +- Value: 0x304D0 +- - Name: '$d.2' +- Section: .data +- Value: 0x304C0 +- - Name: '$d.3' +- Section: .rodata +- Value: 0x370 +- - Name: '$d.4' +- Section: .debug_abbrev +- - Name: '$d.5' +- Section: .debug_info +- - Name: '$d.6' +- Section: .debug_str_offsets +- - Name: '$d.7' +- Section: .debug_str +- Value: 0xA2 +- - Name: '$d.8' +- Section: .debug_addr +- - Name: _ZL4beta +- Type: STT_OBJECT +- Section: .bss +- Value: 0x304D8 +- Size: 0x4 +- - Name: _ZL5alpha +- Type: STT_OBJECT +- Section: .bss +- Value: 0x304DC +- Size: 0x4 +- - Name: '$d.9' +- Section: .comment +- Value: 0x13 +- - Name: '$d.10' +- Section: .eh_frame +- Value: 0x398 +- - Name: '$d.11' +- Section: .debug_line +- - Name: '$d.12' +- Section: .debug_line_str +- Value: 0xE +- - Name: _DYNAMIC +- Section: .dynamic +- Value: 0x20410 +- Other: [ STV_HIDDEN ] +- - Name: _Z1fv +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103E4 +- Size: 0xC +- - Name: _Z1fb +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103F0 +- Size: 0x1C +- - Name: bss_global +- Type: STT_OBJECT +- Section: .bss +- Binding: STB_GLOBAL +- Value: 0x304D0 +- Size: 0x4 +- - Name: data_global +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C0 +- Size: 0x4 +- - Name: str +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C8 +- Size: 0x8 +-DynamicSymbols: +- - Name: _Z1fv +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103E4 +- Size: 0xC +- - Name: _Z1fb +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103F0 +- Size: 0x1C +- - Name: bss_global +- Type: STT_OBJECT +- Section: .bss +- Binding: STB_GLOBAL +- Value: 0x304D0 +- Size: 0x4 +- - Name: data_global +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C0 +- Size: 0x4 +- - Name: str +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C8 +- Size: 0x8 +-DWARF: +- debug_str: +- - '/tmp/file.cpp' +- - _Z1fb +- - alpha +- - f +- - data_global +- - int +- - '/usr/local/google/home/mitchp/llvm-build/opt' +- - bss_global +- - char +- - _ZL4beta +- - str +- - bool +- - _ZL5alpha +- - b +- - beta +- - function_global +- - _Z1fv +- - 'clang version 15.0.0 (https://github.com/llvm/llvm-project.git 0dbaef61b56f0ef0ab0cf38ea92ffc1f35bee3ff)' +- debug_addr: +- - Length: 0x3C +- Version: 0x5 +- AddressSize: 0x8 +- Entries: +- - Address: 0x304D0 +- - Address: 0x304C0 +- - Address: 0x304C8 +- - Address: 0x304D4 +- - Address: 0x304D8 +- - Address: 0x103E4 +- - Address: 0x103F0 +-... +diff --git a/llvm/test/tools/llvm-symbolizer/data.s b/llvm/test/tools/llvm-symbolizer/data.s +index cc9503c59141..e8039f146dbd 100644 +--- a/llvm/test/tools/llvm-symbolizer/data.s ++++ b/llvm/test/tools/llvm-symbolizer/data.s +@@ -7,12 +7,9 @@ + + # CHECK: d1 + # CHECK-NEXT: 0 8 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + # CHECK-NEXT: d2 + # CHECK-NEXT: 8 4 +-# CHECK-NEXT: ??:? +-# CHECK-EMPTY: + + d1: + .quad 0x1122334455667788 +-- +2.38.1.1.g6d9df9d320 + diff --git a/build/build-clang/revert-llvmorg-15-init-11205-gcead4eceb01b_clang_18.patch b/build/build-clang/revert-llvmorg-15-init-11205-gcead4eceb01b_clang_18.patch new file mode 100644 index 0000000000..908374789c --- /dev/null +++ b/build/build-clang/revert-llvmorg-15-init-11205-gcead4eceb01b_clang_18.patch @@ -0,0 +1,972 @@ +From cb411520cb7cd5e6e25966911ca55feb5de779e0 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Fri, 4 Nov 2022 14:51:38 +0900 +Subject: [PATCH] Revert "[symbolizer] Parse DW_TAG_variable DIs to show line + info for globals" + +This reverts commit cead4eceb01b935fae07bf4a7e91911b344d2fec for causing +yet unidentified problems on some webrtc tests under TSan (bug 1798613). +--- + llvm/include/llvm/DebugInfo/DIContext.h | 4 - + .../llvm/DebugInfo/DWARF/DWARFContext.h | 2 - + llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 7 - + llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 14 - + llvm/include/llvm/DebugInfo/PDB/PDBContext.h | 2 - + llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 97 ++-- + llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 60 --- + llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 97 ---- + llvm/lib/DebugInfo/PDB/PDBContext.cpp | 7 - + llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp | 4 - + .../Symbolize/SymbolizableObjectFile.cpp | 8 - + .../Symbolize/ELF/data-command-symtab.yaml | 3 - + .../tools/llvm-symbolizer/data-location.yaml | 450 ------------------ + llvm/test/tools/llvm-symbolizer/data.s | 3 - + 14 files changed, 61 insertions(+), 697 deletions(-) + delete mode 100644 llvm/test/tools/llvm-symbolizer/data-location.yaml + +diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h +index 9b278b696073..a9f98588cf2d 100644 +--- a/llvm/include/llvm/DebugInfo/DIContext.h ++++ b/llvm/include/llvm/DebugInfo/DIContext.h +@@ -114,8 +114,6 @@ struct DIGlobal { + std::string Name; + uint64_t Start = 0; + uint64_t Size = 0; +- std::string DeclFile; +- uint64_t DeclLine = 0; + + DIGlobal() : Name(DILineInfo::BadString) {} + }; +@@ -241,8 +239,6 @@ public: + virtual DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +- virtual DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) = 0; + virtual DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +index bf591ed554c6..3365ef8d8ee3 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +@@ -364,8 +364,6 @@ public: + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +- DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) override; + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +index 149c5ef4e493..4a4d105a2b23 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +@@ -280,13 +280,6 @@ public: + /// \returns an iterator range for the attributes of the current DIE. + iterator_range<attribute_iterator> attributes() const; + +- /// Gets the type size (in bytes) for this DIE. +- /// +- /// \param PointerSize the pointer size of the containing CU. +- /// \returns if this is a type DIE, or this DIE contains a DW_AT_type, returns +- /// the size of the type. +- std::optional<uint64_t> getTypeSize(uint64_t PointerSize); +- + class iterator; + + iterator begin() const; +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +index 9188865b4d77..0341344bc7b8 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +@@ -9,7 +9,6 @@ + #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H + #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H + +-#include "llvm/ADT/DenseSet.h" + #include "llvm/ADT/STLExtras.h" + #include "llvm/ADT/SmallVector.h" + #include "llvm/ADT/StringRef.h" +@@ -28,7 +27,6 @@ + #include <cstdint> + #include <map> + #include <memory> +-#include <set> + #include <utility> + #include <vector> + +@@ -242,11 +240,6 @@ class DWARFUnit { + /// std::map::upper_bound for address range lookup. + std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap; + +- /// Map from the location (interpreted DW_AT_location) of a DW_TAG_variable, +- /// to the end address and the corresponding DIE. +- std::map<uint64_t, std::pair<uint64_t, DWARFDie>> VariableDieMap; +- DenseSet<uint64_t> RootsParsedForVariables; +- + using die_iterator_range = + iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>; + +@@ -329,9 +322,6 @@ public: + /// Recursively update address to Die map. + void updateAddressDieMap(DWARFDie Die); + +- /// Recursively update address to variable Die map. +- void updateVariableDieMap(DWARFDie Die); +- + void setRangesSection(const DWARFSection *RS, uint64_t Base) { + RangeSection = RS; + RangeSectionBase = Base; +@@ -446,10 +436,6 @@ public: + /// cleared. + DWARFDie getSubroutineForAddress(uint64_t Address); + +- /// Returns variable DIE for the address provided. The pointer is alive as +- /// long as parsed compile unit DIEs are not cleared. +- DWARFDie getVariableForAddress(uint64_t Address); +- + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. +diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBContext.h b/llvm/include/llvm/DebugInfo/PDB/PDBContext.h +index 3163c0a1dae0..7b6793f0a639 100644 +--- a/llvm/include/llvm/DebugInfo/PDB/PDBContext.h ++++ b/llvm/include/llvm/DebugInfo/PDB/PDBContext.h +@@ -45,8 +45,6 @@ namespace pdb { + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +- DILineInfo +- getLineInfoForDataAddress(object::SectionedAddress Address) override; + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +index 19d7d659a86a..1bcfdecfd588 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +@@ -1053,25 +1053,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { + // First, get the offset of the compile unit. + uint64_t CUOffset = getDebugAranges()->findAddress(Address); + // Retrieve the compile unit. +- if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset)) +- return OffsetCU; +- +- // Global variables are often not found by the above search, for one of two +- // reasons: +- // 1. .debug_aranges may not include global variables. On clang, it seems we +- // put the globals in the aranges, but this isn't true for gcc. +- // 2. Even if the global variable is in a .debug_arange, global variables +- // may not be captured in the [start, end) addresses described by the +- // parent compile unit. +- // +- // So, we walk the CU's and their child DI's manually, looking for the +- // specific global variable. +- for (std::unique_ptr<DWARFUnit> &CU : compile_units()) { +- if (CU->getVariableForAddress(Address)) { +- return static_cast<DWARFCompileUnit *>(CU.get()); +- } +- } +- return nullptr; ++ return getCompileUnitForOffset(CUOffset); + } + + DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address, +@@ -1141,6 +1123,64 @@ static bool getFunctionNameAndStartLineForAddress( + return FoundResult; + } + ++static std::optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) { ++ if (auto SizeAttr = Type.find(DW_AT_byte_size)) ++ if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) ++ return Size; ++ ++ switch (Type.getTag()) { ++ case DW_TAG_pointer_type: ++ case DW_TAG_reference_type: ++ case DW_TAG_rvalue_reference_type: ++ return PointerSize; ++ case DW_TAG_ptr_to_member_type: { ++ if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) ++ if (BaseType.getTag() == DW_TAG_subroutine_type) ++ return 2 * PointerSize; ++ return PointerSize; ++ } ++ case DW_TAG_const_type: ++ case DW_TAG_immutable_type: ++ case DW_TAG_volatile_type: ++ case DW_TAG_restrict_type: ++ case DW_TAG_typedef: { ++ if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) ++ return getTypeSize(BaseType, PointerSize); ++ break; ++ } ++ case DW_TAG_array_type: { ++ DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type); ++ if (!BaseType) ++ return std::optional<uint64_t>(); ++ std::optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize); ++ if (!BaseSize) ++ return std::optional<uint64_t>(); ++ uint64_t Size = *BaseSize; ++ for (DWARFDie Child : Type) { ++ if (Child.getTag() != DW_TAG_subrange_type) ++ continue; ++ ++ if (auto ElemCountAttr = Child.find(DW_AT_count)) ++ if (std::optional<uint64_t> ElemCount = ++ ElemCountAttr->getAsUnsignedConstant()) ++ Size *= *ElemCount; ++ if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) ++ if (std::optional<int64_t> UpperBound = ++ UpperBoundAttr->getAsSignedConstant()) { ++ int64_t LowerBound = 0; ++ if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) ++ LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0); ++ Size *= *UpperBound - LowerBound + 1; ++ } ++ } ++ return Size; ++ } ++ default: ++ break; ++ } ++ return std::optional<uint64_t>(); ++} ++ + static std::optional<int64_t> + getExpressionFrameOffset(ArrayRef<uint8_t> Expr, + std::optional<unsigned> FrameBaseReg) { +@@ -1201,7 +1241,7 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, + if (std::optional<const char *> Name = dwarf::toString(*NameAttr)) + Local.Name = *Name; + if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) +- Local.Size = Type.getTypeSize(getCUAddrSize()); ++ Local.Size = getTypeSize(Type, getCUAddrSize()); + if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) { + if (const auto *LT = CU->getContext().getLineTableForUnit(CU)) + LT->getFileNameByIndex( +@@ -1242,6 +1282,7 @@ DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + DILineInfoSpecifier Spec) { + DILineInfo Result; ++ + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; +@@ -1256,22 +1297,6 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + Spec.FLIKind, Result); + } + } +- +- return Result; +-} +- +-DILineInfo +-DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { +- DILineInfo Result; +- DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); +- if (!CU) +- return Result; +- +- if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) { +- Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath); +- Result.Line = Die.getDeclLine(); +- } +- + return Result; + } + +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +index 66492f7bf804..357b172bf99b 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +@@ -556,11 +556,6 @@ getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize, + return std::nullopt; + } + +-std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) { +- SmallPtrSet<const DWARFDebugInfoEntry *, 4> Visited; +- return getTypeSizeImpl(*this, PointerSize, Visited); +-} +- + /// Helper to dump a DIE with all of its parents, but no siblings. + static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, + DIDumpOptions DumpOpts, unsigned Depth = 0) { +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +index 74667fcb92bc..148711f0246f 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +@@ -9,7 +9,6 @@ + #include "llvm/DebugInfo/DWARF/DWARFUnit.h" + #include "llvm/ADT/SmallString.h" + #include "llvm/ADT/StringRef.h" +-#include "llvm/BinaryFormat/Dwarf.h" + #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" + #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" + #include "llvm/DebugInfo/DWARF/DWARFContext.h" +@@ -19,13 +18,11 @@ + #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" + #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" + #include "llvm/DebugInfo/DWARF/DWARFDie.h" +-#include "llvm/DebugInfo/DWARF/DWARFExpression.h" + #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" + #include "llvm/DebugInfo/DWARF/DWARFListTable.h" + #include "llvm/DebugInfo/DWARF/DWARFObject.h" + #include "llvm/DebugInfo/DWARF/DWARFSection.h" + #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +-#include "llvm/Object/ObjectFile.h" + #include "llvm/Support/DataExtractor.h" + #include "llvm/Support/Errc.h" + #include "llvm/Support/Path.h" +@@ -752,100 +749,6 @@ DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { + return R->second.second; + } + +-void DWARFUnit::updateVariableDieMap(DWARFDie Die) { +- for (DWARFDie Child : Die) { +- if (isType(Child.getTag())) +- continue; +- updateVariableDieMap(Child); +- } +- +- if (Die.getTag() != DW_TAG_variable) +- return; +- +- Expected<DWARFLocationExpressionsVector> Locations = +- Die.getLocations(DW_AT_location); +- if (!Locations) { +- // Missing DW_AT_location is fine here. +- consumeError(Locations.takeError()); +- return; +- } +- +- uint64_t Address = UINT64_MAX; +- +- for (const DWARFLocationExpression &Location : *Locations) { +- uint8_t AddressSize = getAddressByteSize(); +- DataExtractor Data(Location.Expr, isLittleEndian(), AddressSize); +- DWARFExpression Expr(Data, AddressSize); +- auto It = Expr.begin(); +- if (It == Expr.end()) +- continue; +- +- // Match exactly the main sequence used to describe global variables: +- // `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence +- // that LLVM produces for DILocalVariables and DIGlobalVariables. If, in +- // future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is +- // a good starting point) is extended to use further expressions, this code +- // needs to be updated. +- uint64_t LocationAddr; +- if (It->getCode() == dwarf::DW_OP_addr) { +- LocationAddr = It->getRawOperand(0); +- } else if (It->getCode() == dwarf::DW_OP_addrx) { +- uint64_t DebugAddrOffset = It->getRawOperand(0); +- if (auto Pointer = getAddrOffsetSectionItem(DebugAddrOffset)) { +- LocationAddr = Pointer->Address; +- } +- } else { +- continue; +- } +- +- // Read the optional 2nd operand, a DW_OP_plus_uconst. +- if (++It != Expr.end()) { +- if (It->getCode() != dwarf::DW_OP_plus_uconst) +- continue; +- +- LocationAddr += It->getRawOperand(0); +- +- // Probe for a 3rd operand, if it exists, bail. +- if (++It != Expr.end()) +- continue; +- } +- +- Address = LocationAddr; +- break; +- } +- +- // Get the size of the global variable. If all else fails (i.e. the global has +- // no type), then we use a size of one to still allow symbolization of the +- // exact address. +- uint64_t GVSize = 1; +- if (Die.getAttributeValueAsReferencedDie(DW_AT_type)) +- if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize())) +- GVSize = *Size; +- +- if (Address != UINT64_MAX) +- VariableDieMap[Address] = {Address + GVSize, Die}; +-} +- +-DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) { +- extractDIEsIfNeeded(false); +- +- auto RootDie = getUnitDIE(); +- +- auto RootLookup = RootsParsedForVariables.insert(RootDie.getOffset()); +- if (RootLookup.second) +- updateVariableDieMap(RootDie); +- +- auto R = VariableDieMap.upper_bound(Address); +- if (R == VariableDieMap.begin()) +- return DWARFDie(); +- +- // upper_bound's previous item contains Address. +- --R; +- if (Address >= R->second.first) +- return DWARFDie(); +- return R->second.second; +-} +- + void + DWARFUnit::getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl<DWARFDie> &InlinedChain) { +diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp +index e600fb7385f1..0444093d7622 100644 +--- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp ++++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp +@@ -64,13 +64,6 @@ DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address, + return Result; + } + +-DILineInfo +-PDBContext::getLineInfoForDataAddress(object::SectionedAddress Address) { +- // Unimplemented. S_GDATA and S_LDATA in CodeView (used to describe global +- // variables) aren't capable of carrying line information. +- return DILineInfo(); +-} +- + DILineInfoTable + PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address, + uint64_t Size, +diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +index 877380213f21..496c8149782e 100644 +--- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp ++++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +@@ -206,10 +206,6 @@ void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) { + Name = DILineInfo::Addr2LineBadString; + OS << Name << "\n"; + OS << Global.Start << " " << Global.Size << "\n"; +- if (Global.DeclFile.empty()) +- OS << "??:?\n"; +- else +- OS << Global.DeclFile << ":" << Global.DeclLine << "\n"; + printFooter(); + } + +diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +index d8ee9264b64f..fcff531895a2 100644 +--- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp ++++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +@@ -327,14 +327,6 @@ DIGlobal SymbolizableObjectFile::symbolizeData( + std::string FileName; + getNameFromSymbolTable(ModuleOffset.Address, Res.Name, Res.Start, Res.Size, + FileName); +- Res.DeclFile = FileName; +- +- // Try and get a better filename:lineno pair from the debuginfo, if present. +- DILineInfo DL = DebugInfoContext->getLineInfoForDataAddress(ModuleOffset); +- if (DL.Line != 0) { +- Res.DeclFile = DL.FileName; +- Res.DeclLine = DL.Line; +- } + return Res; + } + +diff --git a/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml b/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml +index 83af3111c5dd..984e444b2fda 100644 +--- a/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml ++++ b/llvm/test/DebugInfo/Symbolize/ELF/data-command-symtab.yaml +@@ -7,15 +7,12 @@ + + # CHECK: func + # CHECK-NEXT: 4096 1 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + # CHECK-NEXT: data + # CHECK-NEXT: 8192 2 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + # CHECK-NEXT: notype + # CHECK-NEXT: 8194 3 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + + --- !ELF +diff --git a/llvm/test/tools/llvm-symbolizer/data-location.yaml b/llvm/test/tools/llvm-symbolizer/data-location.yaml +deleted file mode 100644 +index 54f7d9be44a1..000000000000 +--- a/llvm/test/tools/llvm-symbolizer/data-location.yaml ++++ /dev/null +@@ -1,450 +0,0 @@ +-## Show that when "DATA" is used with an address, it forces the found location +-## to be symbolized as data, including the source information. +- +-# RUN: yaml2obj %s -o %t.so +- +-# RUN: llvm-symbolizer 'DATA 0x304d0' 'DATA 0x304d1' 'DATA 0x304d3' \ +-# RUN: 'DATA 0x304c0' 'DATA 0x304c8' 'DATA 0x304d4' 'DATA 0x304dc' \ +-# RUN: 'DATA 0x304d8' --obj=%t.so | FileCheck %s +- +-# CHECK: bss_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:1 +-# CHECK-EMPTY: +- +-## Check that lookups in the middle of the symbol are also resolved correctly. +-# CHECK: bss_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:1 +-# CHECK-EMPTY: +-# CHECK: bss_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:1 +-# CHECK-EMPTY: +- +-## Now, the remainder of the symbols. +-# CHECK-NEXT: data_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:2 +-# CHECK-EMPTY: +-# CHECK-NEXT: str +-# CHECK-NEXT: {{[0-9]+}} 8 +-# CHECK-NEXT: /tmp/file.cpp:4 +-# CHECK-EMPTY: +-# CHECK-NEXT: f()::function_global +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:8 +-# CHECK-EMPTY: +- +-## Including the one that includes an addend. +-# CHECK-NEXT: alpha +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:12 +-# CHECK-EMPTY: +-# CHECK-NEXT: beta +-# CHECK-NEXT: {{[0-9]+}} 4 +-# CHECK-NEXT: /tmp/file.cpp:13 +-# CHECK-EMPTY: +- +-## Ensure there's still a global that's offset-based. +-# RUN: llvm-dwarfdump --debug-info %t.so | FileCheck %s --check-prefix=OFFSET +- +-# OFFSET: DW_AT_location (DW_OP_addrx 0x4, DW_OP_plus_uconst 0x4) +- +-################################################################################ +-## File below was generated using: +-## +-## $ clang++ -g -O3 /tmp/file.cpp -shared -fuse-ld=lld -nostdlib \ +-## -target aarch64-linux-gnuabi -mllvm -global-merge-ignore-single-use \ +-## -o /tmp/file.so +-## +-## With /tmp/file.cpp as: +-## 1: int bss_global; +-## 2: int data_global = 2; +-## 3: +-## 4: const char* str = +-## 5: "12345678"; +-## 6: +-## 7: int* f() { +-## 8: static int function_global; +-## 9: return &function_global; +-## 10: } +-## 11: +-## 12: static int alpha; +-## 13: static int beta; +-## 14: int *f(bool b) { return beta ? &alpha : β } +-## 15: +-## +-## ... then, one can get the offsets using `nm`, like: +-## $ nm out.so | grep bss_global +-## 00000000000038fc B bss_global +-## +-## Note the use of the aarch64 target (with -nostdlib in order to allow linkage +-## without libraries for cross-compilation) as well as -O3 and +-## -global-merge-ignore-single-use. This is a specific combination that makes +-## the compiler emit the `alpha` global variable with a more complex +-## DW_AT_location than just a DW_OP_addr/DW_OP_addrx. In this instance, it +-## outputs a `DW_AT_location (DW_OP_addrx 0x4, DW_OP_plus_uconst 0x4)`. +-## +-## Ideally, this would be tested by invoking clang directly on a C source file, +-## but unfortunately there's no way to do that for LLVM tests. The other option +-## is to compile IR to an objfile, but llvm-symbolizer doesn't understand that +-## two symbols can have the same address in different sections. In the code +-## above, for example, we'd have bss_global at .bss+0x0, and data_global at +-## .data+0x0, and so the symbolizer would only print one of them. Hence, we have +-## the ugly dso-to-yaml blob below. +-## +-## For now, constant strings don't have a debuginfo entry, and so can't be +-## symbolized correctly. In future (if D123534 gets merged), this can be updated +-## to include a check that llvm-symbolizer can also symbolize constant strings, +-## like `str` above (basically that &"12345678" should be symbolizable) +-## to the specific line. Then, you can find the address of the constant string +-## from the relocation: +-## +-## $ nm out.so | grep str +-## 00000000000038c0 D str +-## $ llvm-objdump -R out.so | grep 38c0 +-## 00000000000038c0 R_X86_64_RELATIVE *ABS*+0x4f8 # <-- 0x4f8 +-################################################################################ +- +---- !ELF +-FileHeader: +- Class: ELFCLASS64 +- Data: ELFDATA2LSB +- Type: ET_DYN +- Machine: EM_AARCH64 +-ProgramHeaders: +- - Type: PT_PHDR +- Flags: [ PF_R ] +- VAddr: 0x40 +- Align: 0x8 +- - Type: PT_LOAD +- Flags: [ PF_R ] +- FirstSec: .dynsym +- LastSec: .eh_frame +- Align: 0x10000 +- - Type: PT_LOAD +- Flags: [ PF_X, PF_R ] +- FirstSec: .text +- LastSec: .text +- VAddr: 0x103E4 +- Align: 0x10000 +- - Type: PT_LOAD +- Flags: [ PF_W, PF_R ] +- FirstSec: .dynamic +- LastSec: .dynamic +- VAddr: 0x20410 +- Align: 0x10000 +- - Type: PT_LOAD +- Flags: [ PF_W, PF_R ] +- FirstSec: .data +- LastSec: .bss +- VAddr: 0x304C0 +- Align: 0x10000 +- - Type: PT_DYNAMIC +- Flags: [ PF_W, PF_R ] +- FirstSec: .dynamic +- LastSec: .dynamic +- VAddr: 0x20410 +- Align: 0x8 +- - Type: PT_GNU_RELRO +- Flags: [ PF_R ] +- FirstSec: .dynamic +- LastSec: .dynamic +- VAddr: 0x20410 +- - Type: PT_GNU_EH_FRAME +- Flags: [ PF_R ] +- FirstSec: .eh_frame_hdr +- LastSec: .eh_frame_hdr +- VAddr: 0x37C +- Align: 0x4 +- - Type: PT_GNU_STACK +- Flags: [ PF_W, PF_R ] +- Align: 0x0 +-Sections: +- - Name: .dynsym +- Type: SHT_DYNSYM +- Flags: [ SHF_ALLOC ] +- Address: 0x238 +- Link: .dynstr +- AddressAlign: 0x8 +- - Name: .gnu.hash +- Type: SHT_GNU_HASH +- Flags: [ SHF_ALLOC ] +- Address: 0x2C8 +- Link: .dynsym +- AddressAlign: 0x8 +- Header: +- SymNdx: 0x1 +- Shift2: 0x1A +- BloomFilter: [ 0x400188002180000C ] +- HashBuckets: [ 0x1 ] +- HashValues: [ 0xEE8502A, 0xEE85016, 0xC033991C, 0x61F7372E, 0xB88AB7F ] +- - Name: .hash +- Type: SHT_HASH +- Flags: [ SHF_ALLOC ] +- Address: 0x2F8 +- Link: .dynsym +- AddressAlign: 0x4 +- Bucket: [ 5, 0, 4, 0, 3, 0 ] +- Chain: [ 0, 0, 0, 1, 2, 0 ] +- - Name: .dynstr +- Type: SHT_STRTAB +- Flags: [ SHF_ALLOC ] +- Address: 0x330 +- AddressAlign: 0x1 +- - Name: .rela.dyn +- Type: SHT_RELA +- Flags: [ SHF_ALLOC ] +- Address: 0x358 +- Link: .dynsym +- AddressAlign: 0x8 +- Relocations: +- - Offset: 0x304C8 +- Type: R_AARCH64_RELATIVE +- Addend: 880 +- - Name: .rodata +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ] +- Address: 0x370 +- AddressAlign: 0x1 +- EntSize: 0x1 +- Content: '313233343536373800' +- - Name: .eh_frame_hdr +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC ] +- Address: 0x37C +- AddressAlign: 0x4 +- Content: 011B033B18000000020000006800010034000000740001004C000000 +- - Name: .eh_frame +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC ] +- Address: 0x398 +- AddressAlign: 0x8 +- Content: 1400000000000000017A5200017C1E011B0C1F0000000000140000001C0000002C0001000C00000000000000000000001400000034000000200001001C000000000000000000000000000000 +- - Name: .text +- Type: SHT_PROGBITS +- Flags: [ SHF_ALLOC, SHF_EXECINSTR ] +- Address: 0x103E4 +- AddressAlign: 0x4 +- Content: 0001009000501391C0035FD60801009008611391E90308AA2A4540B85F0100710001899AC0035FD6 +- - Name: .dynamic +- Type: SHT_DYNAMIC +- Flags: [ SHF_WRITE, SHF_ALLOC ] +- Address: 0x20410 +- Link: .dynstr +- AddressAlign: 0x8 +- Entries: +- - Tag: DT_RELA +- Value: 0x358 +- - Tag: DT_RELASZ +- Value: 0x18 +- - Tag: DT_RELAENT +- Value: 0x18 +- - Tag: DT_RELACOUNT +- Value: 0x1 +- - Tag: DT_SYMTAB +- Value: 0x238 +- - Tag: DT_SYMENT +- Value: 0x18 +- - Tag: DT_STRTAB +- Value: 0x330 +- - Tag: DT_STRSZ +- Value: 0x28 +- - Tag: DT_GNU_HASH +- Value: 0x2C8 +- - Tag: DT_HASH +- Value: 0x2F8 +- - Tag: DT_NULL +- Value: 0x0 +- - Name: .data +- Type: SHT_PROGBITS +- Flags: [ SHF_WRITE, SHF_ALLOC ] +- Address: 0x304C0 +- AddressAlign: 0x8 +- Content: '02000000000000000000000000000000' +- - Name: .bss +- Type: SHT_NOBITS +- Flags: [ SHF_WRITE, SHF_ALLOC ] +- Address: 0x304D0 +- AddressAlign: 0x4 +- Size: 0x10 +- - Name: .debug_abbrev +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: 011101252513050325721710171B25111B120673170000023400032549133F193A0B3B0B0218000003240003253E0B0B0B0000040F004913000005260049130000062E01111B120640187A196E2503253A0B3B0B49133F190000073400032549133A0B3B0B02180000083400032549133A0B3B0B02186E25000009050003253A0B3B0B4913000000 +- - Name: .debug_info +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: AB0000000500010800000000010021000108000000000000000205280000000800000002032E000000000102A1000304050402052E000000000202A101020648000000000402A102044D00000005520000000307080106050C000000016F0D0E0007A500000007082E000000000802A1030008092E000000000D02A1040A080B2E000000000C04A10423040C06061C000000016F0F0E000EA50000000910000EAA00000000042E0000000311020100 +- - Name: .debug_str_offsets +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: 4C00000005000000A2000000000000002C00000059000000280000001C00000072000000640000008C0000008700000069000000140000007B0000009C0000001A0000000E0000008500000076000000 +- - Name: .comment +- Type: SHT_PROGBITS +- Flags: [ SHF_MERGE, SHF_STRINGS ] +- AddressAlign: 0x1 +- EntSize: 0x1 +- Content: 4C696E6B65723A204C4C442031352E302E300000636C616E672076657273696F6E2031352E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A6563742E67697420306462616566363162353666306566306162306366333865613932666663316633356265653366662900 +- - Name: .debug_line +- Type: SHT_PROGBITS +- AddressAlign: 0x1 +- Content: 620000000500080037000000010101FB0E0D00010101010000000100000101011F010E00000003011F020F051E0100000000006C97BBE59F7DC6A9EA956633431DA63E0400000902E4030100000000001805030A140500BF05190A0105120608740204000101 +- - Name: .debug_line_str +- Type: SHT_PROGBITS +- Flags: [ SHF_MERGE, SHF_STRINGS ] +- AddressAlign: 0x1 +- EntSize: 0x1 +- Content: 2F746D702F66696C652E637070002F7573722F6C6F63616C2F676F6F676C652F686F6D652F6D69746368702F6C6C766D2D6275696C642F6F707400 +-Symbols: +- - Name: file.cpp +- Type: STT_FILE +- Index: SHN_ABS +- - Name: '$x.0' +- Section: .text +- Value: 0x103E4 +- - Name: _ZZ1fvE15function_global +- Type: STT_OBJECT +- Section: .bss +- Value: 0x304D4 +- Size: 0x4 +- - Name: '$d.1' +- Section: .bss +- Value: 0x304D0 +- - Name: '$d.2' +- Section: .data +- Value: 0x304C0 +- - Name: '$d.3' +- Section: .rodata +- Value: 0x370 +- - Name: '$d.4' +- Section: .debug_abbrev +- - Name: '$d.5' +- Section: .debug_info +- - Name: '$d.6' +- Section: .debug_str_offsets +- - Name: '$d.7' +- Section: .debug_str +- Value: 0xA2 +- - Name: '$d.8' +- Section: .debug_addr +- - Name: _ZL4beta +- Type: STT_OBJECT +- Section: .bss +- Value: 0x304D8 +- Size: 0x4 +- - Name: _ZL5alpha +- Type: STT_OBJECT +- Section: .bss +- Value: 0x304DC +- Size: 0x4 +- - Name: '$d.9' +- Section: .comment +- Value: 0x13 +- - Name: '$d.10' +- Section: .eh_frame +- Value: 0x398 +- - Name: '$d.11' +- Section: .debug_line +- - Name: '$d.12' +- Section: .debug_line_str +- Value: 0xE +- - Name: _DYNAMIC +- Section: .dynamic +- Value: 0x20410 +- Other: [ STV_HIDDEN ] +- - Name: _Z1fv +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103E4 +- Size: 0xC +- - Name: _Z1fb +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103F0 +- Size: 0x1C +- - Name: bss_global +- Type: STT_OBJECT +- Section: .bss +- Binding: STB_GLOBAL +- Value: 0x304D0 +- Size: 0x4 +- - Name: data_global +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C0 +- Size: 0x4 +- - Name: str +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C8 +- Size: 0x8 +-DynamicSymbols: +- - Name: _Z1fv +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103E4 +- Size: 0xC +- - Name: _Z1fb +- Type: STT_FUNC +- Section: .text +- Binding: STB_GLOBAL +- Value: 0x103F0 +- Size: 0x1C +- - Name: bss_global +- Type: STT_OBJECT +- Section: .bss +- Binding: STB_GLOBAL +- Value: 0x304D0 +- Size: 0x4 +- - Name: data_global +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C0 +- Size: 0x4 +- - Name: str +- Type: STT_OBJECT +- Section: .data +- Binding: STB_GLOBAL +- Value: 0x304C8 +- Size: 0x8 +-DWARF: +- debug_str: +- - '/tmp/file.cpp' +- - _Z1fb +- - alpha +- - f +- - data_global +- - int +- - '/usr/local/google/home/mitchp/llvm-build/opt' +- - bss_global +- - char +- - _ZL4beta +- - str +- - bool +- - _ZL5alpha +- - b +- - beta +- - function_global +- - _Z1fv +- - 'clang version 15.0.0 (https://github.com/llvm/llvm-project.git 0dbaef61b56f0ef0ab0cf38ea92ffc1f35bee3ff)' +- debug_addr: +- - Length: 0x3C +- Version: 0x5 +- AddressSize: 0x8 +- Entries: +- - Address: 0x304D0 +- - Address: 0x304C0 +- - Address: 0x304C8 +- - Address: 0x304D4 +- - Address: 0x304D8 +- - Address: 0x103E4 +- - Address: 0x103F0 +-... +diff --git a/llvm/test/tools/llvm-symbolizer/data.s b/llvm/test/tools/llvm-symbolizer/data.s +index cc9503c59141..e8039f146dbd 100644 +--- a/llvm/test/tools/llvm-symbolizer/data.s ++++ b/llvm/test/tools/llvm-symbolizer/data.s +@@ -7,12 +7,9 @@ + + # CHECK: d1 + # CHECK-NEXT: 0 8 +-# CHECK-NEXT: ??:? + # CHECK-EMPTY: + # CHECK-NEXT: d2 + # CHECK-NEXT: 8 4 +-# CHECK-NEXT: ??:? +-# CHECK-EMPTY: + + d1: + .quad 0x1122334455667788 +-- +2.38.1.1.g6d9df9d320 + diff --git a/build/build-clang/revert-llvmorg-15-init-13446-g7524fe962e47.patch b/build/build-clang/revert-llvmorg-15-init-13446-g7524fe962e47.patch new file mode 100644 index 0000000000..5bd4601827 --- /dev/null +++ b/build/build-clang/revert-llvmorg-15-init-13446-g7524fe962e47.patch @@ -0,0 +1,39 @@ +From 12f64ca10837bd68ec30804ebfa21653925ad5cf Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Thu, 16 Jun 2022 12:51:29 +0900 +Subject: [PATCH] Revert "[libFuzzer] Use the compiler to link the relocatable + object" + +This reverts commit 7524fe962e479416fd6318407eff4eed5b96a40b. +--- + compiler-rt/lib/fuzzer/CMakeLists.txt | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/compiler-rt/lib/fuzzer/CMakeLists.txt b/compiler-rt/lib/fuzzer/CMakeLists.txt +index 856cd732d517..d51de53f5acc 100644 +--- a/compiler-rt/lib/fuzzer/CMakeLists.txt ++++ b/compiler-rt/lib/fuzzer/CMakeLists.txt +@@ -138,15 +138,15 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND + COMPILER_RT_LIBCXX_PATH AND + COMPILER_RT_LIBCXXABI_PATH) + macro(partially_link_libcxx name dir arch) +- get_target_flags_for_arch(${arch} target_cflags) +- if(CMAKE_CXX_COMPILER_ID MATCHES Clang) +- get_compiler_rt_target(${arch} target) +- set(target_cflags --target=${target} ${target_cflags}) ++ if(${arch} MATCHES "i386") ++ set(EMULATION_ARGUMENT "-m" "elf_i386") ++ else() ++ set(EMULATION_ARGUMENT "") + endif() + set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") + file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) + add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD +- COMMAND ${CMAKE_CXX_COMPILER} ${target_cflags} -Wl,--whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" -Wl,--no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o ++ COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o + COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o + COMMAND ${CMAKE_COMMAND} -E remove "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" + COMMAND ${CMAKE_AR} qcs "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" ${name}.o +-- +2.36.0.1.g2bbe56bd8d + diff --git a/build/build-clang/revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_17.patch b/build/build-clang/revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_17.patch new file mode 100644 index 0000000000..4e217dcf3d --- /dev/null +++ b/build/build-clang/revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_17.patch @@ -0,0 +1,172 @@ +From cf00b30288c4c81b2c6a5af01c38f236148777a0 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Tue, 28 Mar 2023 06:13:36 +0900 +Subject: [PATCH] Revert "[Passes][VectorCombine] enable early run generally + and try load folds" + +This reverts commit 163bb6d64e5f1220777c3ec2a8b58c0666a74d91. +It causes various reftest regressions. +--- + llvm/lib/Passes/PassBuilderPipelines.cpp | 7 ++++--- + llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 8 ++------ + llvm/test/Other/new-pm-defaults.ll | 2 +- + .../Other/new-pm-thinlto-postlink-defaults.ll | 1 - + .../Other/new-pm-thinlto-postlink-pgo-defaults.ll | 1 - + .../new-pm-thinlto-postlink-samplepgo-defaults.ll | 1 - + .../Other/new-pm-thinlto-prelink-pgo-defaults.ll | 1 - + .../new-pm-thinlto-prelink-samplepgo-defaults.ll | 1 - + .../PhaseOrdering/X86/vec-load-combine.ll | 15 +++++++++++---- + 9 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp +index eed29c25714b..b925448cd6c0 100644 +--- a/llvm/lib/Passes/PassBuilderPipelines.cpp ++++ b/llvm/lib/Passes/PassBuilderPipelines.cpp +@@ -611,9 +611,10 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, + // Delete small array after loop unroll. + FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); + +- // Try vectorization/scalarization transforms that are both improvements +- // themselves and can allow further folds with GVN and InstCombine. +- FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true)); ++ // The matrix extension can introduce large vector operations early, which can ++ // benefit from running vector-combine early on. ++ if (EnableMatrix) ++ FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true)); + + // Eliminate redundancies. + FPM.addPass(MergedLoadStoreMotionPass()); +diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +index 2e489757ebc1..810a9f92bb7a 100644 +--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp ++++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +@@ -1720,12 +1720,6 @@ bool VectorCombine::run() { + // dispatching to folding functions if there's no chance of matching. + if (IsFixedVectorType) { + switch (Opcode) { +- case Instruction::InsertElement: +- MadeChange |= vectorizeLoadInsert(I); +- break; +- case Instruction::ShuffleVector: +- MadeChange |= widenSubvectorLoad(I); +- break; + case Instruction::Load: + MadeChange |= scalarizeLoadExtract(I); + break; +@@ -1754,9 +1748,11 @@ bool VectorCombine::run() { + if (IsFixedVectorType) { + switch (Opcode) { + case Instruction::InsertElement: ++ MadeChange |= vectorizeLoadInsert(I); + MadeChange |= foldInsExtFNeg(I); + break; + case Instruction::ShuffleVector: ++ MadeChange |= widenSubvectorLoad(I); + MadeChange |= foldShuffleOfBinops(I); + MadeChange |= foldSelectShuffle(I); + break; +diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll +index 13612c3bb459..5f84d28af4a6 100644 +--- a/llvm/test/Other/new-pm-defaults.ll ++++ b/llvm/test/Other/new-pm-defaults.ll +@@ -186,7 +186,7 @@ + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-EP-LOOP-END-NEXT: Running pass: NoOpLoopPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass ++; CHECK-MATRIX: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll +index 3f5d2d5b153d..ea07128c9f6a 100644 +--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll +@@ -159,7 +159,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +index 29021ceace54..43e943cb6011 100644 +--- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +@@ -121,7 +121,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +index daf3141a1f2c..78914d1c23b2 100644 +--- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +@@ -130,7 +130,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +index bfe80902f806..5b62ba39add3 100644 +--- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +@@ -160,7 +160,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +index c7daf7aa46b1..17475423d696 100644 +--- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +@@ -124,7 +124,6 @@ + ; CHECK-O-NEXT: Running pass: IndVarSimplifyPass + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll b/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll +index 77cbc70ff369..dd7164febea4 100644 +--- a/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll ++++ b/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll +@@ -12,13 +12,20 @@ $getAt = comdat any + define dso_local noundef <4 x float> @ConvertVectors_ByRef(ptr noundef nonnull align 16 dereferenceable(16) %0) #0 { + ; SSE-LABEL: @ConvertVectors_ByRef( + ; SSE-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[TMP0:%.*]], align 16 +-; SSE-NEXT: [[TMP3:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 2> +-; SSE-NEXT: ret <4 x float> [[TMP3]] ++; SSE-NEXT: [[TMP3:%.*]] = getelementptr inbounds [4 x float], ptr [[TMP0]], i64 0, i64 1 ++; SSE-NEXT: [[TMP4:%.*]] = load <2 x float>, ptr [[TMP3]], align 4 ++; SSE-NEXT: [[TMP5:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> ++; SSE-NEXT: [[TMP6:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 5, i32 undef> ++; SSE-NEXT: [[TMP7:%.*]] = shufflevector <4 x float> [[TMP6]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 1, i32 2, i32 5> ++; SSE-NEXT: ret <4 x float> [[TMP7]] + ; + ; AVX-LABEL: @ConvertVectors_ByRef( + ; AVX-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[TMP0:%.*]], align 16 +-; AVX-NEXT: [[TMP3:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 2> +-; AVX-NEXT: ret <4 x float> [[TMP3]] ++; AVX-NEXT: [[TMP3:%.*]] = getelementptr inbounds [4 x float], ptr [[TMP0]], i64 0, i64 2 ++; AVX-NEXT: [[TMP4:%.*]] = load float, ptr [[TMP3]], align 8 ++; AVX-NEXT: [[TMP5:%.*]] = insertelement <4 x float> [[TMP2]], float [[TMP4]], i64 2 ++; AVX-NEXT: [[TMP6:%.*]] = insertelement <4 x float> [[TMP5]], float [[TMP4]], i64 3 ++; AVX-NEXT: ret <4 x float> [[TMP6]] + ; + %2 = alloca ptr, align 8 + %3 = alloca <4 x float>, align 16 +-- +2.39.0.1.g6739ec1790 + diff --git a/build/build-clang/revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_18.patch b/build/build-clang/revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_18.patch new file mode 100644 index 0000000000..6449fe14bc --- /dev/null +++ b/build/build-clang/revert-llvmorg-16-init-11301-g163bb6d64e5f_clang_18.patch @@ -0,0 +1,183 @@ +From cf00b30288c4c81b2c6a5af01c38f236148777a0 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Tue, 28 Mar 2023 06:13:36 +0900 +Subject: [PATCH] Revert "[Passes][VectorCombine] enable early run generally + and try load folds" + +This reverts commit 163bb6d64e5f1220777c3ec2a8b58c0666a74d91. +It causes various reftest regressions. +--- + llvm/lib/Passes/PassBuilderPipelines.cpp | 7 ++++--- + llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 8 ++------ + llvm/test/Other/new-pm-defaults.ll | 2 +- + .../Other/new-pm-thinlto-postlink-defaults.ll | 1 - + .../Other/new-pm-thinlto-postlink-pgo-defaults.ll | 1 - + .../new-pm-thinlto-postlink-samplepgo-defaults.ll | 1 - + .../Other/new-pm-thinlto-prelink-pgo-defaults.ll | 1 - + .../new-pm-thinlto-prelink-samplepgo-defaults.ll | 1 - + .../PhaseOrdering/X86/vec-load-combine.ll | 15 +++++++++++---- + 9 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp +index eed29c25714b..b925448cd6c0 100644 +--- a/llvm/lib/Passes/PassBuilderPipelines.cpp ++++ b/llvm/lib/Passes/PassBuilderPipelines.cpp +@@ -611,9 +611,10 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, + // Delete small array after loop unroll. + FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); + +- // Try vectorization/scalarization transforms that are both improvements +- // themselves and can allow further folds with GVN and InstCombine. +- FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true)); ++ // The matrix extension can introduce large vector operations early, which can ++ // benefit from running vector-combine early on. ++ if (EnableMatrix) ++ FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true)); + + // Eliminate redundancies. + FPM.addPass(MergedLoadStoreMotionPass()); +diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +index 2e489757ebc1..810a9f92bb7a 100644 +--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp ++++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +@@ -1715,23 +1715,6 @@ bool VectorCombine::run() { + bool IsFixedVectorType = isa<FixedVectorType>(I.getType()); + auto Opcode = I.getOpcode(); + +- // These folds should be beneficial regardless of when this pass is run +- // in the optimization pipeline. +- // The type checking is for run-time efficiency. We can avoid wasting time +- // dispatching to folding functions if there's no chance of matching. +- if (IsFixedVectorType) { +- switch (Opcode) { +- case Instruction::InsertElement: +- MadeChange |= vectorizeLoadInsert(I); +- break; +- case Instruction::ShuffleVector: +- MadeChange |= widenSubvectorLoad(I); +- break; +- default: +- break; +- } +- } +- + // This transform works with scalable and fixed vectors + // TODO: Identify and allow other scalable transforms + if (isa<VectorType>(I.getType())) { +@@ -1753,9 +1736,11 @@ bool VectorCombine::run() { + if (IsFixedVectorType) { + switch (Opcode) { + case Instruction::InsertElement: ++ MadeChange |= vectorizeLoadInsert(I); + MadeChange |= foldInsExtFNeg(I); + break; + case Instruction::ShuffleVector: ++ MadeChange |= widenSubvectorLoad(I); + MadeChange |= foldShuffleOfBinops(I); + MadeChange |= foldSelectShuffle(I); + break; +diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll +index 13612c3bb459..5f84d28af4a6 100644 +--- a/llvm/test/Other/new-pm-defaults.ll ++++ b/llvm/test/Other/new-pm-defaults.ll +@@ -186,7 +186,7 @@ + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-EP-LOOP-END-NEXT: Running pass: NoOpLoopPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass ++; CHECK-MATRIX: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll +index 3f5d2d5b153d..ea07128c9f6a 100644 +--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll +@@ -159,7 +159,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +index 29021ceace54..43e943cb6011 100644 +--- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +@@ -121,7 +121,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +index daf3141a1f2c..78914d1c23b2 100644 +--- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +@@ -130,7 +130,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +index bfe80902f806..5b62ba39add3 100644 +--- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +@@ -160,7 +160,6 @@ + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: LoopFullUnrollPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +index c7daf7aa46b1..17475423d696 100644 +--- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll ++++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +@@ -124,7 +124,6 @@ + ; CHECK-O-NEXT: Running pass: IndVarSimplifyPass + ; CHECK-O-NEXT: Running pass: LoopDeletionPass + ; CHECK-O-NEXT: Running pass: SROAPass on foo +-; CHECK-O23SZ-NEXT: Running pass: VectorCombinePass + ; CHECK-O23SZ-NEXT: Running pass: MergedLoadStoreMotionPass + ; CHECK-O23SZ-NEXT: Running pass: GVNPass + ; CHECK-O23SZ-NEXT: Running analysis: MemoryDependenceAnalysis +diff --git a/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll b/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll +index 77cbc70ff369..dd7164febea4 100644 +--- a/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll ++++ b/llvm/test/Transforms/PhaseOrdering/X86/vec-load-combine.ll +@@ -12,13 +12,20 @@ $getAt = comdat any + define dso_local noundef <4 x float> @ConvertVectors_ByRef(ptr noundef nonnull align 16 dereferenceable(16) %0) #0 { + ; SSE-LABEL: @ConvertVectors_ByRef( + ; SSE-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[TMP0:%.*]], align 16 +-; SSE-NEXT: [[TMP3:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 2> +-; SSE-NEXT: ret <4 x float> [[TMP3]] ++; SSE-NEXT: [[TMP3:%.*]] = getelementptr inbounds [4 x float], ptr [[TMP0]], i64 0, i64 1 ++; SSE-NEXT: [[TMP4:%.*]] = load <2 x float>, ptr [[TMP3]], align 4 ++; SSE-NEXT: [[TMP5:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> ++; SSE-NEXT: [[TMP6:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 5, i32 undef> ++; SSE-NEXT: [[TMP7:%.*]] = shufflevector <4 x float> [[TMP6]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 1, i32 2, i32 5> ++; SSE-NEXT: ret <4 x float> [[TMP7]] + ; + ; AVX-LABEL: @ConvertVectors_ByRef( + ; AVX-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[TMP0:%.*]], align 16 +-; AVX-NEXT: [[TMP3:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 2> +-; AVX-NEXT: ret <4 x float> [[TMP3]] ++; AVX-NEXT: [[TMP3:%.*]] = getelementptr inbounds [4 x float], ptr [[TMP0]], i64 0, i64 2 ++; AVX-NEXT: [[TMP4:%.*]] = load float, ptr [[TMP3]], align 8 ++; AVX-NEXT: [[TMP5:%.*]] = insertelement <4 x float> [[TMP2]], float [[TMP4]], i64 2 ++; AVX-NEXT: [[TMP6:%.*]] = insertelement <4 x float> [[TMP5]], float [[TMP4]], i64 3 ++; AVX-NEXT: ret <4 x float> [[TMP6]] + ; + %2 = alloca ptr, align 8 + %3 = alloca <4 x float>, align 16 +-- +2.39.0.1.g6739ec1790 + diff --git a/build/build-clang/revert-llvmorg-17-init-4120-g02e8eb1a438b.patch b/build/build-clang/revert-llvmorg-17-init-4120-g02e8eb1a438b.patch new file mode 100644 index 0000000000..63e59ee68b --- /dev/null +++ b/build/build-clang/revert-llvmorg-17-init-4120-g02e8eb1a438b.patch @@ -0,0 +1,118 @@ +From 2836e92ea557be53fcd91e38cb05a989ad0167e9 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Wed, 8 Mar 2023 14:44:58 +0900 +Subject: [PATCH] Revert "Split getCompileUnitFor{Data,Code}Address." + +This reverts commit 02e8eb1a438bdb1dc9a97aea75a8c9c748048039, which +applies on top of cead4eceb01b935fae07bf4a7e91911b344d2fec, that we +revert too. +--- + .../llvm/DebugInfo/DWARF/DWARFContext.h | 11 +-------- + llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 23 ++++++++----------- + 2 files changed, 11 insertions(+), 23 deletions(-) + +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +index 4eba79a7215f..df903b967ef6 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +@@ -445,16 +445,7 @@ public: + /// address. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" +- DWARFCompileUnit *getCompileUnitForCodeAddress(uint64_t Address); +- +- /// Return the compile unit which contains data with the provided address. +- /// Note: This is more expensive than `getCompileUnitForAddress`, as if +- /// `Address` isn't found in the CU ranges (which is cheap), then it falls +- /// back to an expensive O(n) walk of all CU's looking for data that spans the +- /// address. +- /// TODO: change input parameter from "uint64_t Address" into +- /// "SectionedAddress Address" +- DWARFCompileUnit *getCompileUnitForDataAddress(uint64_t Address); ++ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); + + /// Returns whether CU/TU should be populated manually. TU Index populated + /// manually only for DWARF5. +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +index f648ef8ff770..dd86144d16e0 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +@@ -1118,17 +1118,14 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) { + NormalUnits.getUnitForOffset(Offset)); + } + +-DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) { +- uint64_t CUOffset = getDebugAranges()->findAddress(Address); +- return getCompileUnitForOffset(CUOffset); +-} +- +-DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) { ++DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { ++ // First, get the offset of the compile unit. + uint64_t CUOffset = getDebugAranges()->findAddress(Address); ++ // Retrieve the compile unit. + if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset)) + return OffsetCU; + +- // Global variables are often missed by the above search, for one of two ++ // Global variables are often not found by the above search, for one of two + // reasons: + // 1. .debug_aranges may not include global variables. On clang, it seems we + // put the globals in the aranges, but this isn't true for gcc. +@@ -1149,7 +1146,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) { + DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { + DIEsForAddress Result; + +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + if (!CU) + return Result; + +@@ -1300,7 +1297,7 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, + std::vector<DILocal> + DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + std::vector<DILocal> Result; +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + +@@ -1313,7 +1310,7 @@ DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + DILineInfoSpecifier Spec) { + DILineInfo Result; +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + +@@ -1334,7 +1331,7 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + DILineInfo + DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { + DILineInfo Result; +- DWARFCompileUnit *CU = getCompileUnitForDataAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + +@@ -1349,7 +1346,7 @@ DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { + DILineInfoTable DWARFContext::getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) { + DILineInfoTable Lines; +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Lines; + +@@ -1405,7 +1402,7 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, + DILineInfoSpecifier Spec) { + DIInliningInfo InliningInfo; + +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return InliningInfo; + +-- +2.39.0.1.g6739ec1790 + diff --git a/build/build-clang/revert-llvmorg-17-init-4120-g02e8eb1a438b_clang_18.patch b/build/build-clang/revert-llvmorg-17-init-4120-g02e8eb1a438b_clang_18.patch new file mode 100644 index 0000000000..098c410790 --- /dev/null +++ b/build/build-clang/revert-llvmorg-17-init-4120-g02e8eb1a438b_clang_18.patch @@ -0,0 +1,115 @@ +From 2836e92ea557be53fcd91e38cb05a989ad0167e9 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Wed, 8 Mar 2023 14:44:58 +0900 +Subject: [PATCH] Revert "Split getCompileUnitFor{Data,Code}Address." + +This reverts commit 02e8eb1a438bdb1dc9a97aea75a8c9c748048039, which +applies on top of cead4eceb01b935fae07bf4a7e91911b344d2fec, that we +revert too. +--- + .../llvm/DebugInfo/DWARF/DWARFContext.h | 11 +-------- + llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 23 ++++++++----------- + 2 files changed, 11 insertions(+), 23 deletions(-) + +diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +index 4bd8394e6b4e..3f49fadc2b98 100644 +--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h ++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +@@ -459,16 +459,7 @@ public: + /// address. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" +- DWARFCompileUnit *getCompileUnitForCodeAddress(uint64_t Address); +- +- /// Return the compile unit which contains data with the provided address. +- /// Note: This is more expensive than `getCompileUnitForAddress`, as if +- /// `Address` isn't found in the CU ranges (which is cheap), then it falls +- /// back to an expensive O(n) walk of all CU's looking for data that spans the +- /// address. +- /// TODO: change input parameter from "uint64_t Address" into +- /// "SectionedAddress Address" +- DWARFCompileUnit *getCompileUnitForDataAddress(uint64_t Address); ++ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); + + /// Returns whether CU/TU should be populated manually. TU Index populated + /// manually only for DWARF5. +diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +index a45ed0e56553..692304ac6774 100644 +--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp ++++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +@@ -1492,17 +1492,14 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) { + State->getNormalUnits().getUnitForOffset(Offset)); + } + +-DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) { +- uint64_t CUOffset = getDebugAranges()->findAddress(Address); +- return getCompileUnitForOffset(CUOffset); +-} +- +-DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) { ++DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { ++ // First, get the offset of the compile unit. + uint64_t CUOffset = getDebugAranges()->findAddress(Address); ++ // Retrieve the compile unit. + if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset)) + return OffsetCU; + +- // Global variables are often missed by the above search, for one of two ++ // Global variables are often not found by the above search, for one of two + // reasons: + // 1. .debug_aranges may not include global variables. On clang, it seems we + // put the globals in the aranges, but this isn't true for gcc. +@@ -1523,7 +1520,7 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) { + bool CheckDWO) { + DIEsForAddress Result; + +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + if (!CU) + return Result; + +@@ -1674,7 +1671,7 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, + std::vector<DILocal> + DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + std::vector<DILocal> Result; +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + +@@ -1687,7 +1684,7 @@ DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + DILineInfoSpecifier Spec) { + DILineInfo Result; +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + +@@ -1708,7 +1705,7 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, + DILineInfo + DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { + DILineInfo Result; +- DWARFCompileUnit *CU = getCompileUnitForDataAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + +@@ -1723,7 +1720,7 @@ DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { + DILineInfoTable DWARFContext::getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) { + DILineInfoTable Lines; +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Lines; + +@@ -1779,7 +1776,7 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, + DILineInfoSpecifier Spec) { + DIInliningInfo InliningInfo; + +- DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); ++ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return InliningInfo; + diff --git a/build/build-clang/revert-llvmorg-18-init-6188-gc649f29c24c9.patch b/build/build-clang/revert-llvmorg-18-init-6188-gc649f29c24c9.patch new file mode 100644 index 0000000000..290c65f4b5 --- /dev/null +++ b/build/build-clang/revert-llvmorg-18-init-6188-gc649f29c24c9.patch @@ -0,0 +1,466 @@ +From c3994286d37f4273d6d7a4cb578828d64a25a341 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Wed, 20 Sep 2023 10:08:22 +0900 +Subject: [PATCH 3/3] Revert "[llvm-nm] Add --line-numbers flag" + +This reverts commit c649f29c24c9fc1502d8d53e0c96c3d24b31de1a because it +depends on cead4eceb01b935fae07bf4a7e91911b344d2fec, which we revert. +--- + llvm/docs/CommandGuide/llvm-nm.rst | 6 - + llvm/test/tools/llvm-nm/X86/line-numbers.test | 240 ------------------ + llvm/tools/llvm-nm/CMakeLists.txt | 1 - + llvm/tools/llvm-nm/Opts.td | 2 - + llvm/tools/llvm-nm/llvm-nm.cpp | 92 +------ + 6 files changed, 5 insertions(+), 339 deletions(-) + delete mode 100644 llvm/test/tools/llvm-nm/X86/line-numbers.test + +diff --git a/llvm/docs/CommandGuide/llvm-nm.rst b/llvm/docs/CommandGuide/llvm-nm.rst +index 7067bb0a29a1..4b1290a15665 100644 +--- a/llvm/docs/CommandGuide/llvm-nm.rst ++++ b/llvm/docs/CommandGuide/llvm-nm.rst +@@ -190,12 +190,6 @@ OPTIONS + + Print just the symbol names. Alias for `--format=just-symbols``. + +-.. option:: --line-numbers, -l +- +- Use debugging information to print the filenames and line numbers where +- symbols are defined. Undefined symbols have the location of their first +- relocation printed instead. +- + .. option:: -m + + Use Darwin format. Alias for ``--format=darwin``. +diff --git a/llvm/test/tools/llvm-nm/X86/line-numbers.test b/llvm/test/tools/llvm-nm/X86/line-numbers.test +deleted file mode 100644 +index 4b9817ab5c62..000000000000 +--- a/llvm/test/tools/llvm-nm/X86/line-numbers.test ++++ /dev/null +@@ -1,240 +0,0 @@ +-## Check that printing line numbers isn't attempted for files like bitcode, +-## which have symbols but limited/no section or debug info. +-# RUN: llvm-nm --line-numbers %p/Inputs/test.IRobj-x86_64 | FileCheck %s --check-prefix=BITCODE --match-full-lines --implicit-check-not={{.}} +-# BITCODE: ---------------- S _global_const +-# BITCODE-NEXT: ---------------- D _global_data +-# BITCODE-NEXT: ---------------- T _global_func +-# BITCODE-NEXT: ---------------- S _hidden_const +-# BITCODE-NEXT: ---------------- D _hidden_data +-# BITCODE-NEXT: ---------------- T _hidden_func +-# BITCODE-NEXT: ---------------- s _static_const +-# BITCODE-NEXT: ---------------- d _static_data +-# BITCODE-NEXT: ---------------- t _static_func +- +-## Check that various symbol types can use debug information if available to +-## print line numbers, and if unavailable, don't print anything erroneous. The +-## specific cases checked are given by the symbol names below. Other test cases +-## place requirements on the contents of the whole file, so they are kept out +-## of main.o. +-# RUN: rm -rf %t +-# RUN: split-file %s %t +-# RUN: llvm-mc -g --filetype=obj %t/main.s -o %t/main.o +-# RUN: llvm-nm -l %t/main.o | FileCheck %s --match-full-lines --implicit-check-not={{.}} +-# RUN: llvm-nm --line-numbers %t/main.o | FileCheck %s --match-full-lines --implicit-check-not={{.}} +- +-# CHECK: 0000000000001234 a absolute_symbol +-# CHECK-NEXT: 0000000000000000 d data_no_dwarf +-# CHECK-NEXT: 0000000000000000 T defined_global_function [[FILENAME:.*main.s]]:4 +-# CHECK-NEXT: 0000000000000001 t defined_local_function [[FILENAME]]:7 +-# CHECK-NEXT: 0000000000000000 t function_no_dwarf +-# CHECK-NEXT: U undef1 [[FILENAME]]:12 +-# CHECK-NEXT: U undef2 [[FILENAME]]:14 +-# CHECK-NEXT: U undef_no_reloc +-# CHECK-NEXT: 0000000000000002 t undefined_references [[FILENAME]]:12 +- +-## Check that in the absence of DWARF in the whole object, no line number +-## information is printed. +-# RUN: llvm-mc --filetype=obj %t/main.s -o %t/no-dwarf.o +-# RUN: llvm-nm -l %t/no-dwarf.o | FileCheck %s --check-prefix=NO-DWARF --match-full-lines --implicit-check-not={{.}} +- +-# NO-DWARF: 0000000000001234 a absolute_symbol +-# NO-DWARF-NEXT: 0000000000000000 d data_no_dwarf +-# NO-DWARF-NEXT: 0000000000000000 T defined_global_function +-# NO-DWARF-NEXT: 0000000000000001 t defined_local_function +-# NO-DWARF-NEXT: 0000000000000000 t function_no_dwarf +-# NO-DWARF-NEXT: U undef1 +-# NO-DWARF-NEXT: U undef2 +-# NO-DWARF-NEXT: U undef_no_reloc +-# NO-DWARF-NEXT: 0000000000000002 t undefined_references +- +-## Check that printing line numbers for undefined values is not attempted in +-## the absence of any relocation section. +-# RUN: llvm-mc --filetype=obj %t/undef-no-reloc-sections.s -o %t/undef-no-reloc-sections.o +-# RUN: llvm-nm --line-numbers %t/undef-no-reloc-sections.o | FileCheck %s --check-prefix=UNDEF-NO-RELOC-SECTIONS --match-full-lines --implicit-check-not={{.}} +- +-# UNDEF-NO-RELOC-SECTIONS: U undef +- +-## Check that printing line numbers for undefined values does not include +-## relocations for non-text sections. This is broken out of main.s to ensure +-## that the data relocation for undef comes first. +-# RUN: llvm-mc -g --filetype=obj %t/undef-data-reloc.s -o %t/undef-data-reloc.o +-# RUN: llvm-nm --line-numbers %t/undef-data-reloc.o | FileCheck %s --check-prefix=UNDEF-DATA-RELOC --match-full-lines --implicit-check-not={{.}} +- +-# UNDEF-DATA-RELOC: 0000000000000000 r data_reloc +-# UNDEF-DATA-RELOC-NEXT: U undef +- +-## Check that line numbers can be printed for data definitions. These are broken +-## out of main.s since their DWARF cannot be generated with llvm-mc -g. +-# RUN: llvm-mc -g --filetype=obj %t/data-dwarf.s -o %t/data-dwarf.o +-# RUN: llvm-nm --line-numbers %t/data-dwarf.o | FileCheck %s --check-prefix=DATA-DWARF --match-full-lines --implicit-check-not={{.}} +- +-# DATA-DWARF: 0000000000000000 D defined_data /tmp/tmp.c:1 +- +-#--- main.s +-.text +-.globl defined_global_function +-defined_global_function: +- ret +- +-defined_local_function: +- ret +- +-absolute_symbol = 0x1234 +- +-undefined_references: +- nop +- .long undef1 +- nop +- .long undef2 +- ret +- +-# Note: llvm-mc -g produces no DWARF for data. +-.data +-data_no_dwarf: +- .byte 0 +- +-.globl undef_no_reloc +- +-# Note: llvm-mc -g does not produce DWARF for non-SHF_ALLOC sections. +-.section no_alloc_text,"x",@progbits +-function_no_dwarf: +- ret +- +-#--- undef-no-reloc-sections.s +-.globl undef +- +-#--- undef-data-reloc.s +-.globl undef +-.rodata +-data_reloc: +- .long undef +- +-#--- data-dwarf.s +-# char defined_data = 42 +- .text +- .file "tmp.c" +- .file 0 "/tmp" "/tmp/tmp.c" md5 0x39602a53b15a32d6a622ca86936e88d7 +- .file 1 "tmp.c" md5 0x39602a53b15a32d6a622ca86936e88d7 +- .type defined_data,@object # @defined_data +- .data +- .globl defined_data +-defined_data: +- .byte 42 # 0x2a +- .size defined_data, 1 +- +- .section .debug_abbrev,"",@progbits +- .byte 1 # Abbreviation Code +- .byte 17 # DW_TAG_compile_unit +- .byte 1 # DW_CHILDREN_yes +- .byte 37 # DW_AT_producer +- .byte 37 # DW_FORM_strx1 +- .byte 19 # DW_AT_language +- .byte 5 # DW_FORM_data2 +- .byte 3 # DW_AT_name +- .byte 37 # DW_FORM_strx1 +- .byte 114 # DW_AT_str_offsets_base +- .byte 23 # DW_FORM_sec_offset +- .byte 16 # DW_AT_stmt_list +- .byte 23 # DW_FORM_sec_offset +- .byte 27 # DW_AT_comp_dir +- .byte 37 # DW_FORM_strx1 +- .byte 115 # DW_AT_addr_base +- .byte 23 # DW_FORM_sec_offset +- .byte 0 # EOM(1) +- .byte 0 # EOM(2) +- .byte 2 # Abbreviation Code +- .byte 52 # DW_TAG_variable +- .byte 0 # DW_CHILDREN_no +- .byte 3 # DW_AT_name +- .byte 37 # DW_FORM_strx1 +- .byte 73 # DW_AT_type +- .byte 19 # DW_FORM_ref4 +- .byte 63 # DW_AT_external +- .byte 25 # DW_FORM_flag_present +- .byte 58 # DW_AT_decl_file +- .byte 11 # DW_FORM_data1 +- .byte 59 # DW_AT_decl_line +- .byte 11 # DW_FORM_data1 +- .byte 2 # DW_AT_location +- .byte 24 # DW_FORM_exprloc +- .byte 0 # EOM(1) +- .byte 0 # EOM(2) +- .byte 3 # Abbreviation Code +- .byte 36 # DW_TAG_base_type +- .byte 0 # DW_CHILDREN_no +- .byte 3 # DW_AT_name +- .byte 37 # DW_FORM_strx1 +- .byte 62 # DW_AT_encoding +- .byte 11 # DW_FORM_data1 +- .byte 11 # DW_AT_byte_size +- .byte 11 # DW_FORM_data1 +- .byte 0 # EOM(1) +- .byte 0 # EOM(2) +- .byte 0 # EOM(3) +- .section .debug_info,"",@progbits +-.Lcu_begin0: +- .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +-.Ldebug_info_start0: +- .short 5 # DWARF version number +- .byte 1 # DWARF Unit Type +- .byte 8 # Address Size (in bytes) +- .long .debug_abbrev # Offset Into Abbrev. Section +- .byte 1 # Abbrev [1] 0xc:0x22 DW_TAG_compile_unit +- .byte 0 # DW_AT_producer +- .short 12 # DW_AT_language +- .byte 1 # DW_AT_name +- .long .Lstr_offsets_base0 # DW_AT_str_offsets_base +- .long .Lline_table_start0 # DW_AT_stmt_list +- .byte 2 # DW_AT_comp_dir +- .long .Laddr_table_base0 # DW_AT_addr_base +- .byte 2 # Abbrev [2] 0x1e:0xb DW_TAG_variable +- .byte 3 # DW_AT_name +- .long 41 # DW_AT_type +- # DW_AT_external +- .byte 1 # DW_AT_decl_file +- .byte 1 # DW_AT_decl_line +- .byte 2 # DW_AT_location +- .byte 161 +- .byte 0 +- .byte 3 # Abbrev [3] 0x29:0x4 DW_TAG_base_type +- .byte 4 # DW_AT_name +- .byte 6 # DW_AT_encoding +- .byte 1 # DW_AT_byte_size +- .byte 0 # End Of Children Mark +-.Ldebug_info_end0: +- .section .debug_str_offsets,"",@progbits +- .long 24 # Length of String Offsets Set +- .short 5 +- .short 0 +-.Lstr_offsets_base0: +- .section .debug_str,"MS",@progbits,1 +-.Linfo_string0: +- .asciz "Debian clang version 14.0.6" # string offset=0 +-.Linfo_string1: +- .asciz "/tmp/tmp.c" # string offset=28 +-.Linfo_string2: +- .asciz "/tmp" # string offset=39 +-.Linfo_string3: +- .asciz "defined_data" # string offset=44 +-.Linfo_string4: +- .asciz "char" # string offset=57 +- .section .debug_str_offsets,"",@progbits +- .long .Linfo_string0 +- .long .Linfo_string1 +- .long .Linfo_string2 +- .long .Linfo_string3 +- .long .Linfo_string4 +- .section .debug_addr,"",@progbits +- .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +-.Ldebug_addr_start0: +- .short 5 # DWARF version number +- .byte 8 # Address size +- .byte 0 # Segment selector size +-.Laddr_table_base0: +- .quad defined_data +-.Ldebug_addr_end0: +- .ident "Debian clang version 14.0.6" +- .section ".note.GNU-stack","",@progbits +- .addrsig +- .section .debug_line,"",@progbits +-.Lline_table_start0: +diff --git a/llvm/tools/llvm-nm/CMakeLists.txt b/llvm/tools/llvm-nm/CMakeLists.txt +index 5191e138d1c0..ec04f1e9d234 100644 +--- a/llvm/tools/llvm-nm/CMakeLists.txt ++++ b/llvm/tools/llvm-nm/CMakeLists.txt +@@ -8,7 +8,6 @@ set(LLVM_LINK_COMPONENTS + Object + Option + Support +- Symbolize + TargetParser + TextAPI + ) +diff --git a/llvm/tools/llvm-nm/Opts.td b/llvm/tools/llvm-nm/Opts.td +index 04d9f5db5cf8..60ac134269b3 100644 +--- a/llvm/tools/llvm-nm/Opts.td ++++ b/llvm/tools/llvm-nm/Opts.td +@@ -22,7 +22,6 @@ def export_symbols : FF<"export-symbols", "Export symbol list for all inputs">; + def extern_only : FF<"extern-only", "Show only external symbols">; + defm format : Eq<"format", "Specify output format: bsd (default), posix, sysv, darwin, just-symbols">, MetaVarName<"<format>">; + def help : FF<"help", "Display this help">; +-def line_numbers : FF<"line-numbers", "Use debugging information to print symbols' filenames and line numbers">; + def no_llvm_bc : FF<"no-llvm-bc", "Disable LLVM bitcode reader">; + def no_sort : FF<"no-sort", "Show symbols in order encountered">; + def no_weak : FF<"no-weak", "Show only non-weak symbols">; +@@ -68,7 +67,6 @@ def : JoinedOrSeparate<["-"], "f">, HelpText<"Alias for --format">, Alias<format + def : F<"h", "Alias for --help">, Alias<help>; + def : F<"g", "Alias for --extern-only">, Alias<extern_only>; + def : F<"j", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>; +-def : F<"l", "Alias for --line-numbers">, Alias<line_numbers>; + def : F<"m", "Alias for --format=darwin">, Alias<format_EQ>, AliasArgs<["darwin"]>; + def : F<"M", "Deprecated alias for --print-armap">, Alias<print_armap>, Flags<[HelpHidden]>; + def : F<"n", "Alias for --numeric-sort">, Alias<numeric_sort>; +diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp +index 051fa3e5bfa5..9a9e8bd146bb 100644 +--- a/llvm/tools/llvm-nm/llvm-nm.cpp ++++ b/llvm/tools/llvm-nm/llvm-nm.cpp +@@ -19,7 +19,6 @@ + #include "llvm/BinaryFormat/COFF.h" + #include "llvm/BinaryFormat/MachO.h" + #include "llvm/BinaryFormat/XCOFF.h" +-#include "llvm/DebugInfo/Symbolize/Symbolize.h" + #include "llvm/Demangle/Demangle.h" + #include "llvm/IR/Function.h" + #include "llvm/IR/LLVMContext.h" +@@ -98,7 +97,6 @@ static bool Demangle; + static bool DynamicSyms; + static bool ExportSymbols; + static bool ExternalOnly; +-static bool LineNumbers; + static OutputFormatTy OutputFormat; + static bool NoLLVMBitcode; + static bool NoSort; +@@ -553,6 +551,8 @@ static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S, + } + } + } ++ ++ outs() << "\n"; + } + + // Table that maps Darwin's Mach-O stab constants to strings to allow printing. +@@ -689,88 +689,9 @@ static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) { + } + } + +-static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer, +- const NMSymbol &S) { +- const auto *Obj = dyn_cast<ObjectFile>(S.Sym.getObject()); +- if (!Obj) +- return; +- const SymbolRef Sym(S.Sym); +- uint64_t SectionIndex = object::SectionedAddress::UndefSection; +- section_iterator Sec = cantFail(Sym.getSection()); +- if (Sec != Obj->section_end()) +- SectionIndex = Sec->getIndex(); +- object::SectionedAddress Address = {cantFail(Sym.getAddress()), SectionIndex}; +- +- std::string FileName; +- uint32_t Line; +- switch (S.TypeChar) { +- // For undefined symbols, find the first relocation for that symbol with a +- // line number. +- case 'U': { +- for (const SectionRef RelocsSec : Obj->sections()) { +- if (RelocsSec.relocations().empty()) +- continue; +- SectionRef TextSec = *cantFail(RelocsSec.getRelocatedSection()); +- if (!TextSec.isText()) +- continue; +- for (const RelocationRef R : RelocsSec.relocations()) { +- if (R.getSymbol() != Sym) +- continue; +- Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode( +- *Obj, {TextSec.getAddress() + R.getOffset(), SectionIndex}); +- if (!ResOrErr) { +- error(ResOrErr.takeError(), Obj->getFileName()); +- return; +- } +- if (ResOrErr->FileName == DILineInfo::BadString) +- return; +- FileName = std::move(ResOrErr->FileName); +- Line = ResOrErr->Line; +- break; +- } +- if (!FileName.empty()) +- break; +- } +- if (FileName.empty()) +- return; +- break; +- } +- case 't': +- case 'T': { +- Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(*Obj, Address); +- if (!ResOrErr) { +- error(ResOrErr.takeError(), Obj->getFileName()); +- return; +- } +- if (ResOrErr->FileName == DILineInfo::BadString) +- return; +- FileName = std::move(ResOrErr->FileName); +- Line = ResOrErr->Line; +- break; +- } +- default: { +- Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address); +- if (!ResOrErr) { +- error(ResOrErr.takeError(), Obj->getFileName()); +- return; +- } +- if (ResOrErr->DeclFile.empty()) +- return; +- FileName = std::move(ResOrErr->DeclFile); +- Line = ResOrErr->DeclLine; +- break; +- } +- } +- outs() << '\t' << FileName << ':' << Line; +-} +- + static void printSymbolList(SymbolicFile &Obj, + std::vector<NMSymbol> &SymbolList, bool printName, + StringRef ArchiveName, StringRef ArchitectureName) { +- std::optional<symbolize::LLVMSymbolizer> Symbolizer; +- if (LineNumbers) +- Symbolizer.emplace(); +- + if (!PrintFileName) { + if ((OutputFormat == bsd || OutputFormat == posix || + OutputFormat == just_symbols) && +@@ -877,7 +798,7 @@ static void printSymbolList(SymbolicFile &Obj, + printFormat); + } else if (OutputFormat == posix) { + outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " " +- << (MachO ? "0" : SymbolSizeStr); ++ << (MachO ? "0" : SymbolSizeStr) << "\n"; + } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) { + if (PrintAddress) + outs() << SymbolAddrStr << ' '; +@@ -898,14 +819,12 @@ static void printSymbolList(SymbolicFile &Obj, + } else + outs() << S.IndirectName << ")"; + } ++ outs() << "\n"; + } else if (OutputFormat == sysv) { + outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| " + << S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|" +- << SymbolSizeStr << "| |" << S.SectionName; ++ << SymbolSizeStr << "| |" << S.SectionName << "\n"; + } +- if (LineNumbers) +- printLineNumbers(*Symbolizer, S); +- outs() << '\n'; + } + + SymbolList.clear(); +@@ -2496,7 +2415,6 @@ int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) { + else + error("--format value should be one of: bsd, posix, sysv, darwin, " + "just-symbols"); +- LineNumbers = Args.hasArg(OPT_line_numbers); + NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc); + NoSort = Args.hasArg(OPT_no_sort); + NoWeakSymbols = Args.hasArg(OPT_no_weak); +-- +2.41.0.3.g1cb8d410ac + diff --git a/build/build-clang/revert-llvmorg-18-init-6193-gb88cffeafd39.patch b/build/build-clang/revert-llvmorg-18-init-6193-gb88cffeafd39.patch new file mode 100644 index 0000000000..a3ad8e0ed3 --- /dev/null +++ b/build/build-clang/revert-llvmorg-18-init-6193-gb88cffeafd39.patch @@ -0,0 +1,63 @@ +From be338a0b7be5040a7814d10d424f1555604cce7c Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Wed, 20 Sep 2023 10:08:21 +0900 +Subject: [PATCH 2/3] Revert "Explicitly set triple on line-numbers.test" + +This reverts commit b88cffeafd393d54f85feb641c4f8fd4fdb73fe4 because it +depends on c649f29c24c9fc1502d8d53e0c96c3d24b31de1a which we revert. +--- + llvm/test/tools/llvm-nm/X86/line-numbers.test | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/llvm/test/tools/llvm-nm/X86/line-numbers.test b/llvm/test/tools/llvm-nm/X86/line-numbers.test +index 4acda8afb2a4..4b9817ab5c62 100644 +--- a/llvm/test/tools/llvm-nm/X86/line-numbers.test ++++ b/llvm/test/tools/llvm-nm/X86/line-numbers.test +@@ -18,7 +18,7 @@ + ## of main.o. + # RUN: rm -rf %t + # RUN: split-file %s %t +-# RUN: llvm-mc -g --filetype=obj -triple=x86_64-pc-linux %t/main.s -o %t/main.o ++# RUN: llvm-mc -g --filetype=obj %t/main.s -o %t/main.o + # RUN: llvm-nm -l %t/main.o | FileCheck %s --match-full-lines --implicit-check-not={{.}} + # RUN: llvm-nm --line-numbers %t/main.o | FileCheck %s --match-full-lines --implicit-check-not={{.}} + +@@ -34,7 +34,7 @@ + + ## Check that in the absence of DWARF in the whole object, no line number + ## information is printed. +-# RUN: llvm-mc --filetype=obj %t/main.s -triple=x86_64-pc-linux -o %t/no-dwarf.o ++# RUN: llvm-mc --filetype=obj %t/main.s -o %t/no-dwarf.o + # RUN: llvm-nm -l %t/no-dwarf.o | FileCheck %s --check-prefix=NO-DWARF --match-full-lines --implicit-check-not={{.}} + + # NO-DWARF: 0000000000001234 a absolute_symbol +@@ -49,7 +49,7 @@ + + ## Check that printing line numbers for undefined values is not attempted in + ## the absence of any relocation section. +-# RUN: llvm-mc --filetype=obj %t/undef-no-reloc-sections.s -triple=x86_64-pc-linux -o %t/undef-no-reloc-sections.o ++# RUN: llvm-mc --filetype=obj %t/undef-no-reloc-sections.s -o %t/undef-no-reloc-sections.o + # RUN: llvm-nm --line-numbers %t/undef-no-reloc-sections.o | FileCheck %s --check-prefix=UNDEF-NO-RELOC-SECTIONS --match-full-lines --implicit-check-not={{.}} + + # UNDEF-NO-RELOC-SECTIONS: U undef +@@ -57,7 +57,7 @@ + ## Check that printing line numbers for undefined values does not include + ## relocations for non-text sections. This is broken out of main.s to ensure + ## that the data relocation for undef comes first. +-# RUN: llvm-mc -g --filetype=obj %t/undef-data-reloc.s -triple=x86_64-pc-linux -o %t/undef-data-reloc.o ++# RUN: llvm-mc -g --filetype=obj %t/undef-data-reloc.s -o %t/undef-data-reloc.o + # RUN: llvm-nm --line-numbers %t/undef-data-reloc.o | FileCheck %s --check-prefix=UNDEF-DATA-RELOC --match-full-lines --implicit-check-not={{.}} + + # UNDEF-DATA-RELOC: 0000000000000000 r data_reloc +@@ -65,7 +65,7 @@ + + ## Check that line numbers can be printed for data definitions. These are broken + ## out of main.s since their DWARF cannot be generated with llvm-mc -g. +-# RUN: llvm-mc -g --filetype=obj %t/data-dwarf.s -triple=x86_64-pc-linux -o %t/data-dwarf.o ++# RUN: llvm-mc -g --filetype=obj %t/data-dwarf.s -o %t/data-dwarf.o + # RUN: llvm-nm --line-numbers %t/data-dwarf.o | FileCheck %s --check-prefix=DATA-DWARF --match-full-lines --implicit-check-not={{.}} + + # DATA-DWARF: 0000000000000000 D defined_data /tmp/tmp.c:1 +-- +2.41.0.3.g1cb8d410ac + diff --git a/build/build-clang/revert-llvmorg-18-init-6208-g2baf4a06ef06.patch b/build/build-clang/revert-llvmorg-18-init-6208-g2baf4a06ef06.patch new file mode 100644 index 0000000000..ba2116d4ba --- /dev/null +++ b/build/build-clang/revert-llvmorg-18-init-6208-g2baf4a06ef06.patch @@ -0,0 +1,28 @@ +From 9d81bf8d2e457540b8bd93859baef79a043c8482 Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Wed, 20 Sep 2023 10:08:13 +0900 +Subject: [PATCH 1/3] Revert "Fix test added in D150987 to account for + different path separators which was causing the test to fail on Windows." + +This reverts commit 2baf4a06ef06c51c2ef09f981f204983b0f8082c because it +depends on c649f29c24c9fc1502d8d53e0c96c3d24b31de1a which we revert. +--- + llvm/test/tools/llvm-nm/X86/line-numbers.test | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/llvm/test/tools/llvm-nm/X86/line-numbers.test b/llvm/test/tools/llvm-nm/X86/line-numbers.test +index e254df67f955..4acda8afb2a4 100644 +--- a/llvm/test/tools/llvm-nm/X86/line-numbers.test ++++ b/llvm/test/tools/llvm-nm/X86/line-numbers.test +@@ -68,7 +68,7 @@ + # RUN: llvm-mc -g --filetype=obj %t/data-dwarf.s -triple=x86_64-pc-linux -o %t/data-dwarf.o + # RUN: llvm-nm --line-numbers %t/data-dwarf.o | FileCheck %s --check-prefix=DATA-DWARF --match-full-lines --implicit-check-not={{.}} + +-# DATA-DWARF: 0000000000000000 D defined_data /tmp{{\\|/}}tmp.c:1 ++# DATA-DWARF: 0000000000000000 D defined_data /tmp/tmp.c:1 + + #--- main.s + .text +-- +2.41.0.3.g1cb8d410ac + diff --git a/build/build-clang/skip-3-stages.json b/build/build-clang/skip-3-stages.json new file mode 100644 index 0000000000..79b1bf193f --- /dev/null +++ b/build/build-clang/skip-3-stages.json @@ -0,0 +1,6 @@ +{ + "skip_stages": "3", + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++", + "as": "{MOZ_FETCHES_DIR}/clang/bin/clang" +} diff --git a/build/build-clang/skip-stage-1-win64.json b/build/build-clang/skip-stage-1-win64.json new file mode 100644 index 0000000000..8dee151003 --- /dev/null +++ b/build/build-clang/skip-stage-1-win64.json @@ -0,0 +1,7 @@ +{ + "skip_stages": "1", + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang-cl.exe", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang-cl.exe", + "ml": "{MOZ_FETCHES_DIR}/clang/bin/clang-cl.exe", + "lib": "{MOZ_FETCHES_DIR}/clang/bin/llvm-lib.exe" +} diff --git a/build/build-clang/skip-stage-1.json b/build/build-clang/skip-stage-1.json new file mode 100644 index 0000000000..aa1101b13b --- /dev/null +++ b/build/build-clang/skip-stage-1.json @@ -0,0 +1,6 @@ +{ + "skip_stages": "1", + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++", + "as": "{MOZ_FETCHES_DIR}/clang/bin/clang" +} diff --git a/build/build-clang/unpoison-thread-stacks_clang_10.patch b/build/build-clang/unpoison-thread-stacks_clang_10.patch new file mode 100644 index 0000000000..563fa1d7bf --- /dev/null +++ b/build/build-clang/unpoison-thread-stacks_clang_10.patch @@ -0,0 +1,64 @@ +[winasan] Unpoison the stack in NtTerminateThread + +In long-running builds we've seen some ASan complaints during thread creation +that we suspect are due to leftover poisoning from previous threads whose stacks +occupied that memory. This patch adds a hook that unpoisons the stack just +before the NtTerminateThread syscall. + +Differential Revision: https://reviews.llvm.org/D52091 + +** Update for clang 9 ** : After some backouts, this patch eventually landed +upstream in a different form, as the TLS handler `asan_thread_exit`, but that +variant causes failures in our test suite, so revert the TLS handler in favor of +the interceptor approach from the first patch. + +diff --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp +index 417892aaedd..5fe86db44f4 100644 +--- a/compiler-rt/lib/asan/asan_win.cpp ++++ b/compiler-rt/lib/asan/asan_win.cpp +@@ -154,6 +154,14 @@ INTERCEPTOR_WINAPI(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES security, + thr_flags, tid); + } + ++INTERCEPTOR_WINAPI(void, NtTerminateThread, void *rcx) { ++ // Unpoison the terminating thread's stack because the memory may be re-used. ++ NT_TIB *tib = (NT_TIB *)NtCurrentTeb(); ++ uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit; ++ __asan_unpoison_memory_region(tib->StackLimit, stackSize); ++ return REAL(NtTerminateThread(rcx)); ++} ++ + // }}} + + namespace __asan { +@@ -168,7 +176,9 @@ void InitializePlatformInterceptors() { + + ASAN_INTERCEPT_FUNC(CreateThread); + ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter); +- ++ CHECK(::__interception::OverrideFunction("NtTerminateThread", ++ (uptr)WRAP(NtTerminateThread), ++ (uptr *)&REAL(NtTerminateThread))); + #ifdef _WIN64 + ASAN_INTERCEPT_FUNC(__C_specific_handler); + #else +@@ -380,19 +390,6 @@ __declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)( + void *, unsigned long, void *) = asan_thread_init; + #endif + +-static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) { +- if (reason == DLL_THREAD_DETACH) { +- // Unpoison the thread's stack because the memory may be re-used. +- NT_TIB *tib = (NT_TIB *)NtCurrentTeb(); +- uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit; +- __asan_unpoison_memory_region(tib->StackLimit, stackSize); +- } +-} +- +-#pragma section(".CRT$XLY", long, read) +-__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)( +- void *, unsigned long, void *) = asan_thread_exit; +- + WIN_FORCE_LINK(__asan_dso_reg_hook) + + // }}} diff --git a/build/build-clang/win64-ret-null-on-commitment-limit_clang_14.patch b/build/build-clang/win64-ret-null-on-commitment-limit_clang_14.patch new file mode 100644 index 0000000000..23b001bc68 --- /dev/null +++ b/build/build-clang/win64-ret-null-on-commitment-limit_clang_14.patch @@ -0,0 +1,14 @@ +diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +index 7c84cdc22ce4..e13fff03489e 100644 +--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp ++++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +@@ -157,7 +157,8 @@ void UnmapOrDie(void *addr, uptr size) { + static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type, + const char *mmap_type) { + error_t last_error = GetLastError(); +- if (last_error == ERROR_NOT_ENOUGH_MEMORY) ++ if (last_error == ERROR_NOT_ENOUGH_MEMORY || ++ last_error == ERROR_COMMITMENT_LIMIT) + return nullptr; + ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error); + } diff --git a/build/build-clang/win64.json b/build/build-clang/win64.json new file mode 100644 index 0000000000..9d4dcc589e --- /dev/null +++ b/build/build-clang/win64.json @@ -0,0 +1,7 @@ +{ + "target": "x86_64-pc-windows-msvc", + "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang-cl", + "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang-cl", + "ml": "{MOZ_FETCHES_DIR}/clang/bin/clang-cl", + "lib": "{MOZ_FETCHES_DIR}/clang/bin/llvm-lib" +} diff --git a/build/build-rust/README b/build/build-rust/README new file mode 100644 index 0000000000..34f7af63a5 --- /dev/null +++ b/build/build-rust/README @@ -0,0 +1,3 @@ +This directory is for patches to rust toolchains, see these docs for details: + +https://firefox-source-docs.mozilla.org/build/buildsystem/toolchains.html
\ No newline at end of file diff --git a/build/build-rust/cargo-vendor-std.patch b/build/build-rust/cargo-vendor-std.patch new file mode 100644 index 0000000000..1a79846d61 --- /dev/null +++ b/build/build-rust/cargo-vendor-std.patch @@ -0,0 +1,413 @@ +Teaches Cargo to source all std dependencies from vendored sources in the rust-src +component, making -Zbuild-std compatible with vendored builds. + +This was originally landed in https://github.com/rust-lang/cargo/pull/8834 +but was backed out for causing breakage in other situations. It works fine +for Firefox's usecase, though. + +Most of these changes just add/edit tests for the functionality. Only the +change to src/cargo/core/compiler/standard_lib.rs is important. + +diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs +index c456c58d5..333389bc8 100644 +--- a/src/cargo/core/compiler/standard_lib.rs ++++ b/src/cargo/core/compiler/standard_lib.rs +@@ -11,6 +11,7 @@ use crate::ops::{self, Packages}; + use crate::util::errors::CargoResult; + use crate::Config; + use std::collections::{HashMap, HashSet}; ++use std::fs; + use std::path::PathBuf; + + use super::BuildConfig; +@@ -73,27 +74,45 @@ pub fn resolve_std<'cfg>( + } + + let src_path = detect_sysroot_src_path(target_data)?; +- let to_patch = [ +- "rustc-std-workspace-core", +- "rustc-std-workspace-alloc", +- "rustc-std-workspace-std", +- ]; +- let patches = to_patch +- .iter() +- .map(|&name| { +- let source_path = SourceId::for_path(&src_path.join("library").join(name))?; +- let dep = Dependency::parse(name, None, source_path)?; ++ ++ // Special std packages should be pulled from `library/` and should be ++ // prefixed with `rustc-std-workspace-` in certain places. ++ let libs_prefix = "library/"; ++ let special_std_prefix = "rustc-std-workspace-"; ++ let libs_path = src_path.join(libs_prefix); ++ ++ // Crates in rust-src to build. libsysroot is in some sense the "root" package ++ // of std, as nothing else depends on it, so it must be explicitly added. ++ let mut members = vec![format!("{}sysroot", libs_prefix)]; ++ ++ // If rust-src contains a "vendor" directory, then patch in all the crates it contains. ++ let vendor_path = src_path.join("vendor"); ++ let vendor_dir = fs::read_dir(vendor_path)?; ++ let patches = vendor_dir ++ .into_iter() ++ .map(|entry| { ++ let entry = entry?; ++ let name = entry ++ .file_name() ++ .into_string() ++ .map_err(|_| anyhow::anyhow!("package name wasn't utf8"))?; ++ ++ // Remap the rustc-std-workspace crates to the actual rust-src libraries ++ let path = if let Some(real_name) = name.strip_prefix(special_std_prefix) { ++ // Record this crate as something to build in the workspace ++ members.push(format!("{}{}", libs_prefix, real_name)); ++ libs_path.join(&name) ++ } else { ++ entry.path() ++ }; ++ let source_path = SourceId::for_path(&path)?; ++ let dep = Dependency::parse(&name, None, source_path)?; + Ok(dep) + }) + .collect::<CargoResult<Vec<_>>>()?; ++ + let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap(); + let patch = HashMap::from([(crates_io_url, patches)]); +- let members = vec![ +- String::from("library/std"), +- String::from("library/core"), +- String::from("library/alloc"), +- String::from("library/sysroot"), +- ]; + let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new( + &src_path, + &Some(members), +diff --git a/tests/testsuite/mock-std/library/test/Cargo.toml b/tests/testsuite/mock-std/library/test/Cargo.toml +index b9f51eda7..fed5f3973 100644 +--- a/tests/testsuite/mock-std/library/test/Cargo.toml ++++ b/tests/testsuite/mock-std/library/test/Cargo.toml +@@ -9,3 +9,4 @@ std = { path = "../std" } + panic_unwind = { path = "../panic_unwind" } + compiler_builtins = { path = "../compiler_builtins" } + registry-dep-using-std = { version = "*", features = ['mockbuild'] } ++registry-dep-only-used-by-test = { version = "*" } +diff --git a/tests/testsuite/mock-std/library/test/src/lib.rs b/tests/testsuite/mock-std/library/test/src/lib.rs +index a112855f5..224b89bb2 100644 +--- a/tests/testsuite/mock-std/library/test/src/lib.rs ++++ b/tests/testsuite/mock-std/library/test/src/lib.rs +@@ -7,4 +7,5 @@ extern crate test; + pub use test::*; + + pub fn custom_api() { ++ registry_dep_only_used_by_test::wow_testing_is_so_easy(); + } +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml +new file mode 100644 +index 000000000..31ba65a98 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml +@@ -0,0 +1,9 @@ ++[package] ++name = "registry-dep-only-used-by-test" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++ ++[features] +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs +new file mode 100644 +index 000000000..a68d2aeef +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs +@@ -0,0 +1,2 @@ ++pub fn wow_testing_is_so_easy() { ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml +new file mode 100644 +index 000000000..f7e4ab232 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml +@@ -0,0 +1,12 @@ ++[package] ++name = "registry-dep-using-alloc" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++rustc-std-workspace-alloc = { version = "*", optional = true } ++rustc-std-workspace-core = { version = "*", optional = true } ++ ++[features] ++mockbuild = ["rustc-std-workspace-alloc", "rustc-std-workspace-core"] +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs +new file mode 100644 +index 000000000..b9ab30339 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs +@@ -0,0 +1,9 @@ ++#[cfg(feature = "mockbuild")] ++pub fn custom_api() { ++} ++ ++#[cfg(not(feature = "mockbuild"))] ++pub fn non_sysroot_api() { ++ core::custom_api(); ++ alloc::custom_api(); ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml +new file mode 100644 +index 000000000..befb83a63 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml +@@ -0,0 +1,11 @@ ++[package] ++name = "registry-dep-using-core" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++rustc-std-workspace-core = { version = "*", optional = true } ++ ++[features] ++mockbuild = ["rustc-std-workspace-core"] +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs +new file mode 100644 +index 000000000..f9dbac0f4 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs +@@ -0,0 +1,8 @@ ++#[cfg(feature = "mockbuild")] ++pub fn custom_api() { ++} ++ ++#[cfg(not(feature = "mockbuild"))] ++pub fn non_sysroot_api() { ++ core::custom_api(); ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml +new file mode 100644 +index 000000000..71ef0a42f +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml +@@ -0,0 +1,11 @@ ++[package] ++name = "registry-dep-using-std" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++rustc-std-workspace-std = { version = "*", optional = true } ++ ++[features] ++mockbuild = ["rustc-std-workspace-std"] +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs +new file mode 100644 +index 000000000..f3af39178 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs +@@ -0,0 +1,8 @@ ++#[cfg(feature = "mockbuild")] ++pub fn custom_api() { ++} ++ ++#[cfg(not(feature = "mockbuild"))] ++pub fn non_sysroot_api() { ++ std::custom_api(); ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml b/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml +new file mode 100644 +index 000000000..4465a08a8 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml +@@ -0,0 +1 @@ ++this file shouldn't be read +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml b/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml +new file mode 100644 +index 000000000..4465a08a8 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml +@@ -0,0 +1 @@ ++this file shouldn't be read +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml b/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml +new file mode 100644 +index 000000000..4465a08a8 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml +@@ -0,0 +1 @@ ++this file shouldn't be read +\ No newline at end of file +diff --git a/tests/testsuite/standard_lib.rs b/tests/testsuite/standard_lib.rs +index d3be303ea..486a9b4e0 100644 +--- a/tests/testsuite/standard_lib.rs ++++ b/tests/testsuite/standard_lib.rs +@@ -15,71 +15,18 @@ struct Setup { + } + + fn setup() -> Setup { +- // Our mock sysroot requires a few packages from crates.io, so make sure +- // they're "published" to crates.io. Also edit their code a bit to make sure +- // that they have access to our custom crates with custom apis. ++ // Register a version of one of the std dependencies that doesn't compile. ++ // This ensures that the mock-std's vendor is actually being used. + Package::new("registry-dep-using-core", "1.0.0") + .file( + "src/lib.rs", + " +- #![no_std] +- +- #[cfg(feature = \"mockbuild\")] +- pub fn custom_api() { +- } +- +- #[cfg(not(feature = \"mockbuild\"))] +- pub fn non_sysroot_api() { +- core::custom_api(); +- } ++ don't compile me bro!! + ", + ) + .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) + .feature("mockbuild", &["rustc-std-workspace-core"]) + .publish(); +- Package::new("registry-dep-using-alloc", "1.0.0") +- .file( +- "src/lib.rs", +- " +- #![no_std] +- +- extern crate alloc; +- +- #[cfg(feature = \"mockbuild\")] +- pub fn custom_api() { +- } +- +- #[cfg(not(feature = \"mockbuild\"))] +- pub fn non_sysroot_api() { +- core::custom_api(); +- alloc::custom_api(); +- } +- ", +- ) +- .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) +- .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) +- .feature( +- "mockbuild", +- &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], +- ) +- .publish(); +- Package::new("registry-dep-using-std", "1.0.0") +- .file( +- "src/lib.rs", +- " +- #[cfg(feature = \"mockbuild\")] +- pub fn custom_api() { +- } +- +- #[cfg(not(feature = \"mockbuild\"))] +- pub fn non_sysroot_api() { +- std::custom_api(); +- } +- ", +- ) +- .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) +- .feature("mockbuild", &["rustc-std-workspace-std"]) +- .publish(); + + let p = ProjectBuilder::new(paths::root().join("rustc-wrapper")) + .file( +@@ -335,6 +282,81 @@ fn depend_same_as_std() { + fn test() { + let setup = setup(); + ++ // Our mock sysroot requires a few packages from crates.io, so make sure ++ // they're "published" to crates.io. Also edit their code a bit to make sure ++ // that they have access to our custom crates with custom apis. ++ Package::new("registry-dep-using-core", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ #![no_std] ++ ++ #[cfg(feature = \"mockbuild\")] ++ pub fn custom_api() { ++ } ++ ++ #[cfg(not(feature = \"mockbuild\"))] ++ pub fn non_sysroot_api() { ++ core::custom_api(); ++ } ++ ", ++ ) ++ .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) ++ .feature("mockbuild", &["rustc-std-workspace-core"]) ++ .publish(); ++ Package::new("registry-dep-using-alloc", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ #![no_std] ++ ++ extern crate alloc; ++ ++ #[cfg(feature = \"mockbuild\")] ++ pub fn custom_api() { ++ } ++ ++ #[cfg(not(feature = \"mockbuild\"))] ++ pub fn non_sysroot_api() { ++ core::custom_api(); ++ alloc::custom_api(); ++ } ++ ", ++ ) ++ .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) ++ .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) ++ .feature( ++ "mockbuild", ++ &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], ++ ) ++ .publish(); ++ Package::new("registry-dep-using-std", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ #[cfg(feature = \"mockbuild\")] ++ pub fn custom_api() { ++ } ++ ++ #[cfg(not(feature = \"mockbuild\"))] ++ pub fn non_sysroot_api() { ++ std::custom_api(); ++ } ++ ", ++ ) ++ .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) ++ .feature("mockbuild", &["rustc-std-workspace-std"]) ++ .publish(); ++ Package::new("registry-dep-only-used-by-test", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ pub fn wow_testing_is_so_easy() { ++ } ++ ", ++ ) ++ .publish(); ++ + let p = project() + .file( + "src/lib.rs", diff --git a/build/build-rust/example.patch b/build/build-rust/example.patch new file mode 100644 index 0000000000..09a00bf22f --- /dev/null +++ b/build/build-rust/example.patch @@ -0,0 +1,12 @@ +diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md +index 2a4c42ea0a4..c94b24e9cb1 100644 +--- a/CONTRIBUTING.md ++++ b/CONTRIBUTING.md +@@ -1,5 +1,7 @@ + # Contributing to Rust + ++Hello this is a harmless little example patch! ++ + Thank you for your interest in contributing to Rust! + + To get started, read the [Getting Started] guide in the [rustc-dev-guide]. diff --git a/build/build-rust/rust-vendor-std.patch b/build/build-rust/rust-vendor-std.patch new file mode 100644 index 0000000000..e3ad25d1b0 --- /dev/null +++ b/build/build-rust/rust-vendor-std.patch @@ -0,0 +1,81 @@ +Teaches Rust's build system to vendor std's dependencies into the +rust-src component. + +This was originally landed in https://github.com/rust-lang/rust/pull/78790 +but was backed out for causing some breakage for distro maintainers who +need to build Rust itself in a vendored/offline context. It doesn't actually +fetch anything interesting from crates.io, just the magic fake std/core crates +that exist to make the build work right. Those crates *are* vendored but +their contents are ignored in favour of the actual stdlib. + +For firefox's purposes, these patches still work fine, and are necessary +to make -Zbuild-std work in a vendored environment. + +diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs +index 3cb0eccd324..a3b8154c024 100644 +--- a/src/bootstrap/src/core/build_steps/dist.rs ++++ b/src/bootstrap/src/core/build_steps/dist.rs +@@ -905,6 +905,31 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball { + builder.copy(&builder.src.join(file), &dst_src.join(file)); + } + ++ // libsysroot includes std and everything else, so vendoring it ++ // creates exactly what's needed for `cargo -Zbuild-std` or any ++ // other analysis of the stdlib's source. Cargo also needs help ++ // finding the lock, so we copy it to libsysroot temporarily. ++ // ++ // Note that this requires std to only have one version of each ++ // crate. e.g. two versions of getopts won't be patchable. ++ let dst_libsysroot = dst_src.join("library/sysroot"); ++ let dst_vendor = dst_src.join("vendor"); ++ let root_lock = dst_src.join("Cargo.lock"); ++ let temp_lock = dst_libsysroot.join("Cargo.lock"); ++ ++ // `cargo vendor` will delete everything from the lockfile that ++ // isn't used by libsysroot, so we need to not use any links! ++ builder.really_copy(&root_lock, &temp_lock); ++ ++ let mut cmd = Command::new(&builder.initial_cargo); ++ cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libsysroot); ++ cmd.env("RUSTC_BOOTSTRAP", "1"); ++ builder.info("Dist src"); ++ let _time = timeit(builder); ++ builder.run(&mut cmd); ++ ++ builder.remove(&temp_lock); ++ + tarball.generate() + } + } +diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs +index 3ed53452309..1fc0d887748 100644 +--- a/src/bootstrap/src/lib.rs ++++ b/src/bootstrap/src/lib.rs +@@ -1437,6 +1437,27 @@ fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, DependencyType)> { + paths + } + ++ /// Copies a file from `src` to `dst` and doesn't use links, so ++ /// that the copy can be modified without affecting the original. ++ pub fn really_copy(&self, src: &Path, dst: &Path) { ++ if self.config.dry_run() { ++ return; ++ } ++ self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst)); ++ if src == dst { ++ return; ++ } ++ let _ = fs::remove_file(&dst); ++ let metadata = t!(src.symlink_metadata()); ++ if let Err(e) = fs::copy(src, dst) { ++ panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e) ++ } ++ t!(fs::set_permissions(dst, metadata.permissions())); ++ let atime = FileTime::from_last_access_time(&metadata); ++ let mtime = FileTime::from_last_modification_time(&metadata); ++ t!(filetime::set_file_times(dst, atime, mtime)); ++ } ++ + /// Copies a file from `src` to `dst` + pub fn copy(&self, src: &Path, dst: &Path) { + self.copy_internal(src, dst, false); diff --git a/build/buildconfig.py b/build/buildconfig.py new file mode 100644 index 0000000000..527690c2b0 --- /dev/null +++ b/build/buildconfig.py @@ -0,0 +1,19 @@ +# 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/. + +import sys + +from mozbuild.backend.configenvironment import PartialConfigEnvironment +from mozbuild.base import MozbuildObject + +config = MozbuildObject.from_environment() +partial_config = PartialConfigEnvironment(config.topobjdir) + +for var in ("topsrcdir", "topobjdir"): + value = getattr(config, var) + setattr(sys.modules[__name__], var, value) + +for var in ("defines", "substs", "get_dependencies"): + value = getattr(partial_config, var) + setattr(sys.modules[__name__], var, value) diff --git a/build/cargo-host-linker b/build/cargo-host-linker new file mode 100755 index 0000000000..cbd0472bf7 --- /dev/null +++ b/build/cargo-host-linker @@ -0,0 +1,3 @@ +#!/bin/sh +# See comment in cargo-linker. +eval ${MOZ_CARGO_WRAP_HOST_LD} ${MOZ_CARGO_WRAP_HOST_LDFLAGS} '"$@"' diff --git a/build/cargo-host-linker.bat b/build/cargo-host-linker.bat new file mode 100644 index 0000000000..80e6eab273 --- /dev/null +++ b/build/cargo-host-linker.bat @@ -0,0 +1,3 @@ +@echo off +REM See comment in cargo-linker (without extension) +%MOZ_CARGO_WRAP_HOST_LD% %MOZ_CARGO_WRAP_HOST_LDFLAGS% %* diff --git a/build/cargo-linker b/build/cargo-linker new file mode 100755 index 0000000000..898e21d482 --- /dev/null +++ b/build/cargo-linker @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +# If you want to use a custom linker with Cargo, Cargo requires that you +# specify it in Cargo.toml or via the matching environment variable. +# Passing extra options to the linker is possible with Cargo via +# RUSTFLAGS='-C link-args', but testing showed that doing this reliably +# was difficult. +# +# Our solution to these problems is to use this wrapper script. We pass +# in the LD and the LDFLAGS to use via environment variables. +# +# * MOZ_CARGO_WRAP_LD is equivalent to CC on Unix-y platforms, and CC +# frequently has additional arguments in addition to the compiler +# itself. +# +# * MOZ_CARGO_WRAP_LDFLAGS contains space-separated arguments to pass, +# and not quoting it ensures that each of those arguments is passed +# as a separate argument to the actual LD. +# +# * In rare cases, we also need MOZ_CARGO_WRAP_LD_CXX, which is the +# equivalent of CXX, when linking C++ code. Usually, this should +# simply work by the use of CC and -lstdc++ (added by cc-rs). +# However, in the case of sanitizer runtimes, there is a separate +# runtime for C and C++ and linking C++ code with the C runtime can +# fail if the requested feature is in the C++ runtime only (bug 1747298). + +import os +import sys + +# This is not necessarily run with a virtualenv python, so add +# the necessary directory for the shellutil module. +base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +sys.path.insert(0, os.path.join(base_dir, "python", "mozbuild")) +from mozbuild.shellutil import split + + +SANITIZERS = { + "asan": "address", + "hwasan": "hwaddress", + "lsan": "leak", + "msan": "memory", + "tsan": "thread", +} + +use_clang_sanitizer = os.environ.get("MOZ_CLANG_NEWER_THAN_RUSTC_LLVM") +wrap_ld = os.environ["MOZ_CARGO_WRAP_LD"] +args = split(os.environ["MOZ_CARGO_WRAP_LDFLAGS"]) +for arg in sys.argv[1:]: + if arg in ["-lc++", "-lstdc++"]: + wrap_ld = os.environ["MOZ_CARGO_WRAP_LD_CXX"] + elif use_clang_sanitizer and arg.endswith("san.a"): + # When clang is newer than rustc's LLVM, we replace rust's sanitizer + # runtimes with clang's. + filename = os.path.basename(arg) + prefix, dot, suffix = filename[:-2].rpartition(".") + if ( + prefix.startswith("librustc-") + and prefix.endswith("_rt") and dot == "." + ): + args.append(f"-fsanitize={SANITIZERS[suffix]}") + continue + args.append(arg) + +wrap_ld = split(wrap_ld) +os.execvp(wrap_ld[0], wrap_ld + args) diff --git a/build/cargo-linker.bat b/build/cargo-linker.bat new file mode 100644 index 0000000000..36ab80dac3 --- /dev/null +++ b/build/cargo-linker.bat @@ -0,0 +1,2 @@ +@echo off +%MOZ_CARGO_WRAP_LD% %MOZ_CARGO_WRAP_LDFLAGS% %* diff --git a/build/cargo/cargo-audit.yaml b/build/cargo/cargo-audit.yaml new file mode 100644 index 0000000000..8efb56acff --- /dev/null +++ b/build/cargo/cargo-audit.yaml @@ -0,0 +1,6 @@ +--- +command: cargo-audit +continue_on_error: false +cargo_build_flags: + - -f + - "{topsrcdir}/Cargo.lock" diff --git a/build/cargo/cargo-check.yaml b/build/cargo/cargo-check.yaml new file mode 100644 index 0000000000..54fe0fb825 --- /dev/null +++ b/build/cargo/cargo-check.yaml @@ -0,0 +1,5 @@ +--- +command: cargo-check +continue_on_error: true +# cargo_build_flags: [] +requires_export: true diff --git a/build/cargo/cargo-clippy.yaml b/build/cargo/cargo-clippy.yaml new file mode 100644 index 0000000000..74e57cdedf --- /dev/null +++ b/build/cargo/cargo-clippy.yaml @@ -0,0 +1,5 @@ +--- +command: cargo-clippy +continue_on_error: true +requires_export: true +# cargo_build_flags: [] diff --git a/build/cargo/cargo-deny.yaml b/build/cargo/cargo-deny.yaml new file mode 100644 index 0000000000..fde45e37d9 --- /dev/null +++ b/build/cargo/cargo-deny.yaml @@ -0,0 +1,10 @@ +--- +command: cargo-deny +continue_on_error: true +cargo_build_flags: + - --frozen + - --manifest-path + - "{manifest}" + - --target={arch} + - --features + - "{features}" diff --git a/build/cargo/cargo-machete.yaml b/build/cargo/cargo-machete.yaml new file mode 100644 index 0000000000..42ec301ee0 --- /dev/null +++ b/build/cargo/cargo-machete.yaml @@ -0,0 +1,4 @@ +--- +command: cargo-machete +continue_on_error: true +cargo_build_flags: ["{topsrcdir}/{directory}/Cargo.toml"] diff --git a/build/cargo/cargo-udeps.yaml b/build/cargo/cargo-udeps.yaml new file mode 100644 index 0000000000..a33cfcf873 --- /dev/null +++ b/build/cargo/cargo-udeps.yaml @@ -0,0 +1,4 @@ +--- +command: cargo-udeps +continue_on_error: true +# cargo_build_flags: [] diff --git a/build/checksums.py b/build/checksums.py new file mode 100755 index 0000000000..1a393b4a6d --- /dev/null +++ b/build/checksums.py @@ -0,0 +1,154 @@ +#!/usr/bin/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/. + +import hashlib +import logging +import os +from optparse import OptionParser + +logger = logging.getLogger("checksums.py") + + +def digest_file(filename, digest, chunk_size=131072): + """Produce a checksum for the file specified by 'filename'. 'filename' + is a string path to a file that is opened and read in this function. The + checksum algorithm is specified by 'digest' and is a valid OpenSSL + algorithm. If the digest used is not valid or Python's hashlib doesn't + work, the None object will be returned instead. The size of blocks + that this function will read from the file object it opens based on + 'filename' can be specified by 'chunk_size', which defaults to 1K""" + assert not os.path.isdir(filename), "this function only works with files" + + logger.debug("Creating new %s object" % digest) + h = hashlib.new(digest) + with open(filename, "rb") as f: + while True: + data = f.read(chunk_size) + if not data: + logger.debug("Finished reading in file") + break + h.update(data) + hash = h.hexdigest() + logger.debug("Hash for %s is %s" % (filename, hash)) + return hash + + +def process_files(dirs, output_filename, digests): + """This function takes a list of directory names, 'drs'. It will then + compute the checksum for each of the files in these by by opening the files. + Once each file is read and its checksum is computed, this function + will write the information to the file specified by 'output_filename'. + The path written in the output file will have anything specified by 'strip' + removed from the path. The output file is closed before returning nothing + The algorithm to compute checksums with can be specified by 'digests' + and needs to be a list of valid OpenSSL algorithms. + + The output file is written in the format: + <hash> <algorithm> <filesize> <filepath> + Example: + d1fa09a<snip>e4220 sha1 14250744 firefox-4.0b6pre.en-US.mac64.dmg + """ + + if os.path.exists(output_filename): + logger.debug('Overwriting existing checksums file "%s"' % output_filename) + else: + logger.debug('Creating a new checksums file "%s"' % output_filename) + with open(output_filename, "w+") as output: + for d in dirs: + for root, dirs, files in os.walk(d): + for f in files: + full = os.path.join(root, f) + rel = os.path.relpath(full, d) + + for digest in digests: + hash = digest_file(full, digest) + + output.write( + "%s %s %s %s\n" % (hash, digest, os.path.getsize(full), rel) + ) + + +def setup_logging(level=logging.DEBUG): + """This function sets up the logging module using a speficiable logging + module logging level. The default log level is DEBUG. + + The output is in the format: + <level> - <message> + Example: + DEBUG - Finished reading in file""" + + logger = logging.getLogger("checksums.py") + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + handler.setLevel(level) + formatter = logging.Formatter("%(levelname)s - %(message)s") + handler.setFormatter(formatter) + logger.addHandler(handler) + + +def main(): + """This is a main function that parses arguments, sets up logging + and generates a checksum file""" + # Parse command line arguments + parser = OptionParser() + parser.add_option( + "-d", + "--digest", + help="checksum algorithm to use", + action="append", + dest="digests", + ) + parser.add_option( + "-o", + "--output", + help="output file to use", + action="store", + dest="outfile", + default="checksums", + ) + parser.add_option( + "-v", + "--verbose", + help="Be noisy (takes precedence over quiet)", + action="store_true", + dest="verbose", + default=False, + ) + parser.add_option( + "-q", + "--quiet", + help="Be quiet", + action="store_true", + dest="quiet", + default=False, + ) + + options, args = parser.parse_args() + + # Figure out which logging level to use + if options.verbose: + loglevel = logging.DEBUG + elif options.quiet: + loglevel = logging.ERROR + else: + loglevel = logging.INFO + + # Set up logging + setup_logging(loglevel) + + # Validate the digest type to use + if not options.digests: + options.digests = ["sha1"] + + for i in args: + if not os.path.isdir(i): + logger.error("%s is not a directory" % i) + exit(1) + + process_files(args, options.outfile, options.digests) + + +if __name__ == "__main__": + main() diff --git a/build/clang-plugin/.clang-format b/build/clang-plugin/.clang-format new file mode 100644 index 0000000000..9b3aa8b721 --- /dev/null +++ b/build/clang-plugin/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: LLVM diff --git a/build/clang-plugin/ArithmeticArgChecker.cpp b/build/clang-plugin/ArithmeticArgChecker.cpp new file mode 100644 index 0000000000..0042961b32 --- /dev/null +++ b/build/clang-plugin/ArithmeticArgChecker.cpp @@ -0,0 +1,60 @@ +/* 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 "ArithmeticArgChecker.h" +#include "CustomMatchers.h" + +void ArithmeticArgChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + callExpr(allOf(hasDeclaration(noArithmeticExprInArgs()), + anyOf(hasDescendant( + binaryOperator( + allOf(binaryArithmeticOperator(), + hasLHS(hasDescendant(declRefExpr())), + hasRHS(hasDescendant(declRefExpr())))) + .bind("node")), + hasDescendant( + unaryOperator( + allOf(unaryArithmeticOperator(), + hasUnaryOperand(allOf( + hasType(builtinType()), + anyOf(hasDescendant(declRefExpr()), + declRefExpr()))))) + .bind("node"))))) + .bind("call"), + this); + AstMatcher->addMatcher( + cxxConstructExpr( + allOf(hasDeclaration(noArithmeticExprInArgs()), + anyOf(hasDescendant( + binaryOperator( + allOf(binaryArithmeticOperator(), + hasLHS(hasDescendant(declRefExpr())), + hasRHS(hasDescendant(declRefExpr())))) + .bind("node")), + hasDescendant( + unaryOperator( + allOf(unaryArithmeticOperator(), + hasUnaryOperand(allOf( + hasType(builtinType()), + anyOf(hasDescendant(declRefExpr()), + declRefExpr()))))) + .bind("node"))))) + .bind("call"), + this); +} + +void ArithmeticArgChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = + "cannot pass an arithmetic expression of built-in types to %0"; + const Expr *Expression = Result.Nodes.getNodeAs<Expr>("node"); + if (const CallExpr *Call = Result.Nodes.getNodeAs<CallExpr>("call")) { + diag(Expression->getBeginLoc(), Error, DiagnosticIDs::Error) + << Call->getDirectCallee(); + } else if (const CXXConstructExpr *Ctr = + Result.Nodes.getNodeAs<CXXConstructExpr>("call")) { + diag(Expression->getBeginLoc(), Error, DiagnosticIDs::Error) + << Ctr->getConstructor(); + } +} diff --git a/build/clang-plugin/ArithmeticArgChecker.h b/build/clang-plugin/ArithmeticArgChecker.h new file mode 100644 index 0000000000..62165b716b --- /dev/null +++ b/build/clang-plugin/ArithmeticArgChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef ArithmeticArgChecker_h__ +#define ArithmeticArgChecker_h__ + +#include "plugin.h" + +class ArithmeticArgChecker : public BaseCheck { +public: + ArithmeticArgChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/AssertAssignmentChecker.cpp b/build/clang-plugin/AssertAssignmentChecker.cpp new file mode 100644 index 0000000000..467de28d63 --- /dev/null +++ b/build/clang-plugin/AssertAssignmentChecker.cpp @@ -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 "AssertAssignmentChecker.h" +#include "CustomMatchers.h" + +void AssertAssignmentChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + callExpr(isAssertAssignmentTestFunc()).bind("funcCall"), this); +} + +void AssertAssignmentChecker::check(const MatchFinder::MatchResult &Result) { + const CallExpr *FuncCall = Result.Nodes.getNodeAs<CallExpr>("funcCall"); + + if (FuncCall && hasSideEffectAssignment(FuncCall)) { + diag(FuncCall->getBeginLoc(), "Forbidden assignment in assert expression", + DiagnosticIDs::Error); + } +} diff --git a/build/clang-plugin/AssertAssignmentChecker.h b/build/clang-plugin/AssertAssignmentChecker.h new file mode 100644 index 0000000000..5e47b62183 --- /dev/null +++ b/build/clang-plugin/AssertAssignmentChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef AssertAssignmentChecker_h__ +#define AssertAssignmentChecker_h__ + +#include "plugin.h" + +class AssertAssignmentChecker : public BaseCheck { +public: + AssertAssignmentChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/BaseCheck.h b/build/clang-plugin/BaseCheck.h new file mode 100644 index 0000000000..867b82d2ad --- /dev/null +++ b/build/clang-plugin/BaseCheck.h @@ -0,0 +1,34 @@ +/* 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/. */ + +#ifndef BaseCheck_h__ +#define BaseCheck_h__ + +class MozContext {}; +typedef MozContext ContextType; + +class BaseCheck : public MatchFinder::MatchCallback { +public: + BaseCheck(StringRef CheckName, ContextType *Context) {} + virtual void registerMatchers(MatchFinder *Finder) {} + virtual void registerPPCallbacks(CompilerInstance &CI) {} + virtual void check(const MatchFinder::MatchResult &Result) {} + DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning) { + DiagnosticsEngine &Diag = Context->getDiagnostics(); + unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(Level, Description); + return Diag.Report(Loc, ID); + } + +private: + void run(const MatchFinder::MatchResult &Result) override { + Context = Result.Context; + check(Result); + } + +private: + ASTContext *Context; +}; + +#endif diff --git a/build/clang-plugin/CanRunScriptChecker.cpp b/build/clang-plugin/CanRunScriptChecker.cpp new file mode 100644 index 0000000000..613fe81e19 --- /dev/null +++ b/build/clang-plugin/CanRunScriptChecker.cpp @@ -0,0 +1,450 @@ +/* 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/. */ + +/** + * This checker implements the "can run script" analysis. The idea is to detect + * functions that can run script that are being passed reference-counted + * arguments (including "this") whose refcount might go to zero as a result of + * the script running. We want to prevent that. + * + * The approach is to attempt to enforce the following invariants on the call + * graph: + * + * 1) Any caller of a MOZ_CAN_RUN_SCRIPT function is itself MOZ_CAN_RUN_SCRIPT. + * 2) If a virtual MOZ_CAN_RUN_SCRIPT method overrides a base class method, + * that base class method is also MOZ_CAN_RUN_SCRIPT. + * + * Invariant 2 ensures that we don't accidentally call a MOZ_CAN_RUN_SCRIPT + * function via a base-class virtual call. Invariant 1 ensures that + * the property of being able to run script propagates up the callstack. There + * is an opt-out for invariant 1: A function (declaration _or_ implementation) + * can be decorated with MOZ_CAN_RUN_SCRIPT_BOUNDARY to indicate that we do not + * require it or any of its callers to be MOZ_CAN_RUN_SCRIPT even if it calls + * MOZ_CAN_RUN_SCRIPT functions. + * + * There are two known holes in invariant 1, apart from the + * MOZ_CAN_RUN_SCRIPT_BOUNDARY opt-out: + * + * - Functions called via function pointers can be MOZ_CAN_RUN_SCRIPT even if + * their caller is not, because we have no way to determine from the function + * pointer what function is being called. + * - MOZ_CAN_RUN_SCRIPT destructors can happen in functions that are not + * MOZ_CAN_RUN_SCRIPT. + * https://bugzilla.mozilla.org/show_bug.cgi?id=1535523 tracks this. + * + * Given those invariants we then require that when calling a MOZ_CAN_RUN_SCRIPT + * function all refcounted arguments (including "this") satisfy one of these + * conditions: + * a) The argument is held via a strong pointer on the stack. + * b) The argument is a const strong pointer member of "this". We know "this" + * is being kept alive, and a const strong pointer member can't drop its ref + * until "this" dies. + * c) The argument is an argument of the caller (and hence held by a strong + * pointer somewhere higher up the callstack). + * d) The argument is explicitly annotated with MOZ_KnownLive, which indicates + * that something is guaranteed to keep it alive (e.g. it's rooted via a JS + * reflector). + * e) The argument is constexpr and therefore cannot disappear. + */ + +#include "CanRunScriptChecker.h" +#include "CustomMatchers.h" +#include "clang/Lex/Lexer.h" + +void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) { + auto Refcounted = qualType(hasDeclaration(cxxRecordDecl(isRefCounted()))); + auto StackSmartPtr = ignoreTrivials(declRefExpr(to(varDecl( + hasAutomaticStorageDuration(), hasType(isSmartPtrToRefCounted()))))); + auto ConstMemberOfThisSmartPtr = + memberExpr(hasType(isSmartPtrToRefCounted()), hasType(isConstQualified()), + hasObjectExpression(cxxThisExpr())); + // A smartptr can be known-live for three reasons: + // 1) It's declared on the stack. + // 2) It's a const member of "this". We know "this" is alive (recursively) + // and const members can't change their value hence can't drop their + // reference until "this" gets destroyed. + // 3) It's an immediate temporary being constructed at the point where the + // call is happening. + auto KnownLiveSmartPtr = anyOf( + StackSmartPtr, ConstMemberOfThisSmartPtr, + ignoreTrivials(cxxConstructExpr(hasType(isSmartPtrToRefCounted())))); + + auto MozKnownLiveCall = + ignoreTrivials(callExpr(callee(functionDecl(hasName("MOZ_KnownLive"))))); + + // Params of the calling function are presumed live, because it itself should + // be MOZ_CAN_RUN_SCRIPT. Note that this is subject to + // https://bugzilla.mozilla.org/show_bug.cgi?id=1537656 at the moment. + auto KnownLiveParam = anyOf( + // "this" is OK + cxxThisExpr(), + // A parameter of the calling function is OK. + declRefExpr(to(parmVarDecl()))); + + auto KnownLiveMemberOfParam = + memberExpr(hasKnownLiveAnnotation(), + hasObjectExpression(anyOf( + ignoreTrivials(KnownLiveParam), + declRefExpr(to(varDecl(hasAutomaticStorageDuration())))))); + + // A matcher that matches various things that are known to be live directly, + // without making any assumptions about operators. + auto KnownLiveBaseExceptRef = anyOf( + // Things that are known to be a stack or immutable refptr. + KnownLiveSmartPtr, + // MOZ_KnownLive() calls. + MozKnownLiveCall, + // Params of the caller function. + KnownLiveParam, + // Members of the params that are marked as MOZ_KNOWN_LIVE + KnownLiveMemberOfParam, + // Constexpr things. + declRefExpr(to(varDecl(isConstexpr())))); + + // A reference of smart ptr which is initialized with known live thing is OK. + // FIXME: This does not allow nested references. + auto RefToKnownLivePtr = ignoreTrivials(declRefExpr(to(varDecl( + hasAutomaticStorageDuration(), hasType(referenceType()), + hasInitializer(anyOf( + KnownLiveSmartPtr, KnownLiveParam, KnownLiveMemberOfParam, + conditionalOperator( + hasFalseExpression(ignoreTrivials(anyOf( + KnownLiveSmartPtr, KnownLiveParam, KnownLiveMemberOfParam, + declRefExpr(to(varDecl(isConstexpr()))), + // E.g., for RefPtr<T>::operator*() + cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), + hasAnyArgument( + anyOf(KnownLiveBaseExceptRef, + ignoreTrivials(KnownLiveMemberOfParam))), + argumentCountIs(1)), + // E.g., for *T + unaryOperator(unaryDereferenceOperator(), + hasUnaryOperand( + ignoreTrivials(KnownLiveBaseExceptRef)))))), + hasTrueExpression(ignoreTrivials(anyOf( + KnownLiveSmartPtr, KnownLiveParam, KnownLiveMemberOfParam, + declRefExpr(to(varDecl(isConstexpr()))), + // E.g., for RefPtr<T>::operator*() + cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), + hasAnyArgument( + anyOf(KnownLiveBaseExceptRef, + ignoreTrivials(KnownLiveMemberOfParam))), + argumentCountIs(1)), + // E.g., for *T + unaryOperator(unaryDereferenceOperator(), + hasUnaryOperand(ignoreTrivials( + KnownLiveBaseExceptRef))))))))))))); + + // A matcher that matches various things that are known to be live directly, + // without making any assumptions about operators. + auto KnownLiveBase = + anyOf(KnownLiveBaseExceptRef, + // Smart pointer refs initialized with known live smart ptrs. + RefToKnownLivePtr); + + // A matcher that matches various known-live things that don't involve + // non-unary operators. + auto KnownLiveSimple = anyOf( + // Things that are just known live. + KnownLiveBase, + // Method calls on a live things that are smart ptrs. Note that we don't + // want to allow general method calls on live things, because those can + // return non-live objects (e.g. consider "live_pointer->foo()" as an + // example). For purposes of this analysis we are assuming the method + // calls on smart ptrs all just return the pointer inside, + cxxMemberCallExpr( + on(anyOf(allOf(hasType(isSmartPtrToRefCounted()), KnownLiveBase), + // Allow it if calling a member method which is marked as + // MOZ_KNOWN_LIVE + KnownLiveMemberOfParam))), + // operator* or operator-> on a thing that is already known to be live. + cxxOperatorCallExpr( + hasAnyOverloadedOperatorName("*", "->"), + hasAnyArgument( + anyOf(KnownLiveBase, ignoreTrivials(KnownLiveMemberOfParam))), + argumentCountIs(1)), + // A dereference on a thing that is known to be live. This is _not_ + // caught by the "operator* or operator->" clause above, because + // cxxOperatorCallExpr() only catches cases when a class defines + // operator*. The default (built-in) operator* matches unaryOperator() + // instead.), + unaryOperator( + unaryDereferenceOperator(), + hasUnaryOperand( + // If we're doing *someArg, the argument of the dereference is an + // ImplicitCastExpr LValueToRValue which has the DeclRefExpr as an + // argument. We could try to match that explicitly with a custom + // matcher (none of the built-in matchers seem to match on the + // thing being cast for an implicitCastExpr), but it's simpler to + // just use ignoreTrivials to strip off the cast. + ignoreTrivials(KnownLiveBase))), + // Taking a pointer to a live reference. We explicitly want to exclude + // things that are not of type reference-to-refcounted or type refcounted, + // because if someone takes a pointer to a pointer to refcounted or a + // pointer to a smart ptr and passes those in to a callee that definitely + // does not guarantee liveness; in fact the callee could modify those + // things! In practice they would be the wrong type anyway, though, so + // it's hard to add a test for this. + unaryOperator(hasOperatorName("&"), + hasUnaryOperand(allOf(anyOf(hasType(references(Refcounted)), + hasType(Refcounted)), + ignoreTrivials(KnownLiveBase))))); + + auto KnownLive = anyOf( + // Anything above, of course. + KnownLiveSimple, + // Conditional operators where both arms are live. + conditionalOperator(hasFalseExpression(ignoreTrivials(KnownLiveSimple)), + hasTrueExpression(ignoreTrivials(KnownLiveSimple))) + // We're not handling cases like a dereference of a conditional operator, + // mostly because handling a dereference in general is so ugly. I + // _really_ wish I could just write a recursive matcher here easily. + ); + + auto InvalidArg = ignoreTrivialsConditional( + // We want to consider things if there is anything refcounted involved, + // including in any of the trivials that we otherwise strip off. + anyOf(hasType(Refcounted), hasType(pointsTo(Refcounted)), + hasType(references(Refcounted)), hasType(isSmartPtrToRefCounted())), + // We want to find any expression, + expr( + // which is not known live, + unless(KnownLive), + // and which is not a default arg with value nullptr, since those are + // always safe, + unless(cxxDefaultArgExpr(isNullDefaultArg())), + // and which is not a literal nullptr, + unless(cxxNullPtrLiteralExpr()), expr().bind("invalidArg"))); + + // A matcher which will mark the first invalid argument it finds invalid, but + // will always match, even if it finds no invalid arguments, so it doesn't + // preclude other matchers from running and maybe finding invalid args. + auto OptionalInvalidExplicitArg = anyOf( + // We want to find any argument which is invalid. + hasAnyArgument(InvalidArg), + + // This makes this matcher optional. + anything()); + + // Please note that the hasCanRunScriptAnnotation() matchers are not present + // directly in the cxxMemberCallExpr, callExpr and constructExpr matchers + // because we check that the corresponding functions can run script later in + // the checker code. + AstMatcher->addMatcher( + expr( + anyOf( + // We want to match a method call expression, + cxxMemberCallExpr( + // which optionally has an invalid arg, + OptionalInvalidExplicitArg, + // or which optionally has an invalid this argument, + anyOf(on(InvalidArg), anything()), expr().bind("callExpr")), + // or a regular call expression, + callExpr( + // which optionally has an invalid arg. + OptionalInvalidExplicitArg, expr().bind("callExpr")), + // or a construct expression, + cxxConstructExpr( + // which optionally has an invalid arg. + OptionalInvalidExplicitArg, expr().bind("constructExpr"))), + + anyOf( + // We want to match the parent function. + forFunction(functionDecl().bind("nonCanRunScriptParentFunction")), + + // ... optionally. + anything())), + this); +} + +void CanRunScriptChecker::onStartOfTranslationUnit() { + IsFuncSetBuilt = false; + CanRunScriptFuncs.clear(); +} + +namespace { +/// This class is a callback used internally to match function declarations with +/// the MOZ_CAN_RUN_SCRIPT annotation, adding these functions to the +/// can-run-script function set and making sure the functions they override (if +/// any) also have the annotation. +class FuncSetCallback : public MatchFinder::MatchCallback { +public: + FuncSetCallback(CanRunScriptChecker &Checker, + std::unordered_set<const FunctionDecl *> &FuncSet) + : CanRunScriptFuncs(FuncSet), Checker(Checker) {} + + void run(const MatchFinder::MatchResult &Result) override; + +private: + /// This method checks the methods overriden by the given parameter. + void checkOverriddenMethods(const CXXMethodDecl *Method); + + std::unordered_set<const FunctionDecl *> &CanRunScriptFuncs; + CanRunScriptChecker &Checker; +}; + +void FuncSetCallback::run(const MatchFinder::MatchResult &Result) { + const FunctionDecl *Func; + if (auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) { + Func = Lambda->getCallOperator(); + if (!Func || !hasCustomAttribute<moz_can_run_script>(Func)) + return; + } else { + Func = Result.Nodes.getNodeAs<FunctionDecl>("canRunScriptFunction"); + + const char *ErrorAttrInDefinition = + "MOZ_CAN_RUN_SCRIPT must be put in front " + "of the declaration, not the definition"; + const char *NoteAttrInDefinition = "The first declaration exists here"; + if (!Func->isFirstDecl() && + !hasCustomAttribute<moz_can_run_script_for_definition>(Func)) { + const FunctionDecl *FirstDecl = Func->getFirstDecl(); + if (!hasCustomAttribute<moz_can_run_script>(FirstDecl)) { + Checker.diag(Func->getLocation(), ErrorAttrInDefinition, + DiagnosticIDs::Error); + Checker.diag(FirstDecl->getLocation(), NoteAttrInDefinition, + DiagnosticIDs::Note); + } + } + } + + CanRunScriptFuncs.insert(Func); + + // If this is a method, we check the methods it overrides. + if (auto *Method = dyn_cast<CXXMethodDecl>(Func)) { + checkOverriddenMethods(Method); + } +} + +void FuncSetCallback::checkOverriddenMethods(const CXXMethodDecl *Method) { + for (auto OverriddenMethod : Method->overridden_methods()) { + if (!hasCustomAttribute<moz_can_run_script>(OverriddenMethod)) { + const char *ErrorNonCanRunScriptOverridden = + "functions marked as MOZ_CAN_RUN_SCRIPT cannot override functions " + "that are not marked MOZ_CAN_RUN_SCRIPT"; + const char *NoteNonCanRunScriptOverridden = + "overridden function declared here"; + + Checker.diag(Method->getLocation(), ErrorNonCanRunScriptOverridden, + DiagnosticIDs::Error); + Checker.diag(OverriddenMethod->getLocation(), + NoteNonCanRunScriptOverridden, DiagnosticIDs::Note); + } + } +} +} // namespace + +void CanRunScriptChecker::buildFuncSet(ASTContext *Context) { + // We create a match finder. + MatchFinder Finder; + // We create the callback which will be called when we find a function with + // a MOZ_CAN_RUN_SCRIPT annotation. + FuncSetCallback Callback(*this, CanRunScriptFuncs); + // We add the matcher to the finder, linking it to our callback. + Finder.addMatcher( + functionDecl(hasCanRunScriptAnnotation()).bind("canRunScriptFunction"), + &Callback); + Finder.addMatcher(lambdaExpr().bind("lambda"), &Callback); + // We start the analysis, given the ASTContext our main checker is in. + Finder.matchAST(*Context); +} + +void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) { + + // If the set of functions which can run script is not yet built, then build + // it. + if (!IsFuncSetBuilt) { + buildFuncSet(Result.Context); + IsFuncSetBuilt = true; + } + + const char *ErrorInvalidArg = + "arguments must all be strong refs or caller's parameters when calling a " + "function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object " + "argument). '%0' is neither."; + + const char *ErrorNonCanRunScriptParent = + "functions marked as MOZ_CAN_RUN_SCRIPT can only be called from " + "functions also marked as MOZ_CAN_RUN_SCRIPT"; + const char *NoteNonCanRunScriptParent = "caller function declared here"; + + const Expr *InvalidArg; + if (const CXXDefaultArgExpr *defaultArg = + Result.Nodes.getNodeAs<CXXDefaultArgExpr>("invalidArg")) { + InvalidArg = defaultArg->getExpr(); + } else { + InvalidArg = Result.Nodes.getNodeAs<Expr>("invalidArg"); + } + + const CallExpr *Call = Result.Nodes.getNodeAs<CallExpr>("callExpr"); + // If we don't find the FunctionDecl linked to this call or if it's not marked + // as can-run-script, consider that we didn't find a match. + if (Call && (!Call->getDirectCallee() || + !CanRunScriptFuncs.count(Call->getDirectCallee()))) { + Call = nullptr; + } + + const CXXConstructExpr *Construct = + Result.Nodes.getNodeAs<CXXConstructExpr>("constructExpr"); + + // If we don't find the CXXConstructorDecl linked to this construct expression + // or if it's not marked as can-run-script, consider that we didn't find a + // match. + if (Construct && (!Construct->getConstructor() || + !CanRunScriptFuncs.count(Construct->getConstructor()))) { + Construct = nullptr; + } + + const FunctionDecl *ParentFunction = + Result.Nodes.getNodeAs<FunctionDecl>("nonCanRunScriptParentFunction"); + // If the parent function can run script, consider that we didn't find a match + // because we only care about parent functions which can't run script. + // + // In addition, If the parent function is annotated as a + // CAN_RUN_SCRIPT_BOUNDARY, we don't want to complain about it calling a + // CAN_RUN_SCRIPT function. This is a mechanism to opt out of the infectious + // nature of CAN_RUN_SCRIPT which is necessary in some tricky code like + // Bindings. + if (ParentFunction && + (CanRunScriptFuncs.count(ParentFunction) || + hasCustomAttribute<moz_can_run_script_boundary>(ParentFunction))) { + ParentFunction = nullptr; + } + + // Get the call range from either the CallExpr or the ConstructExpr. + SourceRange CallRange; + if (Call) { + CallRange = Call->getSourceRange(); + } else if (Construct) { + CallRange = Construct->getSourceRange(); + } else { + // If we have neither a Call nor a Construct, we have nothing do to here. + return; + } + + // If we have an invalid argument in the call, we emit the diagnostic to + // signal it. + if (InvalidArg) { + const StringRef invalidArgText = Lexer::getSourceText( + CharSourceRange::getTokenRange(InvalidArg->getSourceRange()), + Result.Context->getSourceManager(), Result.Context->getLangOpts()); + diag(InvalidArg->getExprLoc(), ErrorInvalidArg, DiagnosticIDs::Error) + << InvalidArg->getSourceRange() << invalidArgText; + } + + // If the parent function is not marked as MOZ_CAN_RUN_SCRIPT, we emit an + // error and a not indicating it. + if (ParentFunction) { + assert(!hasCustomAttribute<moz_can_run_script>(ParentFunction) && + "Matcher missed something"); + + diag(CallRange.getBegin(), ErrorNonCanRunScriptParent, DiagnosticIDs::Error) + << CallRange; + + diag(ParentFunction->getCanonicalDecl()->getLocation(), + NoteNonCanRunScriptParent, DiagnosticIDs::Note); + } +} diff --git a/build/clang-plugin/CanRunScriptChecker.h b/build/clang-plugin/CanRunScriptChecker.h new file mode 100644 index 0000000000..4516609999 --- /dev/null +++ b/build/clang-plugin/CanRunScriptChecker.h @@ -0,0 +1,31 @@ +/* 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/. */ + +#ifndef CanRunScriptChecker_h__ +#define CanRunScriptChecker_h__ + +#include "plugin.h" +#include <unordered_set> + +class CanRunScriptChecker : public BaseCheck { +public: + CanRunScriptChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; + + // Simply initialize the can-run-script function set at the beginning of each + // translation unit. + void onStartOfTranslationUnit() override; + +private: + /// Runs the inner matcher on the AST to find all the can-run-script + /// functions using custom rules (not only the annotation). + void buildFuncSet(ASTContext *Context); + + bool IsFuncSetBuilt; + std::unordered_set<const FunctionDecl *> CanRunScriptFuncs; +}; + +#endif diff --git a/build/clang-plugin/Checks.inc b/build/clang-plugin/Checks.inc new file mode 100644 index 0000000000..97c77547ac --- /dev/null +++ b/build/clang-plugin/Checks.inc @@ -0,0 +1,44 @@ +/* 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/. */ + +// The list of checker classes that are compatible with clang-tidy. + +CHECK(ArithmeticArgChecker, "arithmetic-argument") +CHECK(AssertAssignmentChecker, "assignment-in-assert") +CHECK(CanRunScriptChecker, "can-run-script") +CHECK(DanglingOnTemporaryChecker, "dangling-on-temporary") +CHECK(ExplicitImplicitChecker, "implicit-constructor") +CHECK(ExplicitOperatorBoolChecker, "explicit-operator-bool") +CHECK(JSHandleRootedTypedefChecker, "js-handle-rooted-typedef") +CHECK(KungFuDeathGripChecker, "kungfu-death-grip") +CHECK(KnownLiveChecker, "known-live") +#ifdef TARGET_IS_WINDOWS +CHECK(LoadLibraryUsageChecker, "load-library-usage") +CHECK(FopenUsageChecker, "fopen-usage") +#endif +CHECK(MustOverrideChecker, "must-override") +CHECK(MustReturnFromCallerChecker, "must-return-from-caller") +CHECK(NaNExprChecker, "nan-expr") +CHECK(NoPrincipalGetURI, "no-principal-geturi") +CHECK(NeedsNoVTableTypeChecker, "needs-no-vtable-type") +CHECK(NoAddRefReleaseOnReturnChecker, "no-addref-release-on-return") +CHECK(NoAutoTypeChecker, "no-auto-type") +CHECK(NoDuplicateRefCntMemberChecker, "no-duplicate-refcnt-member") +CHECK(NoExplicitMoveConstructorChecker, "no-explicit-move-constructor") +CHECK(NoNewThreadsChecker, "no-new-threads") +CHECK(NonMemMovableMemberChecker, "non-memmovable-member") +CHECK(NonMemMovableTemplateArgChecker, "non-memmovable-template-arg") +CHECK(NoUsingNamespaceMozillaJavaChecker, "no-using-namespace-mozilla-java") +CHECK(NonParamInsideFunctionDeclChecker, "non-memmovable-template-arg") +CHECK(NonTrivialTypeInFfiChecker, "non-trivial-type-in-ffi-boundary") +CHECK(OverrideBaseCallChecker, "override-base-call") +CHECK(OverrideBaseCallUsageChecker, "override-base-call-usage") +CHECK(ParamTraitsEnumChecker, "paramtraits-enum") +CHECK(RefCountedCopyConstructorChecker, "refcounted-copy-constructor") +CHECK(RefCountedInsideLambdaChecker, "refcounted-inside-lambda") +CHECK(RefCountedThisInsideConstructorChecker, "refcount-within-constructor") +CHECK(ScopeChecker, "scope") +CHECK(SprintfLiteralChecker, "sprintf-literal") +CHECK(TrivialCtorDtorChecker, "trivial-constructor-destructor") +CHECK(TrivialDtorChecker, "trivial-destructor") diff --git a/build/clang-plugin/ChecksIncludes.inc b/build/clang-plugin/ChecksIncludes.inc new file mode 100644 index 0000000000..d029d6ea30 --- /dev/null +++ b/build/clang-plugin/ChecksIncludes.inc @@ -0,0 +1,45 @@ +/* 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/. */ + +// The list of #include directives necessary for the checker classes that +// are compatible with clang-tidy. + +#include "ArithmeticArgChecker.h" +#include "AssertAssignmentChecker.h" +#include "CanRunScriptChecker.h" +#include "DanglingOnTemporaryChecker.h" +#include "ExplicitImplicitChecker.h" +#include "ExplicitOperatorBoolChecker.h" +#ifdef TARGET_IS_WINDOWS +#include "LoadLibraryUsageChecker.h" +#include "FopenUsageChecker.h" +#endif +#include "JSHandleRootedTypedefChecker.h" +#include "KungFuDeathGripChecker.h" +#include "KnownLiveChecker.h" +#include "MustOverrideChecker.h" +#include "MustReturnFromCallerChecker.h" +#include "NaNExprChecker.h" +#include "NoPrincipalGetURI.h" +#include "NeedsNoVTableTypeChecker.h" +#include "NoAddRefReleaseOnReturnChecker.h" +#include "NoAutoTypeChecker.h" +#include "NoDuplicateRefCntMemberChecker.h" +#include "NoExplicitMoveConstructorChecker.h" +#include "NoNewThreadsChecker.h" +#include "NonMemMovableMemberChecker.h" +#include "NonMemMovableTemplateArgChecker.h" +#include "NonParamInsideFunctionDeclChecker.h" +#include "NonTrivialTypeInFfiChecker.h" +#include "NoUsingNamespaceMozillaJavaChecker.h" +#include "OverrideBaseCallChecker.h" +#include "OverrideBaseCallUsageChecker.h" +#include "ParamTraitsEnumChecker.h" +#include "RefCountedCopyConstructorChecker.h" +#include "RefCountedInsideLambdaChecker.h" +#include "RefCountedThisInsideConstructorChecker.h" +#include "ScopeChecker.h" +#include "SprintfLiteralChecker.h" +#include "TrivialCtorDtorChecker.h" +#include "TrivialDtorChecker.h" diff --git a/build/clang-plugin/CustomAttributes.cpp b/build/clang-plugin/CustomAttributes.cpp new file mode 100644 index 0000000000..d143f5856d --- /dev/null +++ b/build/clang-plugin/CustomAttributes.cpp @@ -0,0 +1,126 @@ +/* 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 "CustomAttributes.h" +#include "plugin.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include <algorithm> + +/* Having annotations in the AST unexpectedly impacts codegen. + * Ideally, we'd avoid having annotations at all, by using an API such as + * the one from https://reviews.llvm.org/D31338, and storing the attributes + * data separately from the AST on our own. Unfortunately, there is no such + * API currently in clang, so we must do without. + * We can do something similar, though, where we go through the AST before + * running the checks, create a mapping of AST nodes to attributes, and + * remove the attributes/annotations from the AST nodes. + * Not all declarations can be reached from the decl() AST matcher, though, + * so we do our best effort (getting the other declarations we look at in + * checks). We emit a warning when checks look at a note that still has + * annotations attached (aka, hasn't been seen during our first pass), + * so that those don't go unnoticed. (-Werror should then take care of + * making that an error) + */ + +using namespace clang; +using namespace llvm; + +static DenseMap<const Decl *, CustomAttributesSet> AttributesCache; + +static CustomAttributesSet CacheAttributes(const Decl *D) { + CustomAttributesSet attrs = {}; + for (auto Attr : D->specific_attrs<AnnotateAttr>()) { + auto annotation = Attr->getAnnotation(); +#define ATTR(a) \ + if (annotation == #a) { \ + attrs.has_##a = true; \ + } else +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR + {} + } + const_cast<Decl *>(D)->dropAttr<AnnotateAttr>(); + AttributesCache.insert(std::make_pair(D, attrs)); + return attrs; +} + +#ifndef CLANG_TIDY +static void Report(const Decl *D, const char *message) { + ASTContext &Context = D->getASTContext(); + DiagnosticsEngine &Diag = Context.getDiagnostics(); + unsigned ID = + Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Warning, message); + Diag.Report(D->getBeginLoc(), ID); +} + +class CustomAttributesMatcher + : public ast_matchers::MatchFinder::MatchCallback { +public: + void run(const ast_matchers::MatchFinder::MatchResult &Result) final { + if (auto D = Result.Nodes.getNodeAs<Decl>("decl")) { + CacheAttributes(D); + } else if (auto L = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) { + CacheAttributes(L->getCallOperator()); + CacheAttributes(L->getLambdaClass()); + } + } +}; + +class CustomAttributesAction : public PluginASTAction { +public: + ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, + StringRef FileName) override { + auto &Context = CI.getASTContext(); + auto AstMatcher = new (Context.Allocate<MatchFinder>()) MatchFinder(); + auto Matcher = new (Context.Allocate<CustomAttributesMatcher>()) + CustomAttributesMatcher(); + AstMatcher->addMatcher(decl().bind("decl"), Matcher); + AstMatcher->addMatcher(lambdaExpr().bind("lambda"), Matcher); + return AstMatcher->newASTConsumer(); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector<std::string> &Args) override { + return true; + } + + ActionType getActionType() override { return AddBeforeMainAction; } +}; + +static FrontendPluginRegistry::Add<CustomAttributesAction> + X("moz-custom-attributes", "prepare custom attributes for moz-check"); +#endif + +CustomAttributesSet GetAttributes(const Decl *D) { + CustomAttributesSet attrs = {}; + if (D->hasAttr<AnnotateAttr>()) { +// If we are not in clang-tidy env push warnings, most likely we are in the +// build environment and this should have been done in AstMatcher - +// CustomAttributesMatcher +#ifndef CLANG_TIDY + Report(D, "Declaration has unhandled annotations."); +#endif + attrs = CacheAttributes(D); + } else { + auto attributes = AttributesCache.find(D); + if (attributes != AttributesCache.end()) { + attrs = attributes->second; + } + } + return attrs; +} + +bool hasCustomAttribute(const clang::Decl *D, CustomAttributes A) { + CustomAttributesSet attrs = GetAttributes(D); + switch (A) { +#define ATTR(a) \ + case a: \ + return attrs.has_##a; +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR + } + return false; +} diff --git a/build/clang-plugin/CustomAttributes.h b/build/clang-plugin/CustomAttributes.h new file mode 100644 index 0000000000..04c95b7184 --- /dev/null +++ b/build/clang-plugin/CustomAttributes.h @@ -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/. */ + +#ifndef CustomAttributes_h__ +#define CustomAttributes_h__ + +#include "clang/AST/DeclBase.h" +#include "llvm/ADT/StringRef.h" + +enum CustomAttributes { +#define ATTR(a) a, +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR +}; + +struct CustomAttributesSet { +#define ATTR(a) bool has_##a : 1; +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR +}; + +template <CustomAttributes A> bool hasCustomAttribute(const clang::Decl *D) { + return false; +} + +extern CustomAttributesSet GetAttributes(const clang::Decl *D); + +#define ATTR(name) \ + template <> inline bool hasCustomAttribute<name>(const clang::Decl *D) { \ + return GetAttributes(D).has_##name; \ + } +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR + +extern bool hasCustomAttribute(const clang::Decl *D, CustomAttributes A); + +#endif /* CustomAttributes_h__ */ diff --git a/build/clang-plugin/CustomAttributes.inc b/build/clang-plugin/CustomAttributes.inc new file mode 100644 index 0000000000..883676e9c5 --- /dev/null +++ b/build/clang-plugin/CustomAttributes.inc @@ -0,0 +1,31 @@ +ATTR(moz_allow_temporary) +ATTR(moz_can_run_script) +ATTR(moz_can_run_script_for_definition) +ATTR(moz_can_run_script_boundary) +ATTR(moz_global_class) +ATTR(moz_heap_allocator) +ATTR(moz_heap_class) +ATTR(moz_implicit) +ATTR(moz_inherit_type_annotations_from_template_args) +ATTR(moz_is_smartptr_to_refcounted) +ATTR(moz_known_live) +ATTR(moz_may_call_after_must_return) +ATTR(moz_must_override) +ATTR(moz_must_return_from_caller_if_this_is_arg) +ATTR(moz_needs_memmovable_members) +ATTR(moz_needs_memmovable_type) +ATTR(moz_needs_no_vtable_type) +ATTR(moz_no_addref_release_on_return) +ATTR(moz_no_arith_expr_in_arg) +ATTR(moz_no_dangling_on_temporaries) +ATTR(moz_non_autoable) +ATTR(moz_non_memmovable) +ATTR(moz_non_param) +ATTR(moz_non_temporary_class) +ATTR(moz_nonheap_class) +ATTR(moz_required_base_method) +ATTR(moz_stack_class) +ATTR(moz_static_local_class) +ATTR(moz_temporary_class) +ATTR(moz_trivial_ctor_dtor) +ATTR(moz_trivial_dtor) diff --git a/build/clang-plugin/CustomMatchers.h b/build/clang-plugin/CustomMatchers.h new file mode 100644 index 0000000000..97caf4d59c --- /dev/null +++ b/build/clang-plugin/CustomMatchers.h @@ -0,0 +1,494 @@ +/* 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/. */ + +#ifndef CustomMatchers_h__ +#define CustomMatchers_h__ + +#include "MemMoveAnnotation.h" +#include "Utils.h" + +#if CLANG_VERSION_FULL >= 1300 +// Starting with clang-13 Expr::isRValue has been renamed to Expr::isPRValue +#define isRValue isPRValue +#endif + +namespace clang { +namespace ast_matchers { + +/// This matcher will match any function declaration that is declared as a heap +/// allocator. +AST_MATCHER(FunctionDecl, heapAllocator) { + return hasCustomAttribute<moz_heap_allocator>(&Node); +} + +/// This matcher will match any declaration that is marked as not accepting +/// arithmetic expressions in its arguments. +AST_MATCHER(Decl, noArithmeticExprInArgs) { + return hasCustomAttribute<moz_no_arith_expr_in_arg>(&Node); +} + +/// This matcher will match any C++ class that is marked as having a trivial +/// constructor and destructor. +AST_MATCHER(CXXRecordDecl, hasTrivialCtorDtor) { + return hasCustomAttribute<moz_trivial_ctor_dtor>(&Node); +} + +/// This matcher will match any C++ class that is marked as having a trivial +/// destructor. +AST_MATCHER(CXXRecordDecl, hasTrivialDtor) { + return hasCustomAttribute<moz_trivial_dtor>(&Node); +} + +AST_MATCHER(CXXConstructExpr, allowsTemporary) { + return hasCustomAttribute<moz_allow_temporary>(Node.getConstructor()); +} + +/// This matcher will match lvalue-ref-qualified methods. +AST_MATCHER(CXXMethodDecl, isLValueRefQualified) { + return Node.getRefQualifier() == RQ_LValue; +} + +/// This matcher will match rvalue-ref-qualified methods. +AST_MATCHER(CXXMethodDecl, isRValueRefQualified) { + return Node.getRefQualifier() == RQ_RValue; +} + +AST_POLYMORPHIC_MATCHER(isFirstParty, + AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt)) { + return !inThirdPartyPath(&Node, &Finder->getASTContext()) && + !ASTIsInSystemHeader(Finder->getASTContext(), Node); +} + +AST_MATCHER(DeclaratorDecl, isNotSpiderMonkey) { + // Detect SpiderMonkey path. Not as strict as isFirstParty, but this is + // expected to disappear soon by getting a common style guide between DOM and + // SpiderMonkey. + std::string Path = Node.getBeginLoc().printToString( + Finder->getASTContext().getSourceManager()); + return Path.find("js") == std::string::npos && + Path.find("xpc") == std::string::npos && + Path.find("XPC") == std::string::npos; +} + +/// This matcher will match temporary expressions. +/// We need this matcher for compatibility with clang 3.* (clang 4 and above +/// insert a MaterializeTemporaryExpr everywhere). +AST_MATCHER(Expr, isTemporary) { + return Node.isRValue() || Node.isXValue() || + isa<MaterializeTemporaryExpr>(&Node); +} + +/// This matcher will match any method declaration that is marked as returning +/// a pointer deleted by the destructor of the class. +AST_MATCHER(CXXMethodDecl, noDanglingOnTemporaries) { + return hasCustomAttribute<moz_no_dangling_on_temporaries>(&Node); +} + +/// This matcher will match any function declaration that is marked to prohibit +/// calling AddRef or Release on its return value. +AST_MATCHER(FunctionDecl, hasNoAddRefReleaseOnReturnAttr) { + return hasCustomAttribute<moz_no_addref_release_on_return>(&Node); +} + +/// This matcher will match any function declaration that is marked as being +/// allowed to run script. +AST_MATCHER(FunctionDecl, hasCanRunScriptAnnotation) { + return hasCustomAttribute<moz_can_run_script>(&Node); +} + +/// This matcher will match all arithmetic binary operators. +AST_MATCHER(BinaryOperator, binaryArithmeticOperator) { + BinaryOperatorKind OpCode = Node.getOpcode(); + return OpCode == BO_Mul || OpCode == BO_Div || OpCode == BO_Rem || + OpCode == BO_Add || OpCode == BO_Sub || OpCode == BO_Shl || + OpCode == BO_Shr || OpCode == BO_And || OpCode == BO_Xor || + OpCode == BO_Or || OpCode == BO_MulAssign || OpCode == BO_DivAssign || + OpCode == BO_RemAssign || OpCode == BO_AddAssign || + OpCode == BO_SubAssign || OpCode == BO_ShlAssign || + OpCode == BO_ShrAssign || OpCode == BO_AndAssign || + OpCode == BO_XorAssign || OpCode == BO_OrAssign; +} + +/// This matcher will match all arithmetic unary operators. +AST_MATCHER(UnaryOperator, unaryArithmeticOperator) { + UnaryOperatorKind OpCode = Node.getOpcode(); + return OpCode == UO_PostInc || OpCode == UO_PostDec || OpCode == UO_PreInc || + OpCode == UO_PreDec || OpCode == UO_Plus || OpCode == UO_Minus || + OpCode == UO_Not; +} + +/// This matcher will match the unary dereference operator +AST_MATCHER(UnaryOperator, unaryDereferenceOperator) { + UnaryOperatorKind OpCode = Node.getOpcode(); + return OpCode == UO_Deref; +} + +/// This matcher will match == and != binary operators. +AST_MATCHER(BinaryOperator, binaryEqualityOperator) { + BinaryOperatorKind OpCode = Node.getOpcode(); + return OpCode == BO_EQ || OpCode == BO_NE; +} + +/// This matcher will match comma operator. +AST_MATCHER(BinaryOperator, binaryCommaOperator) { + BinaryOperatorKind OpCode = Node.getOpcode(); + return OpCode == BO_Comma; +} + +/// This matcher will match floating point types. +AST_MATCHER(QualType, isFloat) { return Node->isRealFloatingType(); } + +/// This matcher will match locations in system headers. This is adopted from +/// isExpansionInSystemHeader in newer clangs, but modified in order to work +/// with old clangs that we use on infra. +AST_POLYMORPHIC_MATCHER(isInSystemHeader, + AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt)) { + return ASTIsInSystemHeader(Finder->getASTContext(), Node); +} + +/// This matcher will match a file "gtest-port.h". The file contains +/// known fopen usages that are OK. +AST_MATCHER(CallExpr, isInWhitelistForFopenUsage) { + static const char Whitelist[] = "gtest-port.h"; + SourceLocation Loc = Node.getBeginLoc(); + StringRef FileName = + getFilename(Finder->getASTContext().getSourceManager(), Loc); + + return llvm::sys::path::rbegin(FileName)->equals(Whitelist); +} + +/// This matcher will match a list of files. These files contain +/// known NaN-testing expressions which we would like to whitelist. +AST_MATCHER(BinaryOperator, isInWhitelistForNaNExpr) { + const char *whitelist[] = {"SkScalar.h", "json_writer.cpp", "State.cpp"}; + + SourceLocation Loc = Node.getOperatorLoc(); + StringRef FileName = + getFilename(Finder->getASTContext().getSourceManager(), Loc); + for (auto itr = std::begin(whitelist); itr != std::end(whitelist); itr++) { + if (llvm::sys::path::rbegin(FileName)->equals(*itr)) { + return true; + } + } + + return false; +} + +AST_MATCHER(CallExpr, isInWhiteListForPrincipalGetUri) { + const auto Whitelist = {"nsIPrincipal.h", "BasePrincipal.cpp", + "ContentPrincipal.cpp"}; + SourceLocation Loc = Node.getBeginLoc(); + StringRef Filename = + getFilename(Finder->getASTContext().getSourceManager(), Loc); + + for (auto Exclusion : Whitelist) { + if (Filename.find(Exclusion) != std::string::npos) { + return true; + } + } + return false; +} + +/// This matcher will match a list of files which contain NS_NewNamedThread +/// code or names of existing threads that we would like to ignore. +AST_MATCHER(CallExpr, isInAllowlistForThreads) { + + // Get the source location of the call. + SourceLocation Loc = Node.getRParenLoc(); + StringRef FileName = + getFilename(Finder->getASTContext().getSourceManager(), Loc); + + const auto rbegin = [](StringRef s) { return llvm::sys::path::rbegin(s); }; + const auto rend = [](StringRef s) { return llvm::sys::path::rend(s); }; + + // Files in the allowlist are (definitionally) explicitly permitted to create + // new threads. + for (auto thread_file : allow_thread_files) { + // All the provided path-elements must match. + const bool match = [&] { + auto it1 = rbegin(FileName), it2 = rbegin(thread_file), + end1 = rend(FileName), end2 = rend(thread_file); + for (; it2 != end2; ++it1, ++it2) { + if (it1 == end1 || !it1->equals(*it2)) { + return false; + } + } + return true; + }(); + if (match) { + return true; + } + } + + // Check the first arg (the name of the thread). + const StringLiteral *nameArg = + dyn_cast<StringLiteral>(Node.getArg(0)->IgnoreImplicit()); + if (nameArg) { + const StringRef name = nameArg->getString(); + for (auto thread_name : allow_thread_names) { + if (name.equals(thread_name)) { + return true; + } + } + } + + return false; +} + +/// This matcher will match all accesses to AddRef or Release methods. +AST_MATCHER(MemberExpr, isAddRefOrRelease) { + ValueDecl *Member = Node.getMemberDecl(); + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member); + if (Method) { + const auto &Name = getNameChecked(Method); + return Name == "AddRef" || Name == "Release"; + } + return false; +} + +/// This matcher will select classes which are refcounted AND have an mRefCnt +/// member. +AST_MATCHER(CXXRecordDecl, hasRefCntMember) { + return isClassRefCounted(&Node) && getClassRefCntMember(&Node); +} + +/// This matcher will select classes which are refcounted. +AST_MATCHER(CXXRecordDecl, isRefCounted) { return isClassRefCounted(&Node); } + +AST_MATCHER(QualType, hasVTable) { return typeHasVTable(Node); } + +AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) { + return hasCustomAttribute<moz_needs_no_vtable_type>(&Node); +} + +/// This matcher will select classes which are non-memmovable +AST_MATCHER(QualType, isNonMemMovable) { + return NonMemMovable.hasEffectiveAnnotation(Node); +} + +/// This matcher will select classes which require a memmovable template arg +AST_MATCHER(CXXRecordDecl, needsMemMovableTemplateArg) { + return hasCustomAttribute<moz_needs_memmovable_type>(&Node); +} + +/// This matcher will select classes which require all members to be memmovable +AST_MATCHER(CXXRecordDecl, needsMemMovableMembers) { + return hasCustomAttribute<moz_needs_memmovable_members>(&Node); +} + +AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) { + const CXXConstructorDecl *Declaration = Node.getCanonicalDecl(); + return + // Skip constructors in system headers + !ASTIsInSystemHeader(Declaration->getASTContext(), *Declaration) && + // Skip ignored namespaces and paths + !isInIgnoredNamespaceForImplicitCtor(Declaration) && + !inThirdPartyPath(Declaration) && + // We only want Converting constructors + Declaration->isConvertingConstructor(false) && + // We don't want copy of move constructors, as those are allowed to be + // implicit + !Declaration->isCopyOrMoveConstructor() && + // We don't want inheriting constructors, since using declarations can't + // have attributes + !Declaration->isInheritingConstructor() && + // We don't want deleted constructors. + !Declaration->isDeleted(); +} + +AST_MATCHER_P(Expr, ignoreTrivials, internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*IgnoreTrivials(&Node), Finder, Builder); +} + +// Takes two matchers: the first one is a condition; the second is a matcher to +// be applied once we are done unwrapping trivials. While the condition does +// not match and we're looking at a trivial, will keep unwrapping the trivial +// and trying again. Once the condition matches, we will go ahead and unwrap all +// trivials and apply the inner matcher to the result. +// +// The expected use here is if we want to condition a match on some typecheck +// but apply the match to only non-trivials, because there are trivials (e.g. +// casts) that can change types. +AST_MATCHER_P2(Expr, ignoreTrivialsConditional, internal::Matcher<Expr>, + Condition, internal::Matcher<Expr>, InnerMatcher) { + const Expr *node = &Node; + while (true) { + if (Condition.matches(*node, Finder, Builder)) { + return InnerMatcher.matches(*IgnoreTrivials(node), Finder, Builder); + } + const Expr *newNode = MaybeSkipOneTrivial(node); + if (newNode == node) { + return false; + } + node = newNode; + } +} + +// We can't call this "isImplicit" since it clashes with an existing matcher in +// clang. +AST_MATCHER(CXXConstructorDecl, isMarkedImplicit) { + return hasCustomAttribute<moz_implicit>(&Node); +} + +AST_MATCHER(CXXRecordDecl, isConcreteClass) { return !Node.isAbstract(); } + +AST_MATCHER(QualType, autoNonAutoableType) { + if (const AutoType *T = Node->getContainedAutoType()) { + if (const CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) { + return hasCustomAttribute<moz_non_autoable>(Rec); + } + } + return false; +} + +AST_MATCHER(CXXConstructorDecl, isExplicitMoveConstructor) { + return Node.isExplicit() && Node.isMoveConstructor(); +} + +AST_MATCHER(CXXConstructorDecl, isCompilerProvidedCopyConstructor) { + return !Node.isUserProvided() && Node.isCopyConstructor(); +} + +AST_MATCHER(CallExpr, isAssertAssignmentTestFunc) { + static const std::string AssertName = "MOZ_AssertAssignmentTest"; + const FunctionDecl *Method = Node.getDirectCallee(); + + return Method && Method->getDeclName().isIdentifier() && + Method->getName() == AssertName; +} + +AST_MATCHER(CallExpr, isSnprintfLikeFunc) { + static const std::string Snprintf = "snprintf"; + static const std::string Vsnprintf = "vsnprintf"; + const FunctionDecl *Func = Node.getDirectCallee(); + + if (!Func || isa<CXXMethodDecl>(Func)) { + return false; + } + + StringRef Name = getNameChecked(Func); + if (Name != Snprintf && Name != Vsnprintf) { + return false; + } + + return !inThirdPartyPath(Node.getBeginLoc(), + Finder->getASTContext().getSourceManager()) && + !isIgnoredPathForSprintfLiteral( + &Node, Finder->getASTContext().getSourceManager()); +} + +AST_MATCHER(CXXRecordDecl, isLambdaDecl) { return Node.isLambda(); } + +AST_MATCHER(QualType, isRefPtr) { return typeIsRefPtr(Node); } + +AST_MATCHER(QualType, isSmartPtrToRefCounted) { + auto *D = getNonTemplateSpecializedCXXRecordDecl(Node); + if (!D) { + return false; + } + + D = D->getCanonicalDecl(); + + return D && hasCustomAttribute<moz_is_smartptr_to_refcounted>(D); +} + +AST_MATCHER(ClassTemplateSpecializationDecl, isSmartPtrToRefCountedDecl) { + auto *D = dyn_cast_or_null<CXXRecordDecl>( + Node.getSpecializedTemplate()->getTemplatedDecl()); + if (!D) { + return false; + } + + D = D->getCanonicalDecl(); + + return D && hasCustomAttribute<moz_is_smartptr_to_refcounted>(D); +} + +AST_MATCHER(CXXRecordDecl, hasBaseClasses) { + const CXXRecordDecl *Decl = Node.getCanonicalDecl(); + + // Must have definition and should inherit other classes + return Decl && Decl->hasDefinition() && Decl->getNumBases(); +} + +AST_MATCHER(CXXMethodDecl, isRequiredBaseMethod) { + const CXXMethodDecl *Decl = Node.getCanonicalDecl(); + return Decl && hasCustomAttribute<moz_required_base_method>(Decl); +} + +AST_MATCHER(CXXMethodDecl, isNonVirtual) { + const CXXMethodDecl *Decl = Node.getCanonicalDecl(); + return Decl && !Decl->isVirtual(); +} + +AST_MATCHER(FunctionDecl, isMozMustReturnFromCaller) { + const FunctionDecl *Decl = Node.getCanonicalDecl(); + return Decl && + hasCustomAttribute<moz_must_return_from_caller_if_this_is_arg>(Decl); +} + +/// This matcher will select default args which have nullptr as the value. +AST_MATCHER(CXXDefaultArgExpr, isNullDefaultArg) { + const Expr *Expr = Node.getExpr(); + return Expr && Expr->isNullPointerConstant(Finder->getASTContext(), + Expr::NPC_NeverValueDependent); +} + +AST_MATCHER(UsingDirectiveDecl, isUsingNamespaceMozillaJava) { + const NamespaceDecl *Namespace = Node.getNominatedNamespace(); + const std::string &FQName = Namespace->getQualifiedNameAsString(); + + static const char NAMESPACE[] = "mozilla::java"; + static const char PREFIX[] = "mozilla::java::"; + + // We match both the `mozilla::java` namespace itself as well as any other + // namespaces contained within the `mozilla::java` namespace. + return !FQName.compare(NAMESPACE) || + !FQName.compare(0, sizeof(PREFIX) - 1, PREFIX); +} + +AST_MATCHER(MemberExpr, hasKnownLiveAnnotation) { + ValueDecl *Member = Node.getMemberDecl(); + FieldDecl *Field = dyn_cast<FieldDecl>(Member); + return Field && hasCustomAttribute<moz_known_live>(Field); +} + +#define GENERATE_JSTYPEDEF_PAIR(templateName) \ + {templateName "Function", templateName "<JSFunction*>"}, \ + {templateName "Id", templateName "<JS::PropertyKey>"}, \ + {templateName "Object", templateName "<JSObject*>"}, \ + {templateName "Script", templateName "<JSScript*>"}, \ + {templateName "String", templateName "<JSString*>"}, \ + {templateName "Symbol", templateName "<JS::Symbol*>"}, \ + {templateName "BigInt", templateName "<JS::BigInt*>"}, \ + {templateName "Value", templateName "<JS::Value>"}, \ + {templateName "ValueVector", templateName "Vector<JS::Value>"}, \ + {templateName "ObjectVector", templateName "Vector<JSObject*>"}, { \ + templateName "IdVector", templateName "Vector<JS::PropertyKey>" \ + } + +static const char *const JSHandleRootedTypedefMap[][2] = { + GENERATE_JSTYPEDEF_PAIR("JS::Handle"), + GENERATE_JSTYPEDEF_PAIR("JS::MutableHandle"), + GENERATE_JSTYPEDEF_PAIR("JS::Rooted"), + // Technically there is no PersistentRootedValueVector, and that's okay + GENERATE_JSTYPEDEF_PAIR("JS::PersistentRooted"), +}; + +AST_MATCHER(DeclaratorDecl, isUsingJSHandleRootedTypedef) { + QualType Type = Node.getType(); + std::string TypeName = Type.getAsString(); + for (auto &pair : JSHandleRootedTypedefMap) { + if (!TypeName.compare(pair[0])) { + return true; + } + } + return false; +} + +} // namespace ast_matchers +} // namespace clang + +#undef isRValue +#endif diff --git a/build/clang-plugin/CustomTypeAnnotation.cpp b/build/clang-plugin/CustomTypeAnnotation.cpp new file mode 100644 index 0000000000..6e0f44ce05 --- /dev/null +++ b/build/clang-plugin/CustomTypeAnnotation.cpp @@ -0,0 +1,182 @@ +/* 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 "CustomTypeAnnotation.h" +#include "Utils.h" + +CustomTypeAnnotation StackClass = + CustomTypeAnnotation(moz_stack_class, "stack"); +CustomTypeAnnotation GlobalClass = + CustomTypeAnnotation(moz_global_class, "global"); +CustomTypeAnnotation NonHeapClass = + CustomTypeAnnotation(moz_nonheap_class, "non-heap"); +CustomTypeAnnotation HeapClass = CustomTypeAnnotation(moz_heap_class, "heap"); +CustomTypeAnnotation NonTemporaryClass = + CustomTypeAnnotation(moz_non_temporary_class, "non-temporary"); +CustomTypeAnnotation TemporaryClass = + CustomTypeAnnotation(moz_temporary_class, "temporary"); +CustomTypeAnnotation StaticLocalClass = + CustomTypeAnnotation(moz_static_local_class, "static-local"); + +void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T, + SourceLocation Loc) { + const char *Inherits = + "%1 is a %0 type because it inherits from a %0 type %2"; + const char *Member = "%1 is a %0 type because member %2 is a %0 type %3"; + const char *Array = "%1 is a %0 type because it is an array of %0 type %2"; + const char *Templ = + "%1 is a %0 type because it has a template argument %0 type %2"; + const char *Implicit = "%1 is a %0 type because %2"; + + AnnotationReason Reason = directAnnotationReason(T); + for (;;) { + switch (Reason.Kind) { + case RK_ArrayElement: + Check.diag(Loc, Array, DiagnosticIDs::Note) << Pretty << T << Reason.Type; + break; + case RK_BaseClass: { + const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl(); + assert(Declaration && "This type should be a C++ class"); + + Check.diag(Declaration->getLocation(), Inherits, DiagnosticIDs::Note) + << Pretty << T << Reason.Type; + break; + } + case RK_Field: + Check.diag(Reason.Field->getLocation(), Member, DiagnosticIDs::Note) + << Pretty << T << Reason.Field << Reason.Type; + break; + case RK_TemplateInherited: { + const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl(); + assert(Declaration && "This type should be a C++ class"); + + Check.diag(Declaration->getLocation(), Templ, DiagnosticIDs::Note) + << Pretty << T << Reason.Type; + break; + } + case RK_Implicit: { + const TagDecl *Declaration = T->getAsTagDecl(); + assert(Declaration && "This type should be a TagDecl"); + + Check.diag(Declaration->getLocation(), Implicit, DiagnosticIDs::Note) + << Pretty << T << Reason.ImplicitReason; + return; + } + default: + // FIXME (bug 1203263): note the original annotation. + return; + } + + T = Reason.Type; + Reason = directAnnotationReason(T); + } +} + +CustomTypeAnnotation::AnnotationReason +CustomTypeAnnotation::directAnnotationReason(QualType T) { + VisitFlags ToVisit = VISIT_FIELDS | VISIT_BASES; + + if (const TagDecl *D = T->getAsTagDecl()) { + // Recurse into template arguments if the annotation + // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present + if (hasCustomAttribute<moz_inherit_type_annotations_from_template_args>( + D)) { + ToVisit |= VISIT_TMPL_ARGS; + } + + if (hasCustomAttribute(D, Attribute)) { + AnnotationReason Reason = {T, RK_Direct, nullptr, ""}; + return Reason; + } + + std::string ImplAnnotReason = getImplicitReason(D, ToVisit); + if (!ImplAnnotReason.empty()) { + AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason}; + return Reason; + } + } + + // Check if we have a cached answer + void *Key = T.getAsOpaquePtr(); + ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr()); + if (Cached != Cache.end()) { + return Cached->second; + } + + // Check if we have a type which we can recurse into + if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) { + if (hasEffectiveAnnotation(Array->getElementType())) { + AnnotationReason Reason{Array->getElementType(), RK_ArrayElement, nullptr, + ""}; + Cache[Key] = Reason; + return Reason; + } + } + + // Recurse into Base classes + if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) { + if (Declaration->hasDefinition()) { + Declaration = Declaration->getDefinition(); + + if (ToVisit & VISIT_BASES) { + for (const CXXBaseSpecifier &Base : Declaration->bases()) { + if (hasEffectiveAnnotation(Base.getType())) { + AnnotationReason Reason{Base.getType(), RK_BaseClass, nullptr, ""}; + Cache[Key] = Reason; + return Reason; + } + } + } + + if (ToVisit & VISIT_FIELDS) { + for (const FieldDecl *Field : Declaration->fields()) { + if (hasEffectiveAnnotation(Field->getType())) { + AnnotationReason Reason{Field->getType(), RK_Field, Field, ""}; + Cache[Key] = Reason; + return Reason; + } + } + } + + if (ToVisit & VISIT_TMPL_ARGS) { + const ClassTemplateSpecializationDecl *Spec = + dyn_cast<ClassTemplateSpecializationDecl>(Declaration); + if (Spec) { + const TemplateArgumentList &Args = Spec->getTemplateArgs(); + + AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray()); + if (Reason.Kind != RK_None) { + Cache[Key] = Reason; + return Reason; + } + } + } + } + } + + AnnotationReason Reason{QualType(), RK_None, nullptr, ""}; + Cache[Key] = Reason; + return Reason; +} + +CustomTypeAnnotation::AnnotationReason +CustomTypeAnnotation::tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args) { + for (const TemplateArgument &Arg : Args) { + if (Arg.getKind() == TemplateArgument::Type) { + QualType Type = Arg.getAsType(); + if (hasEffectiveAnnotation(Type)) { + AnnotationReason Reason = {Type, RK_TemplateInherited, nullptr, ""}; + return Reason; + } + } else if (Arg.getKind() == TemplateArgument::Pack) { + AnnotationReason Reason = tmplArgAnnotationReason(Arg.getPackAsArray()); + if (Reason.Kind != RK_None) { + return Reason; + } + } + } + + AnnotationReason Reason = {QualType(), RK_None, nullptr, ""}; + return Reason; +} diff --git a/build/clang-plugin/CustomTypeAnnotation.h b/build/clang-plugin/CustomTypeAnnotation.h new file mode 100644 index 0000000000..453976915a --- /dev/null +++ b/build/clang-plugin/CustomTypeAnnotation.h @@ -0,0 +1,92 @@ +/* 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/. */ + +#ifndef CustomTypeAnnotation_h__ +#define CustomTypeAnnotation_h__ + +#include "CustomAttributes.h" +#include "plugin.h" +#include "llvm/ADT/BitmaskEnum.h" + +class CustomTypeAnnotation { + enum ReasonKind { + RK_None, + RK_Direct, + RK_ArrayElement, + RK_BaseClass, + RK_Field, + RK_TemplateInherited, + RK_Implicit, + }; + struct AnnotationReason { + QualType Type; + ReasonKind Kind; + const FieldDecl *Field; + std::string ImplicitReason; + + bool valid() const { return Kind != RK_None; } + }; + typedef DenseMap<void *, AnnotationReason> ReasonCache; + + CustomAttributes Attribute; + const char *Pretty; + ReasonCache Cache; + +public: + CustomTypeAnnotation(CustomAttributes Attribute, const char *Pretty) + : Attribute(Attribute), Pretty(Pretty){}; + + virtual ~CustomTypeAnnotation() {} + + // Checks if this custom annotation "effectively affects" the given type. + bool hasEffectiveAnnotation(QualType T) { + return directAnnotationReason(T).valid(); + } + void dumpAnnotationReason(BaseCheck &Check, QualType T, SourceLocation Loc); + + void reportErrorIfPresent(BaseCheck &Check, QualType T, SourceLocation Loc, + const char *Error, const char *Note) { + if (hasEffectiveAnnotation(T)) { + Check.diag(Loc, Error, DiagnosticIDs::Error) << T; + Check.diag(Loc, Note, DiagnosticIDs::Note); + dumpAnnotationReason(Check, T, Loc); + } + } + +private: + AnnotationReason directAnnotationReason(QualType T); + AnnotationReason tmplArgAnnotationReason(ArrayRef<TemplateArgument> Args); + +protected: + // Flags specifying which properties of the underlying type we want to visit. + enum VisitFlags { + VISIT_NONE = 0, + VISIT_FIELDS = 1, + VISIT_TMPL_ARGS = 2, + VISIT_BASES = 4, + LLVM_MARK_AS_BITMASK_ENUM(VISIT_BASES) + }; + + // Allow subclasses to apply annotations for reasons other than a direct + // annotation. A non-empty string return value means that the object D is + // annotated, and should contain the reason why. + // + // The subclass may also modify `VisitFlags` to change what properties of the + // type will be inspected to skip inspecting fields, force template arguments + // to be inspected, etc. + virtual std::string getImplicitReason(const TagDecl *D, + VisitFlags &Flags) const { + return ""; + } +}; + +extern CustomTypeAnnotation StackClass; +extern CustomTypeAnnotation GlobalClass; +extern CustomTypeAnnotation NonHeapClass; +extern CustomTypeAnnotation HeapClass; +extern CustomTypeAnnotation NonTemporaryClass; +extern CustomTypeAnnotation TemporaryClass; +extern CustomTypeAnnotation StaticLocalClass; + +#endif diff --git a/build/clang-plugin/DanglingOnTemporaryChecker.cpp b/build/clang-plugin/DanglingOnTemporaryChecker.cpp new file mode 100644 index 0000000000..96d85ef4c0 --- /dev/null +++ b/build/clang-plugin/DanglingOnTemporaryChecker.cpp @@ -0,0 +1,256 @@ +/* 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 "DanglingOnTemporaryChecker.h" +#include "CustomMatchers.h" +#include "VariableUsageHelpers.h" + +void DanglingOnTemporaryChecker::registerMatchers(MatchFinder *AstMatcher) { + //////////////////////////////////////// + // Quick annotation conflict checkers // + //////////////////////////////////////// + + AstMatcher->addMatcher( + // This is a matcher on a method declaration, + cxxMethodDecl( + // which is marked as no dangling on temporaries, + noDanglingOnTemporaries(), + + // and which is && ref-qualified. + isRValueRefQualified(), + + decl().bind("invalidMethodRefQualified")), + this); + + AstMatcher->addMatcher( + // This is a matcher on a method declaration, + cxxMethodDecl( + // which is marked as no dangling on temporaries, + noDanglingOnTemporaries(), + + // which returns a primitive type, + returns(builtinType()), + + // and which doesn't return a pointer. + unless(returns(pointerType())), + + decl().bind("invalidMethodPointer")), + this); + + ////////////////// + // Main checker // + ////////////////// + + auto hasParentCall = hasParent( + expr(anyOf(cxxOperatorCallExpr( + // If we're in a lamda, we may have an operator call + // expression ancestor in the AST, but the temporary we're + // matching against is not going to have the same lifetime + // as the constructor call. + unless(has(expr(ignoreTrivials(lambdaExpr())))), + expr().bind("parentOperatorCallExpr")), + callExpr( + // If we're in a lamda, we may have a call expression + // ancestor in the AST, but the temporary we're matching + // against is not going to have the same lifetime as the + // function call. + unless(has(expr(ignoreTrivials(lambdaExpr())))), + expr().bind("parentCallExpr")), + objcMessageExpr( + // If we're in a lamda, we may have an objc message + // expression ancestor in the AST, but the temporary we're + // matching against is not going to have the same lifetime + // as the function call. + unless(has(expr(ignoreTrivials(lambdaExpr())))), + expr().bind("parentObjCMessageExpr")), + cxxConstructExpr( + // If we're in a lamda, we may have a construct expression + // ancestor in the AST, but the temporary we're matching + // against is not going to have the same lifetime as the + // constructor call. + unless(has(expr(ignoreTrivials(lambdaExpr())))), + expr().bind("parentConstructExpr"))))); + + AstMatcher->addMatcher( + // This is a matcher on a method call, + cxxMemberCallExpr( + // which is in first party code, + isFirstParty(), + + // and which is performed on a temporary, + on(allOf(unless(hasType(pointerType())), isTemporary(), + // but which is not `this`. + unless(cxxThisExpr()))), + + // and which is marked as no dangling on temporaries. + callee(cxxMethodDecl(noDanglingOnTemporaries())), + + expr().bind("memberCallExpr"), + + // We optionally match a parent call expression or a parent construct + // expression because using a temporary inside a call is fine as long + // as the pointer doesn't escape the function call. + anyOf( + // This is the case where the call is the direct parent, so we + // know that the member call expression is the argument. + allOf(hasParentCall, expr().bind("parentCallArg")), + + // This is the case where the call is not the direct parent, so we + // get its child to know in which argument tree we are. + hasAncestor(expr(hasParentCall, expr().bind("parentCallArg"))), + // To make it optional. + anything())), + this); +} + +void DanglingOnTemporaryChecker::check(const MatchFinder::MatchResult &Result) { + /////////////////////////////////////// + // Quick annotation conflict checker // + /////////////////////////////////////// + + const char *ErrorInvalidRefQualified = "methods annotated with " + "MOZ_NO_DANGLING_ON_TEMPORARIES " + "cannot be && ref-qualified"; + + const char *ErrorInvalidPointer = "methods annotated with " + "MOZ_NO_DANGLING_ON_TEMPORARIES must " + "return a pointer"; + + if (auto InvalidRefQualified = + Result.Nodes.getNodeAs<CXXMethodDecl>("invalidMethodRefQualified")) { + diag(InvalidRefQualified->getLocation(), ErrorInvalidRefQualified, + DiagnosticIDs::Error); + return; + } + + if (auto InvalidPointer = + Result.Nodes.getNodeAs<CXXMethodDecl>("invalidMethodPointer")) { + diag(InvalidPointer->getLocation(), ErrorInvalidPointer, + DiagnosticIDs::Error); + return; + } + + ////////////////// + // Main checker // + ////////////////// + + const char *Error = "calling `%0` on a temporary, potentially allowing use " + "after free of the raw pointer"; + + const char *EscapeStmtNote = + "the raw pointer escapes the function scope here"; + + const ObjCMessageExpr *ParentObjCMessageExpr = + Result.Nodes.getNodeAs<ObjCMessageExpr>("parentObjCMessageExpr"); + + // We don't care about cases in ObjC message expressions. + if (ParentObjCMessageExpr) { + return; + } + + const CXXMemberCallExpr *MemberCall = + Result.Nodes.getNodeAs<CXXMemberCallExpr>("memberCallExpr"); + + const CallExpr *ParentCallExpr = + Result.Nodes.getNodeAs<CallExpr>("parentCallExpr"); + const CXXConstructExpr *ParentConstructExpr = + Result.Nodes.getNodeAs<CXXConstructExpr>("parentConstructExpr"); + const CXXOperatorCallExpr *ParentOperatorCallExpr = + Result.Nodes.getNodeAs<CXXOperatorCallExpr>("parentOperatorCallExpr"); + const Expr *ParentCallArg = Result.Nodes.getNodeAs<Expr>("parentCallArg"); + + // Just in case. + if (!MemberCall) { + return; + } + + // If we have a parent call, we check whether or not we escape the function + // being called. + if (ParentOperatorCallExpr || ParentCallExpr || ParentConstructExpr) { + // Just in case. + if (!ParentCallArg) { + return; + } + + // No default constructor so we can't construct it using if/else. + auto FunctionEscapeData = + ParentOperatorCallExpr + ? escapesFunction(ParentCallArg, ParentOperatorCallExpr) + : ParentCallExpr + ? escapesFunction(ParentCallArg, ParentCallExpr) + : escapesFunction(ParentCallArg, ParentConstructExpr); + + // If there was an error in the escapesFunction call. + if (std::error_code ec = FunctionEscapeData.getError()) { + // FIXME: For now we ignore the variadic case and just consider that the + // argument doesn't escape the function. Same for the case where we can't + // find the function declaration or if the function is builtin. + if (static_cast<EscapesFunctionError>(ec.value()) == + EscapesFunctionError::FunctionIsVariadic || + static_cast<EscapesFunctionError>(ec.value()) == + EscapesFunctionError::FunctionDeclNotFound || + static_cast<EscapesFunctionError>(ec.value()) == + EscapesFunctionError::FunctionIsBuiltin) { + return; + } + + // We emit the internal checker error and return. + diag(MemberCall->getExprLoc(), + std::string(ec.category().name()) + " error: " + ec.message(), + DiagnosticIDs::Error); + return; + } + + // We deconstruct the function escape data. + const Stmt *EscapeStmt; + const Decl *EscapeDecl; + std::tie(EscapeStmt, EscapeDecl) = *FunctionEscapeData; + + // If we didn't escape a parent function, we're done: we don't emit any + // diagnostic. + if (!EscapeStmt || !EscapeDecl) { + return; + } + + // We emit the error diagnostic indicating that we are calling the method + // temporary. + diag(MemberCall->getExprLoc(), Error, DiagnosticIDs::Error) + << MemberCall->getMethodDecl()->getName() + << MemberCall->getSourceRange(); + + // We indicate the escape statement. + diag(EscapeStmt->getBeginLoc(), EscapeStmtNote, DiagnosticIDs::Note) + << EscapeStmt->getSourceRange(); + + // We build the escape note along with its source range. + StringRef EscapeDeclNote; + SourceRange EscapeDeclRange; + if (isa<ParmVarDecl>(EscapeDecl)) { + EscapeDeclNote = "through the parameter declared here"; + EscapeDeclRange = EscapeDecl->getSourceRange(); + } else if (isa<VarDecl>(EscapeDecl)) { + EscapeDeclNote = "through the variable declared here"; + EscapeDeclRange = EscapeDecl->getSourceRange(); + } else if (isa<FieldDecl>(EscapeDecl)) { + EscapeDeclNote = "through the field declared here"; + EscapeDeclRange = EscapeDecl->getSourceRange(); + } else if (auto FuncDecl = dyn_cast<FunctionDecl>(EscapeDecl)) { + EscapeDeclNote = "through the return value of the function declared here"; + EscapeDeclRange = FuncDecl->getReturnTypeSourceRange(); + } else { + return; + } + + // We emit the declaration note indicating through which decl the argument + // escapes. + diag(EscapeDecl->getLocation(), EscapeDeclNote, DiagnosticIDs::Note) + << EscapeDeclRange; + } else { + // We emit the error diagnostic indicating that we are calling the method + // temporary. + diag(MemberCall->getExprLoc(), Error, DiagnosticIDs::Error) + << MemberCall->getMethodDecl()->getName() + << MemberCall->getSourceRange(); + } +} diff --git a/build/clang-plugin/DanglingOnTemporaryChecker.h b/build/clang-plugin/DanglingOnTemporaryChecker.h new file mode 100644 index 0000000000..43f19ebedc --- /dev/null +++ b/build/clang-plugin/DanglingOnTemporaryChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef DanglingOnTemporaryChecker_h__ +#define DanglingOnTemporaryChecker_h__ + +#include "plugin.h" + +class DanglingOnTemporaryChecker : public BaseCheck { +public: + DanglingOnTemporaryChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/DiagnosticsMatcher.cpp b/build/clang-plugin/DiagnosticsMatcher.cpp new file mode 100644 index 0000000000..96d2f60440 --- /dev/null +++ b/build/clang-plugin/DiagnosticsMatcher.cpp @@ -0,0 +1,17 @@ +/* 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 "DiagnosticsMatcher.h" + +DiagnosticsMatcher::DiagnosticsMatcher(CompilerInstance &CI) { +#define CHECK(cls, name) \ + cls##_.registerMatchers(&AstMatcher); \ + cls##_.registerPPCallbacks(CI); +#include "Checks.inc" +#include "external/ExternalChecks.inc" +#ifdef MOZ_CLANG_PLUGIN_ALPHA +#include "alpha/AlphaChecks.inc" +#endif +#undef CHECK +} diff --git a/build/clang-plugin/DiagnosticsMatcher.h b/build/clang-plugin/DiagnosticsMatcher.h new file mode 100644 index 0000000000..2738541f62 --- /dev/null +++ b/build/clang-plugin/DiagnosticsMatcher.h @@ -0,0 +1,31 @@ +/* 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/. */ + +#ifndef DiagnosticsMatcher_h__ +#define DiagnosticsMatcher_h__ + +#include "ChecksIncludes.inc" +#include "external/ExternalIncludes.inc" +#ifdef MOZ_CLANG_PLUGIN_ALPHA +#include "alpha/AlphaIncludes.inc" +#endif + +class DiagnosticsMatcher { +public: + DiagnosticsMatcher(CompilerInstance &CI); + + ASTConsumerPtr makeASTConsumer() { return AstMatcher.newASTConsumer(); } + +private: +#define CHECK(cls, name) cls cls##_{name}; +#include "Checks.inc" +#include "external/ExternalChecks.inc" +#ifdef MOZ_CLANG_PLUGIN_ALPHA +#include "alpha/AlphaChecks.inc" +#endif +#undef CHECK + MatchFinder AstMatcher; +}; + +#endif diff --git a/build/clang-plugin/ExplicitImplicitChecker.cpp b/build/clang-plugin/ExplicitImplicitChecker.cpp new file mode 100644 index 0000000000..e0620f502f --- /dev/null +++ b/build/clang-plugin/ExplicitImplicitChecker.cpp @@ -0,0 +1,36 @@ +/* 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 "ExplicitImplicitChecker.h" +#include "CustomMatchers.h" + +void ExplicitImplicitChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxConstructorDecl( + isInterestingImplicitCtor(), + ofClass(allOf(isConcreteClass(), decl().bind("class"))), + unless(isMarkedImplicit())) + .bind("ctor"), + this); +} + +void ExplicitImplicitChecker::check(const MatchFinder::MatchResult &Result) { + // We've already checked everything in the matcher, so we just have to report + // the error. + + const CXXConstructorDecl *Ctor = + Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor"); + const CXXRecordDecl *Declaration = + Result.Nodes.getNodeAs<CXXRecordDecl>("class"); + + FixItHint FixItHint = + FixItHint::CreateInsertion(Ctor->getLocation(), "explicit "); + diag(Ctor->getLocation(), "bad implicit conversion constructor for %0", + DiagnosticIDs::Error) + << Declaration->getDeclName(); + diag(Ctor->getLocation(), + "consider adding the explicit keyword to the constructor", + DiagnosticIDs::Note) + << FixItHint; +} diff --git a/build/clang-plugin/ExplicitImplicitChecker.h b/build/clang-plugin/ExplicitImplicitChecker.h new file mode 100644 index 0000000000..f1591c999e --- /dev/null +++ b/build/clang-plugin/ExplicitImplicitChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef ExplicitImplicitChecker_h__ +#define ExplicitImplicitChecker_h__ + +#include "plugin.h" + +class ExplicitImplicitChecker : public BaseCheck { +public: + ExplicitImplicitChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/ExplicitOperatorBoolChecker.cpp b/build/clang-plugin/ExplicitOperatorBoolChecker.cpp new file mode 100644 index 0000000000..ed97335a00 --- /dev/null +++ b/build/clang-plugin/ExplicitOperatorBoolChecker.cpp @@ -0,0 +1,31 @@ +/* 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 "ExplicitOperatorBoolChecker.h" +#include "CustomMatchers.h" + +void ExplicitOperatorBoolChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxMethodDecl(allOf(isFirstParty(), hasName("operator bool"))) + .bind("node"), + this); +} + +void ExplicitOperatorBoolChecker::check( + const MatchFinder::MatchResult &Result) { + const CXXConversionDecl *Method = + Result.Nodes.getNodeAs<CXXConversionDecl>("node"); + const CXXRecordDecl *Clazz = Method->getParent(); + + if (!Method->isExplicit() && !hasCustomAttribute<moz_implicit>(Method) && + !ASTIsInSystemHeader(Method->getASTContext(), *Method) && + isInterestingDeclForImplicitConversion(Method)) { + diag(Method->getBeginLoc(), "bad implicit conversion operator for %0", + DiagnosticIDs::Error) + << Clazz; + diag(Method->getBeginLoc(), "consider adding the explicit keyword to %0", + DiagnosticIDs::Note) + << "'operator bool'"; + } +} diff --git a/build/clang-plugin/ExplicitOperatorBoolChecker.h b/build/clang-plugin/ExplicitOperatorBoolChecker.h new file mode 100644 index 0000000000..90909e6296 --- /dev/null +++ b/build/clang-plugin/ExplicitOperatorBoolChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef ExplicitOperatorBoolChecker_h__ +#define ExplicitOperatorBoolChecker_h__ + +#include "plugin.h" + +class ExplicitOperatorBoolChecker : public BaseCheck { +public: + ExplicitOperatorBoolChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/FopenUsageChecker.cpp b/build/clang-plugin/FopenUsageChecker.cpp new file mode 100644 index 0000000000..905fc91f47 --- /dev/null +++ b/build/clang-plugin/FopenUsageChecker.cpp @@ -0,0 +1,73 @@ +/* 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 "FopenUsageChecker.h" +#include "CustomMatchers.h" + +void FopenUsageChecker::registerMatchers(MatchFinder *AstMatcher) { + + auto hasConstCharPtrParam = [](const unsigned int Position) { + return hasParameter( + Position, hasType(hasCanonicalType(pointsTo(asString("const char"))))); + }; + + auto hasParamOfType = [](const unsigned int Position, const char *Name) { + return hasParameter(Position, hasType(asString(Name))); + }; + + auto hasIntegerParam = [](const unsigned int Position) { + return hasParameter(Position, hasType(isInteger())); + }; + + AstMatcher->addMatcher( + callExpr( + allOf( + isFirstParty(), + callee(functionDecl(allOf( + isInSystemHeader(), + anyOf( + allOf(anyOf(allOf(hasName("fopen"), + hasConstCharPtrParam(0)), + allOf(hasName("fopen_s"), + hasParameter( + 0, hasType(pointsTo(pointsTo( + asString("FILE"))))), + hasConstCharPtrParam(2))), + hasConstCharPtrParam(1)), + allOf(anyOf(hasName("open"), + allOf(hasName("_open"), hasIntegerParam(2)), + allOf(hasName("_sopen"), hasIntegerParam(3))), + hasConstCharPtrParam(0), hasIntegerParam(1)), + allOf(hasName("_sopen_s"), + hasParameter(0, hasType(pointsTo(isInteger()))), + hasConstCharPtrParam(1), hasIntegerParam(2), + hasIntegerParam(3), hasIntegerParam(4)), + allOf(hasName("OpenFile"), hasConstCharPtrParam(0), + hasParamOfType(1, "LPOFSTRUCT"), + hasIntegerParam(2)), + allOf(hasName("CreateFileA"), hasConstCharPtrParam(0), + hasIntegerParam(1), hasIntegerParam(2), + hasParamOfType(3, "LPSECURITY_ATTRIBUTES"), + hasIntegerParam(4), hasIntegerParam(5), + hasParamOfType(6, "HANDLE")))))), + unless(isInWhitelistForFopenUsage()))) + .bind("funcCall"), + this); +} + +void FopenUsageChecker::check(const MatchFinder::MatchResult &Result) { + const CallExpr *FuncCall = Result.Nodes.getNodeAs<CallExpr>("funcCall"); + static const char *ExtraInfo = + "On Windows executed functions: fopen, fopen_s, open, _open, _sopen, " + "_sopen_s, OpenFile, CreateFileA should never be used due to lossy " + "conversion from UTF8 to ANSI."; + + if (FuncCall) { + diag(FuncCall->getBeginLoc(), + "Usage of ASCII file functions (here %0) is forbidden on Windows.", + DiagnosticIDs::Warning) + << FuncCall->getDirectCallee()->getName(); + diag(FuncCall->getBeginLoc(), ExtraInfo, DiagnosticIDs::Note); + } +} diff --git a/build/clang-plugin/FopenUsageChecker.h b/build/clang-plugin/FopenUsageChecker.h new file mode 100644 index 0000000000..9dc71831ab --- /dev/null +++ b/build/clang-plugin/FopenUsageChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef FopenUsageChecker_h__ +#define FopenUsageChecker_h__ + +#include "plugin.h" + +class FopenUsageChecker : public BaseCheck { +public: + FopenUsageChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/JSHandleRootedTypedefChecker.cpp b/build/clang-plugin/JSHandleRootedTypedefChecker.cpp new file mode 100644 index 0000000000..3e3adf7906 --- /dev/null +++ b/build/clang-plugin/JSHandleRootedTypedefChecker.cpp @@ -0,0 +1,38 @@ +/* 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 "JSHandleRootedTypedefChecker.h" +#include "CustomMatchers.h" + +void JSHandleRootedTypedefChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + declaratorDecl(isUsingJSHandleRootedTypedef(), isNotSpiderMonkey()) + .bind("declaratorDecl"), + this); +} + +std::string getReplacement(std::string TypeName) { + for (auto &pair : JSHandleRootedTypedefMap) { + if (!TypeName.compare(pair[0])) { + return pair[1]; + } + } + llvm_unreachable("Unexpected type name"); +} + +void JSHandleRootedTypedefChecker::check( + const MatchFinder::MatchResult &Result) { + const char *Error = "The fully qualified types are preferred over the " + "shorthand typedefs for JS::Handle/JS::Rooted types " + "outside SpiderMonkey."; + + const DeclaratorDecl *Declarator = + Result.Nodes.getNodeAs<DeclaratorDecl>("declaratorDecl"); + + std::string Replacement = getReplacement(Declarator->getType().getAsString()); + diag(Declarator->getBeginLoc(), Error, DiagnosticIDs::Error) + << FixItHint::CreateReplacement( + Declarator->getTypeSourceInfo()->getTypeLoc().getSourceRange(), + Replacement); +} diff --git a/build/clang-plugin/JSHandleRootedTypedefChecker.h b/build/clang-plugin/JSHandleRootedTypedefChecker.h new file mode 100644 index 0000000000..32fc8fff9b --- /dev/null +++ b/build/clang-plugin/JSHandleRootedTypedefChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef BUILD_CLANG_PLUGIN_JSHANDLEROOTEDTYPEDEFCHECKER_H_ +#define BUILD_CLANG_PLUGIN_JSHANDLEROOTEDTYPEDEFCHECKER_H_ + +#include "plugin.h" + +class JSHandleRootedTypedefChecker : public BaseCheck { +public: + JSHandleRootedTypedefChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/KnownLiveChecker.cpp b/build/clang-plugin/KnownLiveChecker.cpp new file mode 100644 index 0000000000..be0c3739ec --- /dev/null +++ b/build/clang-plugin/KnownLiveChecker.cpp @@ -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/. */ + +#include "KnownLiveChecker.h" +#include "CustomMatchers.h" + +void KnownLiveChecker::registerMatchers(MatchFinder *AstMatcher) { + // Note that this cannot catch mutations after pass-by-reference, and thus no + // error for cycle collection macros. + + auto KnownLiveLHS = hasLHS(memberExpr(hasKnownLiveAnnotation()).bind("lhs")); + auto ForGeneralFunctions = forFunction( + functionDecl(unless(anyOf(cxxConstructorDecl(), cxxDestructorDecl()))) + .bind("func")); + + auto Matcher = + allOf(isAssignmentOperator(), KnownLiveLHS, ForGeneralFunctions); + + AstMatcher->addMatcher(binaryOperator(Matcher), this); + AstMatcher->addMatcher(cxxOperatorCallExpr(Matcher), this); +} + +void KnownLiveChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = "MOZ_KNOWN_LIVE members can only be modified by " + "constructors and destructors"; + + if (const MemberExpr *Expr = Result.Nodes.getNodeAs<MemberExpr>("lhs")) { + diag(Expr->getBeginLoc(), Error, DiagnosticIDs::Error); + } + if (const CXXOperatorCallExpr *Expr = + Result.Nodes.getNodeAs<CXXOperatorCallExpr>("lhs")) { + diag(Expr->getBeginLoc(), Error, DiagnosticIDs::Error); + } +} diff --git a/build/clang-plugin/KnownLiveChecker.h b/build/clang-plugin/KnownLiveChecker.h new file mode 100644 index 0000000000..bd92d0b326 --- /dev/null +++ b/build/clang-plugin/KnownLiveChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef BUILD_CLANG_PLUGIN_KNOWNLIVECHECKER_H_ +#define BUILD_CLANG_PLUGIN_KNOWNLIVECHECKER_H_ + +#include "plugin.h" + +class KnownLiveChecker : public BaseCheck { +public: + KnownLiveChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/KungFuDeathGripChecker.cpp b/build/clang-plugin/KungFuDeathGripChecker.cpp new file mode 100644 index 0000000000..03bb20514f --- /dev/null +++ b/build/clang-plugin/KungFuDeathGripChecker.cpp @@ -0,0 +1,114 @@ +/* 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 "KungFuDeathGripChecker.h" +#include "CustomMatchers.h" + +void KungFuDeathGripChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(varDecl(allOf(hasType(isRefPtr()), hasLocalStorage(), + hasInitializer(anything()))) + .bind("decl"), + this); +} + +void KungFuDeathGripChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = "Unused \"kungFuDeathGrip\" %0 objects constructed from " + "%1 are prohibited"; + const char *Note = "Please switch all accesses to this %0 to go through " + "'%1', or explicitly pass '%1' to `mozilla::Unused`"; + + const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("decl"); + if (D->isReferenced()) { + return; + } + + // Not interested in parameters. + if (isa<ImplicitParamDecl>(D) || isa<ParmVarDecl>(D)) { + return; + } + + const Expr *E = IgnoreTrivials(D->getInit()); + const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E); + if (CE && CE->getNumArgs() == 0) { + // We don't report an error when we construct and don't use a nsCOMPtr / + // nsRefPtr with no arguments. We don't report it because the error is not + // related to the current check. In the future it may be reported through a + // more generic mechanism. + return; + } + + // We don't want to look at the single argument conversion constructors + // which are inbetween the declaration and the actual object which we are + // assigning into the nsCOMPtr/RefPtr. To do this, we repeatedly + // IgnoreTrivials, then look at the expression. If it is one of these + // conversion constructors, we ignore it and continue to dig. + while ((CE = dyn_cast<CXXConstructExpr>(E)) && CE->getNumArgs() == 1) { + E = IgnoreTrivials(CE->getArg(0)); + } + + // If the argument expression is an xvalue, we are not taking a copy of + // anything. + if (E->isXValue()) { + return; + } + + // It is possible that the QualType doesn't point to a type yet so we are + // not interested. + if (E->getType().isNull()) { + return; + } + + // We allow taking a kungFuDeathGrip of `this` because it cannot change + // beneath us, so calling directly through `this` is OK. This is the same + // for local variable declarations. + // + // We also don't complain about unused RefPtrs which are constructed from + // the return value of a new expression, as these are required in order to + // immediately destroy the value created (which was presumably created for + // its side effects), and are not used as a death grip. + if (isa<CXXThisExpr>(E) || isa<DeclRefExpr>(E) || isa<CXXNewExpr>(E)) { + return; + } + + // These types are assigned into nsCOMPtr and RefPtr for their side effects, + // and not as a kungFuDeathGrip. We don't want to consider RefPtr and nsCOMPtr + // types which are initialized with these types as errors. + const TagDecl *TD = E->getType()->getAsTagDecl(); + if (TD && TD->getIdentifier()) { + static const char *IgnoreTypes[] = { + "already_AddRefed", + "nsGetServiceByCID", + "nsGetServiceByCIDWithError", + "nsGetServiceByContractID", + "nsGetServiceByContractIDWithError", + "nsCreateInstanceByCID", + "nsCreateInstanceByContractID", + "nsCreateInstanceFromFactory", + }; + + for (uint32_t i = 0; i < sizeof(IgnoreTypes) / sizeof(IgnoreTypes[0]); + ++i) { + if (TD->getName() == IgnoreTypes[i]) { + return; + } + } + } + + // Report the error + const char *ErrThing; + const char *NoteThing; + if (isa<MemberExpr>(E)) { + ErrThing = "members"; + NoteThing = "member"; + } else { + ErrThing = "temporary values"; + NoteThing = "value"; + } + + // We cannot provide the note if we don't have an initializer + diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) + << D->getType() << ErrThing; + diag(E->getBeginLoc(), Note, DiagnosticIDs::Note) + << NoteThing << getNameChecked(D); +} diff --git a/build/clang-plugin/KungFuDeathGripChecker.h b/build/clang-plugin/KungFuDeathGripChecker.h new file mode 100644 index 0000000000..6bb2c76835 --- /dev/null +++ b/build/clang-plugin/KungFuDeathGripChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef KungFuDeathGripChecker_h__ +#define KungFuDeathGripChecker_h__ + +#include "plugin.h" + +class KungFuDeathGripChecker : public BaseCheck { +public: + KungFuDeathGripChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/LoadLibraryUsageChecker.cpp b/build/clang-plugin/LoadLibraryUsageChecker.cpp new file mode 100644 index 0000000000..1c7d336ea9 --- /dev/null +++ b/build/clang-plugin/LoadLibraryUsageChecker.cpp @@ -0,0 +1,34 @@ +/* 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 "LoadLibraryUsageChecker.h" +#include "CustomMatchers.h" + +// On MacOS the filesystem is UTF-8, on linux the canonical filename is 8-bit +// string. On Windows data loss conversion will occur. This checker restricts +// the use of ASCII file functions for loading libraries. + +void LoadLibraryUsageChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + callExpr( + allOf(isFirstParty(), + callee(functionDecl(anyOf( + allOf(isInSystemHeader(), anyOf(hasName("LoadLibraryA"), + hasName("LoadLibraryExA"))), + hasName("PR_LoadLibrary")))), + unless(hasArgument(0, stringLiteral())))) + .bind("funcCall"), + this); +} + +void LoadLibraryUsageChecker::check(const MatchFinder::MatchResult &Result) { + const CallExpr *FuncCall = Result.Nodes.getNodeAs<CallExpr>("funcCall"); + + if (FuncCall) { + diag(FuncCall->getBeginLoc(), + "Usage of ASCII file functions (such as %0) is forbidden.", + DiagnosticIDs::Error) + << FuncCall->getDirectCallee()->getName(); + } +} diff --git a/build/clang-plugin/LoadLibraryUsageChecker.h b/build/clang-plugin/LoadLibraryUsageChecker.h new file mode 100644 index 0000000000..f7b60234be --- /dev/null +++ b/build/clang-plugin/LoadLibraryUsageChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef LoadLibraryUsageChecker_h__ +#define LoadLibraryUsageChecker_h__ + +#include "plugin.h" + +class LoadLibraryUsageChecker : public BaseCheck { +public: + LoadLibraryUsageChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif // !defined(LoadLibraryUsageChecker_h__) diff --git a/build/clang-plugin/Makefile.in b/build/clang-plugin/Makefile.in new file mode 100644 index 0000000000..b4c9d40de0 --- /dev/null +++ b/build/clang-plugin/Makefile.in @@ -0,0 +1,14 @@ +# 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 + +HOST_LDFLAGS += $(LLVM_LDFLAGS) $(CLANG_LDFLAGS) + +ifeq ($(HOST_OS_ARCH),WINNT) +# clang-plugin.dll needs to be deterministic for sccache hashes +HOST_LDFLAGS += -brepro +else +HOST_LDFLAGS += -shared +endif diff --git a/build/clang-plugin/MemMoveAnnotation.h b/build/clang-plugin/MemMoveAnnotation.h new file mode 100644 index 0000000000..0a1a96e8ff --- /dev/null +++ b/build/clang-plugin/MemMoveAnnotation.h @@ -0,0 +1,62 @@ +/* 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/. */ + +#ifndef MemMoveAnnotation_h__ +#define MemMoveAnnotation_h__ + +#include "CustomMatchers.h" +#include "CustomTypeAnnotation.h" +#include "Utils.h" + +#include <unordered_set> + +class MemMoveAnnotation final : public CustomTypeAnnotation { +public: + MemMoveAnnotation() + : CustomTypeAnnotation(moz_non_memmovable, "non-memmove()able") {} + + virtual ~MemMoveAnnotation() {} + +protected: + std::string getImplicitReason(const TagDecl *D, + VisitFlags &ToVisit) const override { + // Annotate everything in ::std, with a few exceptions; see bug + // 1201314 for discussion. + if (getDeclarationNamespace(D) != "std") { + return ""; + } + + StringRef Name = getNameChecked(D); + + // If the type has a trivial move constructor and destructor, it is safe to + // memmove, and we don't need to visit any fields. + auto RD = dyn_cast<CXXRecordDecl>(D); + if (RD && RD->isCompleteDefinition() && + (RD->hasTrivialMoveConstructor() || + (!RD->hasMoveConstructor() && RD->hasTrivialCopyConstructor())) && + RD->hasTrivialDestructor()) { + ToVisit = VISIT_NONE; + return ""; + } + + // This doesn't check that it's really ::std::pair and not + // ::std::something_else::pair, but should be good enough. + if (isNameExcepted(Name.data())) { + // If we're an excepted name, stop traversing within the type further, + // and only check template arguments for foreign types. + ToVisit = VISIT_TMPL_ARGS; + return ""; + } + return "it is an stl-provided type not guaranteed to be memmove-able"; + } + +private: + bool isNameExcepted(StringRef Name) const { + return Name == "pair" || Name == "atomic" || Name == "tuple"; + } +}; + +extern MemMoveAnnotation NonMemMovable; + +#endif diff --git a/build/clang-plugin/MozCheckAction.cpp b/build/clang-plugin/MozCheckAction.cpp new file mode 100644 index 0000000000..6ec8c92bd8 --- /dev/null +++ b/build/clang-plugin/MozCheckAction.cpp @@ -0,0 +1,27 @@ +/* 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 "DiagnosticsMatcher.h" +#include "plugin.h" +#include "clang/Frontend/FrontendPluginRegistry.h" + +class MozCheckAction : public PluginASTAction { +public: + ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, + StringRef FileName) override { + void *Buffer = CI.getASTContext().Allocate<DiagnosticsMatcher>(); + auto Matcher = new (Buffer) DiagnosticsMatcher(CI); + return Matcher->makeASTConsumer(); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector<std::string> &Args) override { + return true; + } +}; + +static FrontendPluginRegistry::Add<MozCheckAction> X("moz-check", + "check moz action"); + +DenseMap<StringRef, bool> InThirdPartyPathCache; diff --git a/build/clang-plugin/MozillaTidyModule.cpp b/build/clang-plugin/MozillaTidyModule.cpp new file mode 100644 index 0000000000..b1870e7454 --- /dev/null +++ b/build/clang-plugin/MozillaTidyModule.cpp @@ -0,0 +1,45 @@ +/* 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/. */ + +#ifdef CLANG_TIDY + +#include "../ClangTidy.h" +#include "../ClangTidyModule.h" +#include "../ClangTidyModuleRegistry.h" +#include "ChecksIncludes.inc" +#include "external/ExternalIncludes.inc" +#ifdef MOZ_CLANG_PLUGIN_ALPHA +#include "alpha/AlphaIncludes.inc" +#endif + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +class MozillaModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { +#define CHECK(cls, name) CheckFactories.registerCheck<cls>("mozilla-" name); +#include "Checks.inc" +#include "external/ExternalChecks.inc" +#ifdef MOZ_CLANG_PLUGIN_ALPHA +#include "alpha/AlphaChecks.inc" +#endif +#undef CHECK + } +}; + +// Register the MozillaTidyModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add<MozillaModule> + X("mozilla-module", "Adds Mozilla lint checks."); + +} // namespace tidy +} // namespace clang + +// This anchor is used to force the linker to link in the generated object file +// and thus register the MozillaModule. +volatile int MozillaModuleAnchorSource = 0; + +#endif diff --git a/build/clang-plugin/MustOverrideChecker.cpp b/build/clang-plugin/MustOverrideChecker.cpp new file mode 100644 index 0000000000..b19ae94aac --- /dev/null +++ b/build/clang-plugin/MustOverrideChecker.cpp @@ -0,0 +1,60 @@ +/* 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 "MustOverrideChecker.h" +#include "CustomMatchers.h" + +void MustOverrideChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(cxxRecordDecl(isDefinition()).bind("class"), this); +} + +void MustOverrideChecker::registerPPCallbacks(CompilerInstance &CI) { + this->CI = &CI; +} + +void MustOverrideChecker::check(const MatchFinder::MatchResult &Result) { + auto D = Result.Nodes.getNodeAs<CXXRecordDecl>("class"); + + // Look through all of our immediate bases to find methods that need to be + // overridden + typedef std::vector<CXXMethodDecl *> OverridesVector; + OverridesVector MustOverrides; + for (const auto &Base : D->bases()) { + // The base is either a class (CXXRecordDecl) or it's a templated class... + CXXRecordDecl *Parent = Base.getType() + .getDesugaredType(D->getASTContext()) + ->getAsCXXRecordDecl(); + // The parent might not be resolved to a type yet. In this case, we can't + // do any checking here. For complete correctness, we should visit + // template instantiations, but this case is likely to be rare, so we will + // ignore it until it becomes important. + if (!Parent) { + continue; + } + Parent = Parent->getDefinition(); + for (const auto &M : Parent->methods()) { + if (hasCustomAttribute<moz_must_override>(M)) + MustOverrides.push_back(M); + } + } + + for (auto &O : MustOverrides) { + bool Overridden = false; + for (const auto &M : D->methods()) { + // The way that Clang checks if a method M overrides its parent method + // is if the method has the same name but would not overload. + if (getNameChecked(M) == getNameChecked(O) && + !CI->getSema().IsOverload(M, O, false)) { + Overridden = true; + break; + } + } + if (!Overridden) { + diag(D->getLocation(), "%0 must override %1", DiagnosticIDs::Error) + << D->getDeclName() << O->getDeclName(); + diag(O->getLocation(), "function to override is here", + DiagnosticIDs::Note); + } + } +} diff --git a/build/clang-plugin/MustOverrideChecker.h b/build/clang-plugin/MustOverrideChecker.h new file mode 100644 index 0000000000..ed1835eb57 --- /dev/null +++ b/build/clang-plugin/MustOverrideChecker.h @@ -0,0 +1,22 @@ +/* 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/. */ + +#ifndef MustOverrideChecker_h__ +#define MustOverrideChecker_h__ + +#include "plugin.h" + +class MustOverrideChecker : public BaseCheck { +public: + MustOverrideChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context), CI(nullptr) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void registerPPCallbacks(CompilerInstance &CI) override; + void check(const MatchFinder::MatchResult &Result) override; + +private: + const CompilerInstance *CI; +}; + +#endif diff --git a/build/clang-plugin/MustReturnFromCallerChecker.cpp b/build/clang-plugin/MustReturnFromCallerChecker.cpp new file mode 100644 index 0000000000..df28ddb4d3 --- /dev/null +++ b/build/clang-plugin/MustReturnFromCallerChecker.cpp @@ -0,0 +1,136 @@ +/* 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 "MustReturnFromCallerChecker.h" +#include "CustomMatchers.h" + +void MustReturnFromCallerChecker::registerMatchers(MatchFinder *AstMatcher) { + // Look for a call to a MOZ_MUST_RETURN_FROM_CALLER member + AstMatcher->addMatcher( + cxxMemberCallExpr( + on(declRefExpr(to(parmVarDecl()))), + callee(functionDecl(isMozMustReturnFromCaller())), + anyOf(hasAncestor(lambdaExpr().bind("containing-lambda")), + hasAncestor(functionDecl().bind("containing-func")))) + .bind("call"), + this); +} + +void MustReturnFromCallerChecker::check( + const MatchFinder::MatchResult &Result) { + const auto *ContainingLambda = + Result.Nodes.getNodeAs<LambdaExpr>("containing-lambda"); + const auto *ContainingFunc = + Result.Nodes.getNodeAs<FunctionDecl>("containing-func"); + const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call"); + + Stmt *Body = nullptr; + if (ContainingLambda) { + Body = ContainingLambda->getBody(); + } else if (ContainingFunc) { + Body = ContainingFunc->getBody(); + } else { + return; + } + assert(Body && "Should have a body by this point"); + + // Generate the CFG for the enclosing function or decl. + CFG::BuildOptions Options; + std::unique_ptr<CFG> TheCFG = + CFG::buildCFG(nullptr, Body, Result.Context, Options); + if (!TheCFG) { + return; + } + + // Determine which block in the CFG we want to look at the successors of. + StmtToBlockMap BlockMap(TheCFG.get(), Result.Context); + size_t CallIndex; + const auto *Block = BlockMap.blockContainingStmt(Call, &CallIndex); + if (!Block) { + // This statement is not within the CFG! + return; + } + + if (!immediatelyReturns(Block, Result.Context, CallIndex + 1)) { + diag(Call->getBeginLoc(), + "You must immediately return after calling this function", + DiagnosticIDs::Error); + } +} + +bool MustReturnFromCallerChecker::isIgnorable(const Stmt *S) { + auto AfterTrivials = IgnoreTrivials(S); + + // After a call to MOZ_MUST_RETURN_FROM_CALLER function it's ok to have any of + // these expressions. + if (isa<ReturnStmt>(AfterTrivials) || isa<CXXConstructExpr>(AfterTrivials) || + isa<DeclRefExpr>(AfterTrivials) || isa<MemberExpr>(AfterTrivials) || + isa<IntegerLiteral>(AfterTrivials) || + isa<FloatingLiteral>(AfterTrivials) || + isa<CXXNullPtrLiteralExpr>(AfterTrivials) || + isa<CXXBoolLiteralExpr>(AfterTrivials)) { + return true; + } + + // Solitary `this` should be permited, like in the context `return this;` + if (auto TE = dyn_cast<CXXThisExpr>(AfterTrivials)) { + if (TE->child_begin() == TE->child_end()) { + return true; + } + return false; + } + + // For UnaryOperator make sure we only accept arithmetic operations. + if (auto UO = dyn_cast<UnaryOperator>(AfterTrivials)) { + if (!UO->isArithmeticOp()) { + return false; + } + return isIgnorable(UO->getSubExpr()); + } + + // It's also OK to call any function or method which is annotated with + // MOZ_MAY_CALL_AFTER_MUST_RETURN. We consider all CXXConversionDecls + // to be MOZ_MAY_CALL_AFTER_MUST_RETURN (like operator T*()). + if (auto CE = dyn_cast<CallExpr>(AfterTrivials)) { + auto Callee = CE->getDirectCallee(); + if (Callee && hasCustomAttribute<moz_may_call_after_must_return>(Callee)) { + return true; + } + + if (Callee && isa<CXXConversionDecl>(Callee)) { + return true; + } + } + return false; +} + +bool MustReturnFromCallerChecker::immediatelyReturns( + RecurseGuard<const CFGBlock *> Block, ASTContext *TheContext, + size_t FromIdx) { + if (Block.isRepeat()) { + return false; + } + + for (size_t I = FromIdx; I < Block->size(); ++I) { + auto S = (*Block)[I].getAs<CFGStmt>(); + if (!S) { + continue; + } + + // Some statements should be ignored by default due to their CFG context. + if (isIgnorable(S->getStmt())) { + continue; + } + + // Otherwise, this expression is problematic. + return false; + } + + for (auto Succ = Block->succ_begin(); Succ != Block->succ_end(); ++Succ) { + if (!immediatelyReturns(Block.recurse(*Succ), TheContext, 0)) { + return false; + } + } + return true; +} diff --git a/build/clang-plugin/MustReturnFromCallerChecker.h b/build/clang-plugin/MustReturnFromCallerChecker.h new file mode 100644 index 0000000000..68630bf7a7 --- /dev/null +++ b/build/clang-plugin/MustReturnFromCallerChecker.h @@ -0,0 +1,27 @@ +/* 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/. */ + +#ifndef MustReturnFromCallerChecker_h__ +#define MustReturnFromCallerChecker_h__ + +#include "RecurseGuard.h" +#include "StmtToBlockMap.h" +#include "Utils.h" +#include "plugin.h" + +class MustReturnFromCallerChecker : public BaseCheck { +public: + MustReturnFromCallerChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; + +private: + bool isIgnorable(const Stmt *S); + bool immediatelyReturns(RecurseGuard<const CFGBlock *> Block, + ASTContext *TheContext, size_t FromIdx); +}; + +#endif diff --git a/build/clang-plugin/NaNExprChecker.cpp b/build/clang-plugin/NaNExprChecker.cpp new file mode 100644 index 0000000000..bacebc9155 --- /dev/null +++ b/build/clang-plugin/NaNExprChecker.cpp @@ -0,0 +1,54 @@ +/* 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 "NaNExprChecker.h" +#include "CustomMatchers.h" + +void NaNExprChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + binaryOperator( + allOf(binaryEqualityOperator(), + hasLHS(has(ignoringParenImpCasts( + declRefExpr(hasType(qualType((isFloat())))).bind("lhs")))), + hasRHS(has(ignoringParenImpCasts( + declRefExpr(hasType(qualType((isFloat())))).bind("rhs")))), + unless(anyOf(isInSystemHeader(), isInWhitelistForNaNExpr())))) + .bind("node"), + this); +} + +void NaNExprChecker::check(const MatchFinder::MatchResult &Result) { + if (!Result.Context->getLangOpts().CPlusPlus) { + return; + } + + const BinaryOperator *Expression = + Result.Nodes.getNodeAs<BinaryOperator>("node"); + const DeclRefExpr *LHS = Result.Nodes.getNodeAs<DeclRefExpr>("lhs"); + const DeclRefExpr *RHS = Result.Nodes.getNodeAs<DeclRefExpr>("rhs"); + const ImplicitCastExpr *LHSExpr = + dyn_cast<ImplicitCastExpr>(Expression->getLHS()); + const ImplicitCastExpr *RHSExpr = + dyn_cast<ImplicitCastExpr>(Expression->getRHS()); + // The AST subtree that we are looking for will look like this: + // -BinaryOperator ==/!= + // |-ImplicitCastExpr LValueToRValue + // | |-DeclRefExpr + // |-ImplicitCastExpr LValueToRValue + // |-DeclRefExpr + // The check below ensures that we are dealing with the correct AST subtree + // shape, and + // also that both of the found DeclRefExpr's point to the same declaration. + if (LHS->getFoundDecl() == RHS->getFoundDecl() && LHSExpr && RHSExpr && + std::distance(LHSExpr->child_begin(), LHSExpr->child_end()) == 1 && + std::distance(RHSExpr->child_begin(), RHSExpr->child_end()) == 1 && + *LHSExpr->child_begin() == LHS && *RHSExpr->child_begin() == RHS) { + diag(Expression->getBeginLoc(), + "comparing a floating point value to itself for " + "NaN checking can lead to incorrect results", + DiagnosticIDs::Error); + diag(Expression->getBeginLoc(), "consider using std::isnan instead", + DiagnosticIDs::Note); + } +} diff --git a/build/clang-plugin/NaNExprChecker.h b/build/clang-plugin/NaNExprChecker.h new file mode 100644 index 0000000000..313c3cb4cc --- /dev/null +++ b/build/clang-plugin/NaNExprChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef NaNExprChecker_h__ +#define NaNExprChecker_h__ + +#include "plugin.h" + +class NaNExprChecker : public BaseCheck { +public: + NaNExprChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NeedsNoVTableTypeChecker.cpp b/build/clang-plugin/NeedsNoVTableTypeChecker.cpp new file mode 100644 index 0000000000..9d5ad039ba --- /dev/null +++ b/build/clang-plugin/NeedsNoVTableTypeChecker.cpp @@ -0,0 +1,39 @@ +/* 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 "NeedsNoVTableTypeChecker.h" +#include "CustomMatchers.h" + +void NeedsNoVTableTypeChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + classTemplateSpecializationDecl( + allOf(hasAnyTemplateArgument(refersToType(hasVTable())), + hasNeedsNoVTableTypeAttr())) + .bind("node"), + this); +} + +void NeedsNoVTableTypeChecker::check(const MatchFinder::MatchResult &Result) { + const ClassTemplateSpecializationDecl *Specialization = + Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("node"); + + // Get the offending template argument + QualType Offender; + const TemplateArgumentList &Args = + Specialization->getTemplateInstantiationArgs(); + for (unsigned i = 0; i < Args.size(); ++i) { + Offender = Args[i].getAsType(); + if (typeHasVTable(Offender)) { + break; + } + } + + diag(Specialization->getBeginLoc(), + "%0 cannot be instantiated because %1 has a VTable", + DiagnosticIDs::Error) + << Specialization << Offender; + diag(Specialization->getPointOfInstantiation(), + "bad instantiation of %0 requested here", DiagnosticIDs::Note) + << Specialization; +} diff --git a/build/clang-plugin/NeedsNoVTableTypeChecker.h b/build/clang-plugin/NeedsNoVTableTypeChecker.h new file mode 100644 index 0000000000..abff4d1554 --- /dev/null +++ b/build/clang-plugin/NeedsNoVTableTypeChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef NeedsNoVTableTypeChecker_h__ +#define NeedsNoVTableTypeChecker_h__ + +#include "plugin.h" + +class NeedsNoVTableTypeChecker : public BaseCheck { +public: + NeedsNoVTableTypeChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NoAddRefReleaseOnReturnChecker.cpp b/build/clang-plugin/NoAddRefReleaseOnReturnChecker.cpp new file mode 100644 index 0000000000..e1c38fa6b2 --- /dev/null +++ b/build/clang-plugin/NoAddRefReleaseOnReturnChecker.cpp @@ -0,0 +1,32 @@ +/* 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 "NoAddRefReleaseOnReturnChecker.h" +#include "CustomMatchers.h" + +void NoAddRefReleaseOnReturnChecker::registerMatchers(MatchFinder *AstMatcher) { + // Look for all of the calls to AddRef() or Release() + AstMatcher->addMatcher( + memberExpr(isAddRefOrRelease(), hasParent(callExpr())).bind("member"), + this); +} + +void NoAddRefReleaseOnReturnChecker::check( + const MatchFinder::MatchResult &Result) { + const MemberExpr *Member = Result.Nodes.getNodeAs<MemberExpr>("member"); + const Expr *Base = IgnoreTrivials(Member->getBase()); + + // Check if the call to AddRef() or Release() was made on the result of a call + // to a MOZ_NO_ADDREF_RELEASE_ON_RETURN function or method. + if (auto *Call = dyn_cast<CallExpr>(Base)) { + if (auto *Callee = Call->getDirectCallee()) { + if (hasCustomAttribute<moz_no_addref_release_on_return>(Callee)) { + diag(Call->getBeginLoc(), + "%1 must not be called on the return value of '%0' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN", + DiagnosticIDs::Error) + << Callee->getQualifiedNameAsString() << dyn_cast<CXXMethodDecl>(Member->getMemberDecl()); + } + } + } +} diff --git a/build/clang-plugin/NoAddRefReleaseOnReturnChecker.h b/build/clang-plugin/NoAddRefReleaseOnReturnChecker.h new file mode 100644 index 0000000000..525f769eff --- /dev/null +++ b/build/clang-plugin/NoAddRefReleaseOnReturnChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NoAddRefReleaseOnReturnChecker_h__ +#define NoAddRefReleaseOnReturnChecker_h__ + +#include "plugin.h" + +class NoAddRefReleaseOnReturnChecker : public BaseCheck { +public: + NoAddRefReleaseOnReturnChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NoAutoTypeChecker.cpp b/build/clang-plugin/NoAutoTypeChecker.cpp new file mode 100644 index 0000000000..937c7c5742 --- /dev/null +++ b/build/clang-plugin/NoAutoTypeChecker.cpp @@ -0,0 +1,21 @@ +/* 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 "NoAutoTypeChecker.h" +#include "CustomMatchers.h" + +void NoAutoTypeChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"), + this); +} + +void NoAutoTypeChecker::check(const MatchFinder::MatchResult &Result) { + const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node"); + + diag(D->getLocation(), "Cannot use auto to declare a variable of type %0", + DiagnosticIDs::Error) + << D->getType(); + diag(D->getLocation(), "Please write out this type explicitly", + DiagnosticIDs::Note); +} diff --git a/build/clang-plugin/NoAutoTypeChecker.h b/build/clang-plugin/NoAutoTypeChecker.h new file mode 100644 index 0000000000..0801503846 --- /dev/null +++ b/build/clang-plugin/NoAutoTypeChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef NoAutoTypeChecker_h__ +#define NoAutoTypeChecker_h__ + +#include "plugin.h" + +class NoAutoTypeChecker : public BaseCheck { +public: + NoAutoTypeChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NoDuplicateRefCntMemberChecker.cpp b/build/clang-plugin/NoDuplicateRefCntMemberChecker.cpp new file mode 100644 index 0000000000..eb78a3bd49 --- /dev/null +++ b/build/clang-plugin/NoDuplicateRefCntMemberChecker.cpp @@ -0,0 +1,65 @@ +/* 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 "NoDuplicateRefCntMemberChecker.h" +#include "CustomMatchers.h" + +void NoDuplicateRefCntMemberChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(cxxRecordDecl().bind("decl"), this); +} + +void NoDuplicateRefCntMemberChecker::check( + const MatchFinder::MatchResult &Result) { + const CXXRecordDecl *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl"); + const FieldDecl *RefCntMember = getClassRefCntMember(D); + const FieldDecl *FoundRefCntBase = nullptr; + + if (!D->hasDefinition()) + return; + D = D->getDefinition(); + + // If we don't have an mRefCnt member, and we have less than 2 superclasses, + // we don't have to run this loop, as neither case will ever apply. + if (!RefCntMember && D->getNumBases() < 2) { + return; + } + + // Check every superclass for whether it has a base with a refcnt member, and + // warn for those which do + for (auto &Base : D->bases()) { + // Determine if this base class has an mRefCnt member + const FieldDecl *BaseRefCntMember = getBaseRefCntMember(Base.getType()); + + if (BaseRefCntMember) { + if (RefCntMember) { + // We have an mRefCnt, and superclass has an mRefCnt + const char *Error = "Refcounted record %0 has multiple mRefCnt members"; + const char *Note1 = "Superclass %0 also has an mRefCnt member"; + const char *Note2 = + "Consider using the _INHERITED macros for AddRef and Release here"; + + diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D; + diag(BaseRefCntMember->getBeginLoc(), Note1, DiagnosticIDs::Note) + << BaseRefCntMember->getParent(); + diag(RefCntMember->getBeginLoc(), Note2, DiagnosticIDs::Note); + } + + if (FoundRefCntBase) { + const char *Error = "Refcounted record %0 has multiple superclasses " + "with mRefCnt members"; + const char *Note = "Superclass %0 has an mRefCnt member"; + + // superclass has mRefCnt, and another superclass also has an mRefCnt + diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << D; + diag(BaseRefCntMember->getBeginLoc(), Note, DiagnosticIDs::Note) + << BaseRefCntMember->getParent(); + diag(FoundRefCntBase->getBeginLoc(), Note, DiagnosticIDs::Note) + << FoundRefCntBase->getParent(); + } + + // Record that we've found a base with a mRefCnt member + FoundRefCntBase = BaseRefCntMember; + } + } +} diff --git a/build/clang-plugin/NoDuplicateRefCntMemberChecker.h b/build/clang-plugin/NoDuplicateRefCntMemberChecker.h new file mode 100644 index 0000000000..e038ca873b --- /dev/null +++ b/build/clang-plugin/NoDuplicateRefCntMemberChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NoDuplicateRefCntMemberChecker_h__ +#define NoDuplicateRefCntMemberChecker_h__ + +#include "plugin.h" + +class NoDuplicateRefCntMemberChecker : public BaseCheck { +public: + NoDuplicateRefCntMemberChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp b/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp new file mode 100644 index 0000000000..69e324dee3 --- /dev/null +++ b/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp @@ -0,0 +1,25 @@ +/* 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 "NoExplicitMoveConstructorChecker.h" +#include "CustomMatchers.h" + +void NoExplicitMoveConstructorChecker::registerMatchers( + MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxConstructorDecl(isExplicitMoveConstructor(), isFirstParty()) + .bind("node"), + this); +} + +void NoExplicitMoveConstructorChecker::check( + const MatchFinder::MatchResult &Result) { + // Everything we needed to know was checked in the matcher - we just report + // the error here + const CXXConstructorDecl *D = + Result.Nodes.getNodeAs<CXXConstructorDecl>("node"); + + diag(D->getLocation(), "Move constructors may not be marked explicit", + DiagnosticIDs::Error); +} diff --git a/build/clang-plugin/NoExplicitMoveConstructorChecker.h b/build/clang-plugin/NoExplicitMoveConstructorChecker.h new file mode 100644 index 0000000000..adc474c144 --- /dev/null +++ b/build/clang-plugin/NoExplicitMoveConstructorChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NoExplicitMoveConstructorChecker_h__ +#define NoExplicitMoveConstructorChecker_h__ + +#include "plugin.h" + +class NoExplicitMoveConstructorChecker : public BaseCheck { +public: + NoExplicitMoveConstructorChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NoNewThreadsChecker.cpp b/build/clang-plugin/NoNewThreadsChecker.cpp new file mode 100644 index 0000000000..90c190f8d1 --- /dev/null +++ b/build/clang-plugin/NoNewThreadsChecker.cpp @@ -0,0 +1,36 @@ +/* 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 "NoNewThreadsChecker.h" +#include "CustomMatchers.h" + +void NoNewThreadsChecker::registerMatchers(MatchFinder *AstMatcher) { + // The checker looks for: + // -Instances of NS_NewNamedThread that aren't in allowed files + // -Instances of NS_NewNamedThread that use names that aren't recognized + AstMatcher->addMatcher( + callExpr(allOf(isFirstParty(), + callee(functionDecl(hasName("NS_NewNamedThread"))), + unless(isInAllowlistForThreads()))) + .bind("funcCall"), + this); +} + +void NoNewThreadsChecker::check(const MatchFinder::MatchResult &Result) { + const CallExpr *FuncCall = Result.Nodes.getNodeAs<CallExpr>("funcCall"); + + if (FuncCall) { + diag(FuncCall->getBeginLoc(), + "Thread name not recognized. Please use the background thread pool.", + DiagnosticIDs::Error) + << FuncCall->getDirectCallee()->getName(); + diag( + FuncCall->getBeginLoc(), + "NS_NewNamedThread has been deprecated in favor of background " + "task dispatch via NS_DispatchBackgroundTask and " + "NS_CreateBackgroundTaskQueue. If you must create a new ad-hoc thread, " + "have your thread name added to ThreadAllows.txt.", + DiagnosticIDs::Note); + } +} diff --git a/build/clang-plugin/NoNewThreadsChecker.h b/build/clang-plugin/NoNewThreadsChecker.h new file mode 100644 index 0000000000..e8dc13fece --- /dev/null +++ b/build/clang-plugin/NoNewThreadsChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef NoNewThreadsChecker_h__ +#define NoNewThreadsChecker_h__ + +#include "plugin.h" + +class NoNewThreadsChecker : public BaseCheck { +public: + NoNewThreadsChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif // !defined(NoNewThreadsChecker_h__) diff --git a/build/clang-plugin/NoPrincipalGetURI.cpp b/build/clang-plugin/NoPrincipalGetURI.cpp new file mode 100644 index 0000000000..60e22abeb5 --- /dev/null +++ b/build/clang-plugin/NoPrincipalGetURI.cpp @@ -0,0 +1,27 @@ +/* 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 "NoPrincipalGetURI.h" +#include "CustomMatchers.h" + +void NoPrincipalGetURI::registerMatchers(MatchFinder *AstMatcher) { + + AstMatcher->addMatcher( + cxxMemberCallExpr( + allOf(callee(cxxMethodDecl(hasName("GetURI"))), + anyOf(on(hasType(hasCanonicalType(asString("class nsIPrincipal *")))), + on(hasType(hasCanonicalType(asString("class nsIPrincipal"))))), + unless(isInWhiteListForPrincipalGetUri())), + argumentCountIs(1)) + .bind("id"), + this); +} + +void NoPrincipalGetURI::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMemberCallExpr>("id"); + diag(MatchedDecl->getExprLoc(), + "Principal->GetURI is deprecated and will be removed soon. Please " + "consider using the new helper functions of nsIPrincipal", + DiagnosticIDs::Error); +} diff --git a/build/clang-plugin/NoPrincipalGetURI.h b/build/clang-plugin/NoPrincipalGetURI.h new file mode 100644 index 0000000000..2b39b74bed --- /dev/null +++ b/build/clang-plugin/NoPrincipalGetURI.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef NoPrincipalGetURI_h__ +#define NoPrincipalGetURI_h__ + +#include "plugin.h" + +class NoPrincipalGetURI : public BaseCheck { +public: + NoPrincipalGetURI(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NoUsingNamespaceMozillaJavaChecker.cpp b/build/clang-plugin/NoUsingNamespaceMozillaJavaChecker.cpp new file mode 100644 index 0000000000..20449dba92 --- /dev/null +++ b/build/clang-plugin/NoUsingNamespaceMozillaJavaChecker.cpp @@ -0,0 +1,24 @@ +/* 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 "NoUsingNamespaceMozillaJavaChecker.h" +#include "CustomMatchers.h" + +void NoUsingNamespaceMozillaJavaChecker::registerMatchers( + MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + usingDirectiveDecl(isUsingNamespaceMozillaJava()).bind("directive"), + this); +} + +void NoUsingNamespaceMozillaJavaChecker::check( + const MatchFinder::MatchResult &Result) { + const UsingDirectiveDecl *Directive = + Result.Nodes.getNodeAs<UsingDirectiveDecl>("directive"); + const NamespaceDecl *Namespace = Directive->getNominatedNamespace(); + + diag(Directive->getUsingLoc(), "using namespace %0 is forbidden", + DiagnosticIDs::Error) + << Namespace->getQualifiedNameAsString(); +} diff --git a/build/clang-plugin/NoUsingNamespaceMozillaJavaChecker.h b/build/clang-plugin/NoUsingNamespaceMozillaJavaChecker.h new file mode 100644 index 0000000000..7b68ba9333 --- /dev/null +++ b/build/clang-plugin/NoUsingNamespaceMozillaJavaChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NoUsingNamespaceMozillaJavaChecker_h__ +#define NoUsingNamespaceMozillaJavaChecker_h__ + +#include "plugin.h" + +class NoUsingNamespaceMozillaJavaChecker : public BaseCheck { +public: + NoUsingNamespaceMozillaJavaChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NonMemMovableMemberChecker.cpp b/build/clang-plugin/NonMemMovableMemberChecker.cpp new file mode 100644 index 0000000000..232c634534 --- /dev/null +++ b/build/clang-plugin/NonMemMovableMemberChecker.cpp @@ -0,0 +1,34 @@ +/* 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 "NonMemMovableMemberChecker.h" +#include "CustomMatchers.h" + +MemMoveAnnotation NonMemMovable = MemMoveAnnotation(); + +void NonMemMovableMemberChecker::registerMatchers(MatchFinder *AstMatcher) { + // Handle non-mem-movable members + AstMatcher->addMatcher(cxxRecordDecl(needsMemMovableMembers()).bind("decl"), + this); +} + +void NonMemMovableMemberChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = + "class %0 cannot have non-memmovable member %1 of type %2"; + + // Get the specialization + const CXXRecordDecl *Declaration = + Result.Nodes.getNodeAs<CXXRecordDecl>("decl"); + + // Report an error for every member which is non-memmovable + for (const FieldDecl *Field : Declaration->fields()) { + QualType Type = Field->getType(); + if (NonMemMovable.hasEffectiveAnnotation(Type)) { + diag(Field->getLocation(), Error, DiagnosticIDs::Error) + << Declaration << Field << Type; + NonMemMovable.dumpAnnotationReason(*this, Type, + Declaration->getLocation()); + } + } +} diff --git a/build/clang-plugin/NonMemMovableMemberChecker.h b/build/clang-plugin/NonMemMovableMemberChecker.h new file mode 100644 index 0000000000..0fc9b1f87f --- /dev/null +++ b/build/clang-plugin/NonMemMovableMemberChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NonMemMovableMemberChecker_h__ +#define NonMemMovableMemberChecker_h__ + +#include "plugin.h" + +class NonMemMovableMemberChecker : public BaseCheck { +public: + NonMemMovableMemberChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NonMemMovableTemplateArgChecker.cpp b/build/clang-plugin/NonMemMovableTemplateArgChecker.cpp new file mode 100644 index 0000000000..65afe21006 --- /dev/null +++ b/build/clang-plugin/NonMemMovableTemplateArgChecker.cpp @@ -0,0 +1,51 @@ +/* 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 "NonMemMovableTemplateArgChecker.h" +#include "CustomMatchers.h" + +void NonMemMovableTemplateArgChecker::registerMatchers( + MatchFinder *AstMatcher) { + // Handle non-mem-movable template specializations + AstMatcher->addMatcher( + classTemplateSpecializationDecl( + allOf(needsMemMovableTemplateArg(), + hasAnyTemplateArgument(refersToType(isNonMemMovable())))) + .bind("specialization"), + this); +} + +void NonMemMovableTemplateArgChecker::check( + const MatchFinder::MatchResult &Result) { + const char *Error = + "Cannot instantiate %0 with non-memmovable template argument %1"; + const char *Note = "instantiation of %0 requested here"; + + // Get the specialization + const ClassTemplateSpecializationDecl *Specialization = + Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization"); + SourceLocation RequestLoc = Specialization->getPointOfInstantiation(); + + // Report an error for every template argument which is non-memmovable + const TemplateArgumentList &Args = + Specialization->getTemplateInstantiationArgs(); + for (unsigned i = 0; i < Args.size(); ++i) { + QualType ArgType = Args[i].getAsType(); + if (NonMemMovable.hasEffectiveAnnotation(ArgType)) { + diag(Specialization->getLocation(), Error, DiagnosticIDs::Error) + << Specialization << ArgType; + // XXX It would be really nice if we could get the instantiation stack + // information + // from Sema such that we could print a full template instantiation stack, + // however, + // it seems as though that information is thrown out by the time we get + // here so we + // can only report one level of template specialization (which in many + // cases won't + // be useful) + diag(RequestLoc, Note, DiagnosticIDs::Note) << Specialization; + NonMemMovable.dumpAnnotationReason(*this, ArgType, RequestLoc); + } + } +} diff --git a/build/clang-plugin/NonMemMovableTemplateArgChecker.h b/build/clang-plugin/NonMemMovableTemplateArgChecker.h new file mode 100644 index 0000000000..cd94c95930 --- /dev/null +++ b/build/clang-plugin/NonMemMovableTemplateArgChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NonMemMovableTemplateArgChecker_h__ +#define NonMemMovableTemplateArgChecker_h__ + +#include "plugin.h" + +class NonMemMovableTemplateArgChecker : public BaseCheck { +public: + NonMemMovableTemplateArgChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp b/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp new file mode 100644 index 0000000000..e74fd2bb08 --- /dev/null +++ b/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp @@ -0,0 +1,217 @@ +/* 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 "NonParamInsideFunctionDeclChecker.h" +#include "CustomMatchers.h" +#include "clang/Basic/TargetInfo.h" + +class NonParamAnnotation : public CustomTypeAnnotation { +public: + NonParamAnnotation() : CustomTypeAnnotation(moz_non_param, "non-param"){}; + +protected: + // Helper for checking if a Decl has an explicitly specified alignment. + // Returns the alignment, in char units, of the largest alignment attribute, + // if it exceeds pointer alignment, and 0 otherwise. + static unsigned checkExplicitAlignment(const Decl *D) { + ASTContext &Context = D->getASTContext(); +#if CLANG_VERSION_FULL >= 1600 + unsigned PointerAlign = Context.getTargetInfo().getPointerAlign(LangAS::Default); +#else + unsigned PointerAlign = Context.getTargetInfo().getPointerAlign(0); +#endif + + // getMaxAlignment gets the largest alignment, in bits, specified by an + // alignment attribute directly on the declaration. If no alignment + // attribute is specified, it will return `0`. + unsigned MaxAlign = D->getMaxAlignment(); + if (MaxAlign > PointerAlign) { + return Context.toCharUnitsFromBits(MaxAlign).getQuantity(); + } + return 0; + } + + // This is directly derived from the logic in Clang's `canPassInRegisters` + // function, from `SemaDeclCXX`. It is used instead of `canPassInRegisters` to + // behave consistently on 64-bit windows platforms which are overly + // permissive, allowing too many types to be passed in registers. + // + // Types which can be passed in registers will be re-aligned in the called + // function by clang, so aren't impacted by the win32 object passing ABI + // alignment issue. + static bool canPassAsTemporary(const CXXRecordDecl *D) { + // Per C++ [class.temporary]p3: + // + // When an object of class type X is passed to or returned from a function, + // if X has at least one eligible copy or move constructor ([special]), each + // such constructor is trivial, and the destructor of X is either trivial or + // deleted, implementations are permitted to create a temporary object to + // hold the function parameter or result object. + // + // The temporary object is constructed from the function argument or return + // value, respectively, and the function's parameter or return object is + // initialized as if by using the eligible trivial constructor to copy the + // temporary (even if that constructor is inaccessible or would not be + // selected by overload resolution to perform a copy or move of the object). + bool HasNonDeletedCopyOrMove = false; + + if (D->needsImplicitCopyConstructor() && + !D->defaultedCopyConstructorIsDeleted()) { + if (!D->hasTrivialCopyConstructorForCall()) + return false; + HasNonDeletedCopyOrMove = true; + } + + if (D->needsImplicitMoveConstructor() && + !D->defaultedMoveConstructorIsDeleted()) { + if (!D->hasTrivialMoveConstructorForCall()) + return false; + HasNonDeletedCopyOrMove = true; + } + + if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() && + !D->hasTrivialDestructorForCall()) + return false; + + for (const CXXMethodDecl *MD : D->methods()) { + if (MD->isDeleted()) + continue; + + auto *CD = dyn_cast<CXXConstructorDecl>(MD); + if (CD && CD->isCopyOrMoveConstructor()) + HasNonDeletedCopyOrMove = true; + else if (!isa<CXXDestructorDecl>(MD)) + continue; + + if (!MD->isTrivialForCall()) + return false; + } + + return HasNonDeletedCopyOrMove; + } + + // Adding alignas(_) on a struct implicitly marks it as MOZ_NON_PARAM, due to + // MSVC limitations which prevent passing explcitly aligned types by value as + // parameters. This overload of hasFakeAnnotation injects fake MOZ_NON_PARAM + // annotations onto these types. + std::string getImplicitReason(const TagDecl *D, + VisitFlags &ToVisit) const override { + // Some stdlib types are known to have alignments over the pointer size on + // non-win32 platforms, but should not be linted against. Clear any + // annotations on those types. + if (!D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() && + getDeclarationNamespace(D) == "std") { + StringRef Name = getNameChecked(D); + if (Name == "function") { + ToVisit = VISIT_NONE; + return ""; + } + } + + // If the type doesn't have a destructor and can be passed with a temporary, + // clang will handle re-aligning it for us automatically, and we don't need + // to worry about the passed alignment. + auto RD = dyn_cast<CXXRecordDecl>(D); + if (RD && RD->isCompleteDefinition() && canPassAsTemporary(RD)) { + return ""; + } + + // Check if the decl itself has an explicit alignment on it. + if (unsigned ExplicitAlign = checkExplicitAlignment(D)) { + return "it has an explicit alignment of '" + + std::to_string(ExplicitAlign) + "'"; + } + + // Check if any of the decl's fields have an explicit alignment on them. + if (auto RD = dyn_cast<RecordDecl>(D)) { + for (auto F : RD->fields()) { + if (unsigned ExplicitAlign = checkExplicitAlignment(F)) { + return ("member '" + F->getName() + + "' has an explicit alignment of '" + + std::to_string(ExplicitAlign) + "'") + .str(); + } + } + } + + // We don't need to check the types of fields, as the CustomTypeAnnotation + // infrastructure will handle that for us. + return ""; + } +}; +NonParamAnnotation NonParam; + +void NonParamInsideFunctionDeclChecker::registerMatchers( + MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + functionDecl( + anyOf(allOf(isDefinition(), + hasAncestor( + classTemplateSpecializationDecl().bind("spec"))), + isDefinition())) + .bind("func"), + this); + AstMatcher->addMatcher(lambdaExpr().bind("lambda"), this); +} + +void NonParamInsideFunctionDeclChecker::check( + const MatchFinder::MatchResult &Result) { + static DenseSet<const FunctionDecl *> CheckedFunctionDecls; + + const FunctionDecl *func = Result.Nodes.getNodeAs<FunctionDecl>("func"); + if (!func) { + const LambdaExpr *lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); + if (lambda) { + func = lambda->getCallOperator(); + } + } + + if (!func) { + return; + } + + if (func->isDeleted()) { + return; + } + + // We need to skip decls which have these types as parameters in system + // headers, because presumably those headers act like an assertion that the + // alignment will be preserved in that situation. + if (getDeclarationNamespace(func) == "std") { + return; + } + + if (inThirdPartyPath(func)) { + return; + } + + // Don't report errors on the same declarations more than once. + if (CheckedFunctionDecls.count(func)) { + return; + } + CheckedFunctionDecls.insert(func); + + const ClassTemplateSpecializationDecl *Spec = + Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("spec"); + + for (ParmVarDecl *p : func->parameters()) { + QualType T = p->getType().withoutLocalFastQualifiers(); + if (NonParam.hasEffectiveAnnotation(T)) { + diag(p->getLocation(), "Type %0 must not be used as parameter", + DiagnosticIDs::Error) + << T; + diag(p->getLocation(), + "Please consider passing a const reference instead", + DiagnosticIDs::Note); + + if (Spec) { + diag(Spec->getPointOfInstantiation(), + "The bad argument was passed to %0 here", DiagnosticIDs::Note) + << Spec->getSpecializedTemplate(); + } + + NonParam.dumpAnnotationReason(*this, T, p->getLocation()); + } + } +} diff --git a/build/clang-plugin/NonParamInsideFunctionDeclChecker.h b/build/clang-plugin/NonParamInsideFunctionDeclChecker.h new file mode 100644 index 0000000000..ed11f3fe12 --- /dev/null +++ b/build/clang-plugin/NonParamInsideFunctionDeclChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NonParamInsideFunctionDeclChecker_h__ +#define NonParamInsideFunctionDeclChecker_h__ + +#include "plugin.h" + +class NonParamInsideFunctionDeclChecker : public BaseCheck { +public: + NonParamInsideFunctionDeclChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/NonTrivialTypeInFfiChecker.cpp b/build/clang-plugin/NonTrivialTypeInFfiChecker.cpp new file mode 100644 index 0000000000..f482fb131f --- /dev/null +++ b/build/clang-plugin/NonTrivialTypeInFfiChecker.cpp @@ -0,0 +1,56 @@ +/* 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 "NonTrivialTypeInFfiChecker.h" +#include "CustomMatchers.h" + +void NonTrivialTypeInFfiChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(functionDecl(isExternC()).bind("func"), this); +} + +void NonTrivialTypeInFfiChecker::check(const MatchFinder::MatchResult &Result) { + static DenseSet<const FunctionDecl *> CheckedFunctionDecls; + + const FunctionDecl *func = Result.Nodes.getNodeAs<FunctionDecl>("func"); + // Don't report errors on the same declarations more than once. + if (!CheckedFunctionDecls.insert(func).second) { + return; + } + + if (inThirdPartyPath(func)) { + return; + } + + auto NoteFor = [](const QualType &T) -> std::string { + std::string s = "Please consider using a pointer or reference"; + if (T->getAs<TemplateSpecializationType>()) { + s += ", or explicitly instantiating the template"; + } + return s + " instead"; + }; + + for (ParmVarDecl *p : func->parameters()) { + QualType T = p->getType().getUnqualifiedType(); + if (!T->isVoidType() && !T->isReferenceType() && + !T.isTriviallyCopyableType(*Result.Context)) { + diag(p->getLocation(), + "Type %0 must not be used as parameter to extern " + "\"C\" function", + DiagnosticIDs::Error) + << T; + diag(p->getLocation(), NoteFor(T), DiagnosticIDs::Note); + } + } + + QualType T = func->getReturnType().getUnqualifiedType(); + if (!T->isVoidType() && !T->isReferenceType() && + !T.isTriviallyCopyableType(*Result.Context)) { + diag(func->getLocation(), + "Type %0 must not be used as return type of " + "extern \"C\" function", + DiagnosticIDs::Error) + << T; + diag(func->getLocation(), NoteFor(T), DiagnosticIDs::Note); + } +} diff --git a/build/clang-plugin/NonTrivialTypeInFfiChecker.h b/build/clang-plugin/NonTrivialTypeInFfiChecker.h new file mode 100644 index 0000000000..106c64c021 --- /dev/null +++ b/build/clang-plugin/NonTrivialTypeInFfiChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef NonTrivialTypeInFfiChecker_h__ +#define NonTrivialTypeInFfiChecker_h__ + +#include "plugin.h" + +class NonTrivialTypeInFfiChecker : public BaseCheck { +public: + NonTrivialTypeInFfiChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/OverrideBaseCallChecker.cpp b/build/clang-plugin/OverrideBaseCallChecker.cpp new file mode 100644 index 0000000000..600d431335 --- /dev/null +++ b/build/clang-plugin/OverrideBaseCallChecker.cpp @@ -0,0 +1,109 @@ +/* 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 "OverrideBaseCallChecker.h" +#include "CustomMatchers.h" + +void OverrideBaseCallChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(cxxRecordDecl(hasBaseClasses()).bind("class"), this); +} + +bool OverrideBaseCallChecker::isRequiredBaseMethod( + const CXXMethodDecl *Method) { + return hasCustomAttribute<moz_required_base_method>(Method); +} + +void OverrideBaseCallChecker::evaluateExpression( + const Stmt *StmtExpr, std::list<const CXXMethodDecl *> &MethodList) { + // Continue while we have methods in our list + if (!MethodList.size()) { + return; + } + + if (auto MemberFuncCall = dyn_cast<CXXMemberCallExpr>(StmtExpr)) { + if (auto Method = + dyn_cast<CXXMethodDecl>(MemberFuncCall->getDirectCallee())) { + findBaseMethodCall(Method, MethodList); + } + } + + for (auto S : StmtExpr->children()) { + if (S) { + evaluateExpression(S, MethodList); + } + } +} + +void OverrideBaseCallChecker::getRequiredBaseMethod( + const CXXMethodDecl *Method, + std::list<const CXXMethodDecl *> &MethodsList) { + + if (isRequiredBaseMethod(Method)) { + MethodsList.push_back(Method); + } else { + // Loop through all it's base methods. + for (auto BaseMethod = Method->begin_overridden_methods(); + BaseMethod != Method->end_overridden_methods(); BaseMethod++) { + getRequiredBaseMethod(*BaseMethod, MethodsList); + } + } +} + +void OverrideBaseCallChecker::findBaseMethodCall( + const CXXMethodDecl *Method, + std::list<const CXXMethodDecl *> &MethodsList) { + + MethodsList.remove(Method); + // Loop also through all it's base methods; + for (auto BaseMethod = Method->begin_overridden_methods(); + BaseMethod != Method->end_overridden_methods(); BaseMethod++) { + findBaseMethodCall(*BaseMethod, MethodsList); + } +} + +void OverrideBaseCallChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = + "Method %0 must be called in all overrides, but is not called in " + "this override defined for class %1"; + const CXXRecordDecl *Decl = Result.Nodes.getNodeAs<CXXRecordDecl>("class"); + + // Loop through the methods and look for the ones that are overridden. + for (auto Method : Decl->methods()) { + // If this method doesn't override other methods or it doesn't have a body, + // continue to the next declaration. + if (!Method->size_overridden_methods() || !Method->hasBody()) { + continue; + } + + // Preferred the usage of list instead of vector in order to avoid + // calling erase-remove when deleting items + std::list<const CXXMethodDecl *> MethodsList; + // For each overridden method push it to a list if it meets our + // criteria + for (auto BaseMethod = Method->begin_overridden_methods(); + BaseMethod != Method->end_overridden_methods(); BaseMethod++) { + getRequiredBaseMethod(*BaseMethod, MethodsList); + } + + // If no method has been found then no annotation was used + // so checking is not needed + if (!MethodsList.size()) { + continue; + } + + // Loop through the body of our method and search for calls to + // base methods + evaluateExpression(Method->getBody(), MethodsList); + + // If list is not empty pop up errors + for (auto BaseMethod : MethodsList) { + std::string QualName; + raw_string_ostream OS(QualName); + BaseMethod->printQualifiedName(OS); + + diag(Method->getLocation(), Error, DiagnosticIDs::Error) + << OS.str() << Decl->getName(); + } + } +} diff --git a/build/clang-plugin/OverrideBaseCallChecker.h b/build/clang-plugin/OverrideBaseCallChecker.h new file mode 100644 index 0000000000..e919af6749 --- /dev/null +++ b/build/clang-plugin/OverrideBaseCallChecker.h @@ -0,0 +1,27 @@ +/* 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/. */ + +#ifndef OverrideBaseCallChecker_h__ +#define OverrideBaseCallChecker_h__ + +#include "plugin.h" + +class OverrideBaseCallChecker : public BaseCheck { +public: + OverrideBaseCallChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; + +private: + void evaluateExpression(const Stmt *StmtExpr, + std::list<const CXXMethodDecl *> &MethodList); + void getRequiredBaseMethod(const CXXMethodDecl *Method, + std::list<const CXXMethodDecl *> &MethodsList); + void findBaseMethodCall(const CXXMethodDecl *Method, + std::list<const CXXMethodDecl *> &MethodsList); + bool isRequiredBaseMethod(const CXXMethodDecl *Method); +}; + +#endif diff --git a/build/clang-plugin/OverrideBaseCallUsageChecker.cpp b/build/clang-plugin/OverrideBaseCallUsageChecker.cpp new file mode 100644 index 0000000000..34b9cd16a9 --- /dev/null +++ b/build/clang-plugin/OverrideBaseCallUsageChecker.cpp @@ -0,0 +1,21 @@ +/* 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 "OverrideBaseCallUsageChecker.h" +#include "CustomMatchers.h" + +void OverrideBaseCallUsageChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxMethodDecl(isNonVirtual(), isRequiredBaseMethod()).bind("method"), + this); +} + +void OverrideBaseCallUsageChecker::check( + const MatchFinder::MatchResult &Result) { + const char *Error = + "MOZ_REQUIRED_BASE_METHOD can be used only on virtual methods"; + const CXXMethodDecl *Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method"); + + diag(Method->getLocation(), Error, DiagnosticIDs::Error); +} diff --git a/build/clang-plugin/OverrideBaseCallUsageChecker.h b/build/clang-plugin/OverrideBaseCallUsageChecker.h new file mode 100644 index 0000000000..0e81d72387 --- /dev/null +++ b/build/clang-plugin/OverrideBaseCallUsageChecker.h @@ -0,0 +1,23 @@ +/* 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/. */ + +#ifndef OverrideBaseCallUsageChecker_h__ +#define OverrideBaseCallUsageChecker_h__ + +#include "plugin.h" + +/* + * This is a companion checker for OverrideBaseCallChecker that rejects + * the usage of MOZ_REQUIRED_BASE_METHOD on non-virtual base methods. + */ +class OverrideBaseCallUsageChecker : public BaseCheck { +public: + OverrideBaseCallUsageChecker(StringRef CheckName = "override-base-call-usage", + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/ParamTraitsEnumChecker.cpp b/build/clang-plugin/ParamTraitsEnumChecker.cpp new file mode 100644 index 0000000000..7214e9fe5b --- /dev/null +++ b/build/clang-plugin/ParamTraitsEnumChecker.cpp @@ -0,0 +1,38 @@ +/* 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 "ParamTraitsEnumChecker.h" +#include "CustomMatchers.h" + +void ParamTraitsEnumChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + classTemplateSpecializationDecl(hasName("ParamTraits")).bind("decl"), + this); +} + +void ParamTraitsEnumChecker::check(const MatchFinder::MatchResult &Result) { + const ClassTemplateSpecializationDecl *Decl = + Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("decl"); + + for (auto &Inner : Decl->decls()) { + if (auto *Def = dyn_cast<TypedefDecl>(Inner)) { + QualType UnderlyingType = Def->getUnderlyingType(); + QualType CanonicalType = UnderlyingType.getCanonicalType(); + + const clang::Type *TypePtr = CanonicalType.getTypePtrOrNull(); + if (!TypePtr) { + return; + } + + if (TypePtr->isEnumeralType()) { + diag(Decl->getBeginLoc(), + "Custom ParamTraits implementation for an enum type", + DiagnosticIDs::Error); + diag(Decl->getBeginLoc(), + "Please use a helper class for example ContiguousEnumSerializer", + DiagnosticIDs::Note); + } + } + } +} diff --git a/build/clang-plugin/ParamTraitsEnumChecker.h b/build/clang-plugin/ParamTraitsEnumChecker.h new file mode 100644 index 0000000000..e89a7d2895 --- /dev/null +++ b/build/clang-plugin/ParamTraitsEnumChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef ParamTraitsEnumChecker_h__ +#define ParamTraitsEnumChecker_h__ + +#include "plugin.h" + +class ParamTraitsEnumChecker : public BaseCheck { +public: + ParamTraitsEnumChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/RecurseGuard.h b/build/clang-plugin/RecurseGuard.h new file mode 100644 index 0000000000..5daf55a9e8 --- /dev/null +++ b/build/clang-plugin/RecurseGuard.h @@ -0,0 +1,56 @@ +/* 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/. */ + +#ifndef RecurseGuard_h__ +#define RecurseGuard_h__ + +#include "Utils.h" + +// This class acts as a tracker for avoiding infinite recursion when traversing +// chains in CFGs etc. +// +// Constructing a RecurseGuard sets up a shared backing store which tracks the +// currently observed objects. Whenever recursing, use RecurseGuard.recurse(T) +// to construct another RecurseGuard with the same backing store. +// +// The RecurseGuard object will unregister its object when it is destroyed, and +// has a method `isRepeat()` which will return `true` if the item was already +// seen. +template <typename T> class RecurseGuard { +public: + RecurseGuard(T Thing) : Thing(Thing), Set(new DenseSet<T>()), Repeat(false) { + Set->insert(Thing); + } + RecurseGuard(T Thing, std::shared_ptr<DenseSet<T>> &Set) + : Thing(Thing), Set(Set), Repeat(false) { + Repeat = !Set->insert(Thing).second; + } + RecurseGuard(const RecurseGuard &) = delete; + RecurseGuard(RecurseGuard &&Other) + : Thing(Other.Thing), Set(Other.Set), Repeat(Other.Repeat) { + Other.Repeat = true; + } + ~RecurseGuard() { + if (!Repeat) { + Set->erase(Thing); + } + } + + bool isRepeat() { return Repeat; } + + T get() { return Thing; } + + operator T() { return Thing; } + + T operator->() { return Thing; } + + RecurseGuard recurse(T NewThing) { return RecurseGuard(NewThing, Set); } + +private: + T Thing; + std::shared_ptr<DenseSet<T>> Set; + bool Repeat; +}; + +#endif // RecurseGuard_h__ diff --git a/build/clang-plugin/RefCountedCopyConstructorChecker.cpp b/build/clang-plugin/RefCountedCopyConstructorChecker.cpp new file mode 100644 index 0000000000..569d4eecec --- /dev/null +++ b/build/clang-plugin/RefCountedCopyConstructorChecker.cpp @@ -0,0 +1,34 @@ +/* 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 "RefCountedCopyConstructorChecker.h" +#include "CustomMatchers.h" + +void RefCountedCopyConstructorChecker::registerMatchers( + MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxConstructExpr( + hasDeclaration(cxxConstructorDecl(isCompilerProvidedCopyConstructor(), + ofClass(hasRefCntMember())))) + .bind("node"), + this); +} + +void RefCountedCopyConstructorChecker::check( + const MatchFinder::MatchResult &Result) { + const char *Error = + "Invalid use of compiler-provided copy constructor on refcounted type"; + const char *Note = "The default copy constructor also copies the " + "default mRefCnt property, leading to reference " + "count imbalance issues. Please provide your own " + "copy constructor which only copies the fields which " + "need to be copied"; + + // Everything we needed to know was checked in the matcher - we just report + // the error here + const CXXConstructExpr *E = Result.Nodes.getNodeAs<CXXConstructExpr>("node"); + + diag(E->getLocation(), Error, DiagnosticIDs::Error); + diag(E->getLocation(), Note, DiagnosticIDs::Note); +} diff --git a/build/clang-plugin/RefCountedCopyConstructorChecker.h b/build/clang-plugin/RefCountedCopyConstructorChecker.h new file mode 100644 index 0000000000..edae63534a --- /dev/null +++ b/build/clang-plugin/RefCountedCopyConstructorChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef RefCountedCopyConstructorChecker_h__ +#define RefCountedCopyConstructorChecker_h__ + +#include "plugin.h" + +class RefCountedCopyConstructorChecker : public BaseCheck { +public: + RefCountedCopyConstructorChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/RefCountedInsideLambdaChecker.cpp b/build/clang-plugin/RefCountedInsideLambdaChecker.cpp new file mode 100644 index 0000000000..3256aa8f04 --- /dev/null +++ b/build/clang-plugin/RefCountedInsideLambdaChecker.cpp @@ -0,0 +1,164 @@ +/* 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 "RefCountedInsideLambdaChecker.h" +#include "CustomMatchers.h" + +RefCountedMap RefCountedClasses; + +void RefCountedInsideLambdaChecker::registerMatchers(MatchFinder *AstMatcher) { + // We want to reject any code which captures a pointer to an object of a + // refcounted type, and then lets that value escape. As a primitive analysis, + // we reject any occurances of the lambda as a template parameter to a class + // (which could allow it to escape), as well as any presence of such a lambda + // in a return value (either from lambdas, or in c++14, auto functions). + // + // We check these lambdas' capture lists for raw pointers to refcounted types. + AstMatcher->addMatcher(functionDecl(returns(recordType(hasDeclaration( + cxxRecordDecl(isLambdaDecl()).bind("decl"))))), + this); + AstMatcher->addMatcher(lambdaExpr().bind("lambdaExpr"), this); + AstMatcher->addMatcher( + classTemplateSpecializationDecl( + hasAnyTemplateArgument(refersToType(recordType( + hasDeclaration(cxxRecordDecl(isLambdaDecl()).bind("decl")))))), + this); +} + +void RefCountedInsideLambdaChecker::emitDiagnostics(SourceLocation Loc, + StringRef Name, + QualType Type) { + diag(Loc, + "Refcounted variable '%0' of type %1 cannot be captured by a lambda", + DiagnosticIDs::Error) + << Name << Type; + diag(Loc, "Please consider using a smart pointer", DiagnosticIDs::Note); +} + +static bool IsKnownLive(const VarDecl *Var) { + const Stmt *Init = Var->getInit(); + if (!Init) { + return false; + } + if (auto *Call = dyn_cast<CallExpr>(Init)) { + const FunctionDecl *Callee = Call->getDirectCallee(); + return Callee && Callee->getName() == "MOZ_KnownLive"; + } + return false; +} + +void RefCountedInsideLambdaChecker::check( + const MatchFinder::MatchResult &Result) { + static DenseSet<const CXXRecordDecl *> CheckedDecls; + + const CXXRecordDecl *Lambda = Result.Nodes.getNodeAs<CXXRecordDecl>("decl"); + + if (const LambdaExpr *OuterLambda = + Result.Nodes.getNodeAs<LambdaExpr>("lambdaExpr")) { + const CXXMethodDecl *OpCall = OuterLambda->getCallOperator(); + QualType ReturnTy = OpCall->getReturnType(); + if (const CXXRecordDecl *Record = ReturnTy->getAsCXXRecordDecl()) { + Lambda = Record; + } + } + + if (!Lambda || !Lambda->isLambda()) { + return; + } + + // Don't report errors on the same declarations more than once. + if (CheckedDecls.count(Lambda)) { + return; + } + CheckedDecls.insert(Lambda); + + bool StrongRefToThisCaptured = false; + + for (const LambdaCapture &Capture : Lambda->captures()) { + // Check if any of the captures are ByRef. If they are, we have nothing to + // report, as it's OK to capture raw pointers to refcounted objects so long + // as the Lambda doesn't escape the current scope, which is required by + // ByRef captures already. + if (Capture.getCaptureKind() == LCK_ByRef) { + return; + } + + // Check if this capture is byvalue, and captures a strong reference to + // this. + // XXX: Do we want to make sure that this type which we are capturing is a + // "Smart Pointer" somehow? + if (!StrongRefToThisCaptured && Capture.capturesVariable() && + Capture.getCaptureKind() == LCK_ByCopy) { + const VarDecl *Var = dyn_cast<VarDecl>(Capture.getCapturedVar()); + if (Var->hasInit()) { + const Stmt *Init = Var->getInit(); + + // Ignore single argument constructors, and trivial nodes. + while (true) { + auto NewInit = IgnoreTrivials(Init); + if (auto ConstructExpr = dyn_cast<CXXConstructExpr>(NewInit)) { + if (ConstructExpr->getNumArgs() == 1) { + NewInit = ConstructExpr->getArg(0); + } + } + if (Init == NewInit) { + break; + } + Init = NewInit; + } + + if (isa<CXXThisExpr>(Init)) { + StrongRefToThisCaptured = true; + } + } + } + } + + // Now we can go through and produce errors for any captured variables or this + // pointers. + for (const LambdaCapture &Capture : Lambda->captures()) { + if (Capture.capturesVariable()) { + const VarDecl *Var = dyn_cast<VarDecl>(Capture.getCapturedVar()); + QualType Pointee = Var->getType()->getPointeeType(); + if (!Pointee.isNull() && isClassRefCounted(Pointee) && + !IsKnownLive(Var)) { + emitDiagnostics(Capture.getLocation(), Var->getName(), Pointee); + return; + } + } + + // The situation with captures of `this` is more complex. All captures of + // `this` look the same-ish (they are LCK_This). We want to complain about + // captures of `this` where `this` is a refcounted type, and the capture is + // actually used in the body of the lambda (if the capture isn't used, then + // we don't care, because it's only being captured in order to give access + // to private methods). + // + // In addition, we don't complain about this, even if it is used, if it was + // captured implicitly when the LambdaCaptureDefault was LCD_ByRef, as that + // expresses the intent that the lambda won't leave the enclosing scope. + bool ImplicitByRefDefaultedCapture = + Capture.isImplicit() && Lambda->getLambdaCaptureDefault() == LCD_ByRef; + if (Capture.capturesThis() && !ImplicitByRefDefaultedCapture && + !StrongRefToThisCaptured) { + ThisVisitor V(*this); + bool NotAborted = V.TraverseDecl( + const_cast<CXXMethodDecl *>(Lambda->getLambdaCallOperator())); + if (!NotAborted) { + return; + } + } + } +} + +bool RefCountedInsideLambdaChecker::ThisVisitor::VisitCXXThisExpr( + CXXThisExpr *This) { + QualType Pointee = This->getType()->getPointeeType(); + if (!Pointee.isNull() && isClassRefCounted(Pointee)) { + Checker.emitDiagnostics(This->getBeginLoc(), "this", Pointee); + return false; + } + + return true; +} diff --git a/build/clang-plugin/RefCountedInsideLambdaChecker.h b/build/clang-plugin/RefCountedInsideLambdaChecker.h new file mode 100644 index 0000000000..ed9419681a --- /dev/null +++ b/build/clang-plugin/RefCountedInsideLambdaChecker.h @@ -0,0 +1,33 @@ +/* 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/. */ + +#ifndef RefCountedInsideLambdaChecker_h__ +#define RefCountedInsideLambdaChecker_h__ + +#include "plugin.h" + +class RefCountedInsideLambdaChecker : public BaseCheck { +public: + RefCountedInsideLambdaChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; + + void emitDiagnostics(SourceLocation Loc, StringRef Name, QualType Type); + +private: + class ThisVisitor : public RecursiveASTVisitor<ThisVisitor> { + public: + explicit ThisVisitor(RefCountedInsideLambdaChecker &Checker) + : Checker(Checker) {} + + bool VisitCXXThisExpr(CXXThisExpr *This); + + private: + RefCountedInsideLambdaChecker &Checker; + }; +}; + +#endif diff --git a/build/clang-plugin/RefCountedThisInsideConstructorChecker.cpp b/build/clang-plugin/RefCountedThisInsideConstructorChecker.cpp new file mode 100644 index 0000000000..9607f41f10 --- /dev/null +++ b/build/clang-plugin/RefCountedThisInsideConstructorChecker.cpp @@ -0,0 +1,29 @@ +/* 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 "RefCountedThisInsideConstructorChecker.h" +#include "CustomMatchers.h" + +void RefCountedThisInsideConstructorChecker::registerMatchers( + MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxConstructExpr(hasType(isSmartPtrToRefCounted()), + hasArgument(0, cxxThisExpr()), + hasAncestor(cxxConstructorDecl().bind("constructor"))) + .bind("call"), + this); +} + +void RefCountedThisInsideConstructorChecker::check( + const MatchFinder::MatchResult &Result) { + const CXXConstructExpr *Call = + Result.Nodes.getNodeAs<CXXConstructExpr>("call"); + + diag(Call->getBeginLoc(), + "Refcounting `this` inside the constructor is a footgun, `this` may be " + "destructed at the end of the constructor unless there's another strong " + "reference. Consider adding a separate Create function and do the work " + "there.", + DiagnosticIDs::Error); +} diff --git a/build/clang-plugin/RefCountedThisInsideConstructorChecker.h b/build/clang-plugin/RefCountedThisInsideConstructorChecker.h new file mode 100644 index 0000000000..f8ae68e2a5 --- /dev/null +++ b/build/clang-plugin/RefCountedThisInsideConstructorChecker.h @@ -0,0 +1,19 @@ +/* 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/. */ + +#ifndef BUILD_CLANG_PLUGIN_PREVENTADDREFWITHINCONSTRUCTORCHECKER_H +#define BUILD_CLANG_PLUGIN_PREVENTADDREFWITHINCONSTRUCTORCHECKER_H + +#include "plugin.h" + +class RefCountedThisInsideConstructorChecker : public BaseCheck { +public: + RefCountedThisInsideConstructorChecker(StringRef CheckName, + ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/ScopeChecker.cpp b/build/clang-plugin/ScopeChecker.cpp new file mode 100644 index 0000000000..962c252105 --- /dev/null +++ b/build/clang-plugin/ScopeChecker.cpp @@ -0,0 +1,180 @@ +/* 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 "ScopeChecker.h" +#include "CustomMatchers.h" + +void ScopeChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(varDecl().bind("node"), this); + AstMatcher->addMatcher(cxxNewExpr().bind("node"), this); + AstMatcher->addMatcher( + materializeTemporaryExpr( + unless(hasDescendant(cxxConstructExpr(allowsTemporary())))) + .bind("node"), + this); + AstMatcher->addMatcher( + callExpr(callee(functionDecl(heapAllocator()))).bind("node"), this); +} + +// These enum variants determine whether an allocation has occured in the code. +enum AllocationVariety { + AV_None, + AV_Global, + AV_Automatic, + AV_Temporary, + AV_Heap, +}; + +// XXX Currently the Decl* in the AutomaticTemporaryMap is unused, but it +// probably will be used at some point in the future, in order to produce better +// error messages. +typedef DenseMap<const MaterializeTemporaryExpr *, const Decl *> + AutomaticTemporaryMap; +AutomaticTemporaryMap AutomaticTemporaries; + +void ScopeChecker::check(const MatchFinder::MatchResult &Result) { + // There are a variety of different reasons why something could be allocated + AllocationVariety Variety = AV_None; + SourceLocation Loc; + QualType T; + bool IsStaticLocal = false; + + if (const ParmVarDecl *D = Result.Nodes.getNodeAs<ParmVarDecl>("node")) { + if (D->hasUnparsedDefaultArg() || D->hasUninstantiatedDefaultArg()) { + return; + } + if (const Expr *Default = D->getDefaultArg()) { + if (const MaterializeTemporaryExpr *E = + dyn_cast<MaterializeTemporaryExpr>(Default)) { + // We have just found a ParmVarDecl which has, as its default argument, + // a MaterializeTemporaryExpr. We mark that MaterializeTemporaryExpr as + // automatic, by adding it to the AutomaticTemporaryMap. + // Reporting on this type will occur when the MaterializeTemporaryExpr + // is matched against. + AutomaticTemporaries[E] = D; + } + } + return; + } + + // Determine the type of allocation which we detected + if (const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node")) { + if (D->hasGlobalStorage()) { + Variety = AV_Global; + } else { + Variety = AV_Automatic; + } + T = D->getType(); + Loc = D->getBeginLoc(); + IsStaticLocal = D->isStaticLocal(); + } else if (const CXXNewExpr *E = Result.Nodes.getNodeAs<CXXNewExpr>("node")) { + // New allocates things on the heap. + // We don't consider placement new to do anything, as it doesn't actually + // allocate the storage, and thus gives us no useful information. + if (!isPlacementNew(E)) { + Variety = AV_Heap; + T = E->getAllocatedType(); + Loc = E->getBeginLoc(); + } + } else if (const MaterializeTemporaryExpr *E = + Result.Nodes.getNodeAs<MaterializeTemporaryExpr>("node")) { + // Temporaries can actually have varying storage durations, due to temporary + // lifetime extension. We consider the allocation variety of this temporary + // to be the same as the allocation variety of its lifetime. + + // XXX We maybe should mark these lifetimes as being due to a temporary + // which has had its lifetime extended, to improve the error messages. + switch (E->getStorageDuration()) { + case SD_FullExpression: { + // Check if this temporary is allocated as a default argument! + // if it is, we want to pretend that it is automatic. + AutomaticTemporaryMap::iterator AutomaticTemporary = + AutomaticTemporaries.find(E); + if (AutomaticTemporary != AutomaticTemporaries.end()) { + Variety = AV_Automatic; + } else { + Variety = AV_Temporary; + } + } break; + case SD_Automatic: + Variety = AV_Automatic; + break; + case SD_Thread: + case SD_Static: + Variety = AV_Global; + break; + case SD_Dynamic: + assert(false && "I don't think that this ever should occur..."); + Variety = AV_Heap; + break; + } + T = E->getType().getUnqualifiedType(); + Loc = E->getBeginLoc(); + } else if (const CallExpr *E = Result.Nodes.getNodeAs<CallExpr>("node")) { + T = E->getType()->getPointeeType(); + if (!T.isNull()) { + // This will always allocate on the heap, as the heapAllocator() check + // was made in the matcher + Variety = AV_Heap; + Loc = E->getBeginLoc(); + } + } + + // Error messages for incorrect allocations. + const char *Stack = "variable of type %0 only valid on the stack"; + const char *Global = "variable of type %0 only valid as global"; + const char *Heap = "variable of type %0 only valid on the heap"; + const char *NonHeap = "variable of type %0 is not valid on the heap"; + const char *NonTemporary = "variable of type %0 is not valid in a temporary"; + const char *Temporary = "variable of type %0 is only valid as a temporary"; + const char *StaticLocal = "variable of type %0 is only valid as a static " + "local"; + + const char *StackNote = + "value incorrectly allocated in an automatic variable"; + const char *GlobalNote = "value incorrectly allocated in a global variable"; + const char *HeapNote = "value incorrectly allocated on the heap"; + const char *TemporaryNote = "value incorrectly allocated in a temporary"; + + // Report errors depending on the annotations on the input types. + switch (Variety) { + case AV_None: + return; + + case AV_Global: + StackClass.reportErrorIfPresent(*this, T, Loc, Stack, GlobalNote); + HeapClass.reportErrorIfPresent(*this, T, Loc, Heap, GlobalNote); + TemporaryClass.reportErrorIfPresent(*this, T, Loc, Temporary, GlobalNote); + if (!IsStaticLocal) { + StaticLocalClass.reportErrorIfPresent(*this, T, Loc, StaticLocal, + GlobalNote); + } + break; + + case AV_Automatic: + GlobalClass.reportErrorIfPresent(*this, T, Loc, Global, StackNote); + HeapClass.reportErrorIfPresent(*this, T, Loc, Heap, StackNote); + TemporaryClass.reportErrorIfPresent(*this, T, Loc, Temporary, StackNote); + StaticLocalClass.reportErrorIfPresent(*this, T, Loc, StaticLocal, + StackNote); + break; + + case AV_Temporary: + GlobalClass.reportErrorIfPresent(*this, T, Loc, Global, TemporaryNote); + HeapClass.reportErrorIfPresent(*this, T, Loc, Heap, TemporaryNote); + NonTemporaryClass.reportErrorIfPresent(*this, T, Loc, NonTemporary, + TemporaryNote); + StaticLocalClass.reportErrorIfPresent(*this, T, Loc, StaticLocal, + TemporaryNote); + break; + + case AV_Heap: + GlobalClass.reportErrorIfPresent(*this, T, Loc, Global, HeapNote); + StackClass.reportErrorIfPresent(*this, T, Loc, Stack, HeapNote); + NonHeapClass.reportErrorIfPresent(*this, T, Loc, NonHeap, HeapNote); + TemporaryClass.reportErrorIfPresent(*this, T, Loc, Temporary, HeapNote); + StaticLocalClass.reportErrorIfPresent(*this, T, Loc, StaticLocal, HeapNote); + break; + } +} diff --git a/build/clang-plugin/ScopeChecker.h b/build/clang-plugin/ScopeChecker.h new file mode 100644 index 0000000000..edab241f1c --- /dev/null +++ b/build/clang-plugin/ScopeChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef ScopeChecker_h__ +#define ScopeChecker_h__ + +#include "plugin.h" + +class ScopeChecker : public BaseCheck { +public: + ScopeChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/SprintfLiteralChecker.cpp b/build/clang-plugin/SprintfLiteralChecker.cpp new file mode 100644 index 0000000000..94e8e2fd1b --- /dev/null +++ b/build/clang-plugin/SprintfLiteralChecker.cpp @@ -0,0 +1,84 @@ +/* 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 "SprintfLiteralChecker.h" +#include "CustomMatchers.h" + +void SprintfLiteralChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + callExpr( + isSnprintfLikeFunc(), + allOf(hasArgument( + 0, ignoringParenImpCasts(declRefExpr().bind("buffer"))), + anyOf(hasArgument(1, sizeOfExpr(has(ignoringParenImpCasts( + declRefExpr().bind("size"))))), + hasArgument(1, integerLiteral().bind("immediate")), + hasArgument(1, declRefExpr(to(varDecl( + hasType(isConstQualified()), + hasInitializer(integerLiteral().bind( + "constant"))))))))) + .bind("funcCall"), + this); +} + +void SprintfLiteralChecker::check(const MatchFinder::MatchResult &Result) { + if (!Result.Context->getLangOpts().CPlusPlus) { + // SprintfLiteral is not usable in C, so there is no point in issuing these + // warnings. + return; + } + + const char *Error = + "Use %1 instead of %0 when writing into a character array."; + const char *Note = + "This will prevent passing in the wrong size to %0 accidentally."; + + const CallExpr *D = Result.Nodes.getNodeAs<CallExpr>("funcCall"); + + StringRef Name = D->getDirectCallee()->getName(); + const char *Replacement; + if (Name == "snprintf") { + Replacement = "SprintfLiteral"; + } else { + assert(Name == "vsnprintf"); + Replacement = "VsprintfLiteral"; + } + + const DeclRefExpr *Buffer = Result.Nodes.getNodeAs<DeclRefExpr>("buffer"); + const DeclRefExpr *Size = Result.Nodes.getNodeAs<DeclRefExpr>("size"); + if (Size) { + // Match calls like snprintf(x, sizeof(x), ...). + if (Buffer->getFoundDecl() != Size->getFoundDecl()) { + return; + } + + diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) << Name << Replacement; + diag(D->getBeginLoc(), Note, DiagnosticIDs::Note) << Name; + return; + } + + const QualType QType = Buffer->getType(); + const ConstantArrayType *Type = + dyn_cast<ConstantArrayType>(QType.getTypePtrOrNull()); + if (Type) { + // Match calls like snprintf(x, 100, ...), where x is int[100]; + const IntegerLiteral *Literal = + Result.Nodes.getNodeAs<IntegerLiteral>("immediate"); + if (!Literal) { + // Match calls like: const int y = 100; snprintf(x, y, ...); + Literal = Result.Nodes.getNodeAs<IntegerLiteral>("constant"); + } + + // We're going to assume here that the bitwidth of both of these values fits + // within 64 bits. and zero-extend both values to 64-bits before comparing + // them. + uint64_t Size = Type->getSize().getZExtValue(); + uint64_t Lit = Literal->getValue().getZExtValue(); + if (Size <= Lit) { + diag(D->getBeginLoc(), Error, DiagnosticIDs::Error) + << Name << Replacement; + diag(D->getBeginLoc(), Note, DiagnosticIDs::Note) << Name; + } + } +} diff --git a/build/clang-plugin/SprintfLiteralChecker.h b/build/clang-plugin/SprintfLiteralChecker.h new file mode 100644 index 0000000000..bf407987b3 --- /dev/null +++ b/build/clang-plugin/SprintfLiteralChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef SprintfLiteralChecker_h__ +#define SprintfLiteralChecker_h__ + +#include "plugin.h" + +class SprintfLiteralChecker : public BaseCheck { +public: + SprintfLiteralChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/StmtToBlockMap.h b/build/clang-plugin/StmtToBlockMap.h new file mode 100644 index 0000000000..09b0cac415 --- /dev/null +++ b/build/clang-plugin/StmtToBlockMap.h @@ -0,0 +1,90 @@ +/* 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/. */ + +#ifndef StmtToBlockMap_h__ +#define StmtToBlockMap_h__ + +#include "Utils.h" + +// This method is copied from clang-tidy's ExprSequence.cpp. +// +// Returns the Stmt nodes that are parents of 'S', skipping any potential +// intermediate non-Stmt nodes. +// +// In almost all cases, this function returns a single parent or no parents at +// all. +inline SmallVector<const Stmt *, 1> getParentStmts(const Stmt *S, + ASTContext *Context) { + SmallVector<const Stmt *, 1> Result; + + auto Parents = Context->getParents(*S); + + SmallVector<clang::DynTypedNode, 1> NodesToProcess(Parents.begin(), + Parents.end()); + + while (!NodesToProcess.empty()) { + clang::DynTypedNode Node = NodesToProcess.back(); + NodesToProcess.pop_back(); + + if (const auto *S = Node.get<Stmt>()) { + Result.push_back(S); + } else { + Parents = Context->getParents(Node); + NodesToProcess.append(Parents.begin(), Parents.end()); + } + } + + return Result; +} + +// This class is a modified version of the class from clang-tidy's +// ExprSequence.cpp +// +// Maps `Stmt`s to the `CFGBlock` that contains them. Some `Stmt`s may be +// contained in more than one `CFGBlock`; in this case, they are mapped to the +// innermost block (i.e. the one that is furthest from the root of the tree). +// An optional outparameter provides the index into the block where the `Stmt` +// was found. +class StmtToBlockMap { +public: + // Initializes the map for the given `CFG`. + StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext) + : Context(TheContext) { + for (const auto *B : *TheCFG) { + for (size_t I = 0; I < B->size(); ++I) { + if (auto S = (*B)[I].getAs<CFGStmt>()) { + Map[S->getStmt()] = std::make_pair(B, I); + } + } + } + } + + // Returns the block that S is contained in. Some `Stmt`s may be contained + // in more than one `CFGBlock`; in this case, this function returns the + // innermost block (i.e. the one that is furthest from the root of the tree). + // + // The optional outparameter `Index` is set to the index into the block where + // the `Stmt` was found. + const CFGBlock *blockContainingStmt(const Stmt *S, + size_t *Index = nullptr) const { + while (!Map.count(S)) { + SmallVector<const Stmt *, 1> Parents = getParentStmts(S, Context); + if (Parents.empty()) + return nullptr; + S = Parents[0]; + } + + const auto &E = Map.lookup(S); + if (Index) + *Index = E.second; + return E.first; + } + +private: + ASTContext *Context; + + llvm::DenseMap<const Stmt *, std::pair<const CFGBlock *, size_t>> Map; +}; + +#endif // StmtToBlockMap_h__ diff --git a/build/clang-plugin/ThirdPartyPaths.h b/build/clang-plugin/ThirdPartyPaths.h new file mode 100644 index 0000000000..6a497923f2 --- /dev/null +++ b/build/clang-plugin/ThirdPartyPaths.h @@ -0,0 +1,17 @@ +/* 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/. */ + +#ifndef ThirdPartyPaths_h__ +#define ThirdPartyPaths_h__ + +#include <stdint.h> + +// These two values are defined in ThirdPartyPaths.cpp, which is a file +// generated by ThirdPartyPaths.py. + +extern const char *MOZ_THIRD_PARTY_PATHS[]; + +extern const uint32_t MOZ_THIRD_PARTY_PATHS_COUNT; + +#endif diff --git a/build/clang-plugin/ThirdPartyPaths.py b/build/clang-plugin/ThirdPartyPaths.py new file mode 100644 index 0000000000..caaa919d43 --- /dev/null +++ b/build/clang-plugin/ThirdPartyPaths.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import json + + +def generate(output, *input_paths): + """ + This file generates a ThirdPartyPaths.cpp file from the ThirdPartyPaths.txt + file in /tools/rewriting, which is used by the Clang Plugin to help identify + sources which should be ignored. + """ + tpp_list = [] + lines = set() + + for path in input_paths: + with open(path) as f: + lines.update(f.readlines()) + + for line in lines: + line = line.strip() + if line.endswith("/"): + line = line[:-1] + tpp_list.append(line) + tpp_strings = ",\n ".join([json.dumps(tpp) for tpp in sorted(tpp_list)]) + + output.write( + """\ +/* THIS FILE IS GENERATED BY ThirdPartyPaths.py - DO NOT EDIT */ + +#include <stdint.h> + +const char* MOZ_THIRD_PARTY_PATHS[] = { + %s +}; + +extern const uint32_t MOZ_THIRD_PARTY_PATHS_COUNT = %d; + +""" + % (tpp_strings, len(tpp_list)) + ) diff --git a/build/clang-plugin/ThreadAllows.py b/build/clang-plugin/ThreadAllows.py new file mode 100644 index 0000000000..f3e1ee894c --- /dev/null +++ b/build/clang-plugin/ThreadAllows.py @@ -0,0 +1,82 @@ +# 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/. +import json +import os +import posixpath +from os import PathLike + +# `typing.Literal` not available until Python 3.8; +# `typing_extensions` not generally available here +from typing import Iterable, Set + +FIRST_LINE = "// This file was generated by {}. DO NOT EDIT.".format( + # `posixpath` for forward slashes, for presentation purposes + posixpath.relpath(__file__, os.getenv("TOPSRCDIR", "/")) +) + + +def generate_allowed_items( + which: str, # should be: Literal["files", "names"], + paths: Iterable[PathLike], +) -> str: + def remove_trailing_comment(s: str) -> str: + return s[0 : s.find("#")] + + def read_items_from_path(path: PathLike) -> Set[str]: + out = set() + with open(path) as file: + for line in file.readlines(): + line = remove_trailing_comment(line).strip() + if not line: + continue # comment or empty line; discard + out.add(line) + return out + + allowed = set().union(*(read_items_from_path(path) for path in paths)) + # BUG: `json.dumps` may not correctly handle use of the quote character in + # thread names + allowed_list_s = ",\n ".join(json.dumps(elem) for elem in sorted(allowed)) + + return f"""\ +static const char *allow_thread_{which}[] = {{ + {allowed_list_s} +}};""" + + +def generate_allows( + *, allowed_names: Iterable[PathLike], allowed_files: Iterable[PathLike] +) -> str: + """ + This function reads in the specified sets of files -- ordinarily, + ["ThreadAllows.txt"] and ["ThreadFileAllows.txt"] -- and generates the text + of a header file containing two arrays with their contents, for inclusion by + the thread-name checker. + + The checker will reject the creation of any thread via NS_NewNamedThread + unless either: + - the thread's name is a literal string which is found in the set of + allowed thread names; or + - the thread's creation occurs within a file which is found in the set of + unchecked files. + + The latter condition exists mostly for the definition of NS_NewNamedThread, + but there also exist a few cases where the thread name is dynamically + computed (and so can't be checked). + """ + output_string = ( + FIRST_LINE + + "\n\n" + + generate_allowed_items("files", allowed_files) + + "\n\n" + + generate_allowed_items("names", allowed_names) + + "\n" + ) + return output_string + + +# Entry point used by build/clang-plugin/moz.build (q.v.). +def generate_file(output, allowed_names, allowed_files): + output.write( + generate_allows(allowed_names=[allowed_names], allowed_files=[allowed_files]) + ) diff --git a/build/clang-plugin/ThreadAllows.txt b/build/clang-plugin/ThreadAllows.txt new file mode 100644 index 0000000000..801e57504f --- /dev/null +++ b/build/clang-plugin/ThreadAllows.txt @@ -0,0 +1,115 @@ +# This file is ingested by `ThreadAllows.py` to produce a list of thread names +# which our clang plugin will allow to be used with `NS_NewNamedThread`. +# +# Permitted thread names are a maximum of 15 characters in length, and must be +# string literals at their point-of-use in the code -- i.e., in the invocation +# of `NS_NewNamedThread`. +# +# Within this file, each permitted thread name is on a separate line. Comments +# begin with `#`, as seen here. Leading and trailing whitespace, trailing +# comments, and blank lines are ignored, and may be used freely. +# +# Please explain the addition of any new thread names in comments, preferably +# with a pointer to a relevant bug. (Do not add thread names only used in tests +# to this file; instead, add the test file to `ThreadFileAllows.txt`.) + +###### +# Gecko/Firefox thread names +# (See also "Unsorted thread names", below.) + +# Used by `nsUpdateProcessor` to check for updates. May also be used for polling +# the update process. +UpdateProcessor + +###### +# Thunderbird-only thread names +IMAP + +###### +# Other +Checker Test # used only as part of tests for the thread-checker itself +Testing Thread # used only as part of tests for toolkit/components/url-classifier/tests/gtest/ + +###### +# Unsorted thread names +# +# Thread names below this point are grandfathered in. Please do not add new +# thread names to this list -- and please remove any that you can, whether by +# documenting and moving them or by confirming that they are no longer required. +# +# In particular, if a thread name is only used for testing, please consider +# moving its declarator to `ThreadFileAllows.txt`. + +BGReadURLs +BHMgr Monitor +BHMgr Processor +COM Intcpt Log +COM MTA +Cache I/O +Cameras IPC +CanvasRenderer +Compositor +Cookie +CrashRep Inject +DDMediaLogs +DOMCacheThread +DataChannel IO +DataStorage +DesktopCapture +File Dialog +FileWatcher IO +Font Loader +FontEnumThread +Function Broker +GMPThread +Gamepad +GraphRunner +HTML5 Parser +ICS parser +IPC Launch +IPDL Background +IdentityCrypto +ImageBridgeChld +LS Thread +MDCDMThread +MediaCache +MediaTelemetry +MediaTrackGrph +MemoryPoller +mtransport +NamedPipeSrv +Netlink Monitor +OSKeyStore +OutputDrain +PaintThread +Permission +PlayEventSound +ProcessHangMon +ProfSymbolTable +ProfilerChild +ProxyResolution +RemoteLzyStream +RemVidChild +Renderer +ResetCleanup +SaveScripts +Socket Thread +SpeechWorker +StressRunner +SuicideManager +System Proxy +TelemetryModule +Timer +ToastBgThread +TRR Background +URL Classifier +VideoCapture +VRService +VsyncIOThread +Wifi Monitor +Worker Launcher +speechd init +thread +thread shutdown +wifi tickler +WMFCDMThread diff --git a/build/clang-plugin/ThreadFileAllows.txt b/build/clang-plugin/ThreadFileAllows.txt new file mode 100644 index 0000000000..a10cbbea3e --- /dev/null +++ b/build/clang-plugin/ThreadFileAllows.txt @@ -0,0 +1,75 @@ +# This file is ingested by `ThreadAllows.py` to produce a list of files which +# our clang plugin will allow to use `NS_NewNamedThread`. +# +# Files may be specified with any number of slash-separated path-elements; all +# provided path-elements must match. (Because we often move and/or symlink +# header files, this means headers will usually have no path-elements.) +# +# Note that this file contains a list of _files_, not _paths_. The clang plugin +# has no notion of $TOPSRCDIR. + +###### +# Release files + +# declaration and definition of `NS_NewNamedThread` +nsThreadUtils.h +xpcom/threads/nsThreadUtils.cpp + +# Thread-pools are permitted to make dynamically many threads, using dynamic +# thread names with explicit numbering. +xpcom/threads/nsThreadPool.cpp + +###### +# Test files + +# Tests for XPCOM threads themselves. +xpcom/tests/gtest/TestThreadManager.cpp +xpcom/tests/gtest/TestThreads.cpp +xpcom/tests/gtest/TestThreadUtils.cpp + +# Tests which use dynamic thread names. +xpcom/tests/gtest/TestHandleWatcher.cpp + +###### +# Unsorted release files +# +# Files below this point are grandfathered in. Please do not add new files to +# this list -- and please remove any that you can, whether by documenting and +# moving them or by confirming that they are no longer required. +dom/indexedDB/ActorsParent.cpp +dom/quota/ActorsParent.cpp +DecodePool.cpp +GeckoChildProcessHost.cpp +LazyIdleThread.cpp +LazyIdleThread.h +VRThread.cpp +mozStorageConnection.cpp +nr_socket_prsock.cpp + +###### +# Unsorted test files +# +# Files below this point are quasi-grandfathered in: these are test files which +# create new threads whose names were formerly in ThreadAllows.txt (without +# justification), and have been moved here (without justification). +dom/media/doctor/test/gtest/TestMultiWriterQueue.cpp +image/test/fuzzing/TestDecoders.cpp +image/test/gtest/TestDecodeToSurface.cpp +ipc/ipdl/test/gtest/IPDLUnitTest.cpp +security/sandbox/common/test/SandboxTestingThread.h +storage/test/gtest/test_interruptSynchronousConnection.cpp +storage/test/gtest/test_unlock_notify.cpp +toolkit/components/telemetry/geckoview/gtest/TestGeckoViewStreaming.cpp +toolkit/components/telemetry/tests/gtest/TestScalars.cpp +toolkit/components/url-classifier/tests/gtest/Common.cpp +tools/fuzzing/ipc/IPCFuzzController.cpp +tools/profiler/tests/gtest/GeckoProfiler.cpp +xpcom/tests/gtest/TestAtoms.cpp +xpcom/tests/gtest/TestAutoRefCnt.cpp +xpcom/tests/gtest/TestDelayedRunnable.cpp +xpcom/tests/gtest/TestLogging.cpp +xpcom/tests/gtest/TestPipes.cpp +xpcom/tests/gtest/TestRacingServiceManager.cpp +xpcom/tests/gtest/TestRWLock.cpp +xpcom/tests/gtest/TestThrottledEventQueue.cpp +xpcom/tests/gtest/TestTimers.cpp diff --git a/build/clang-plugin/TrivialCtorDtorChecker.cpp b/build/clang-plugin/TrivialCtorDtorChecker.cpp new file mode 100644 index 0000000000..59576a5b64 --- /dev/null +++ b/build/clang-plugin/TrivialCtorDtorChecker.cpp @@ -0,0 +1,29 @@ +/* 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 "TrivialCtorDtorChecker.h" +#include "CustomMatchers.h" + +void TrivialCtorDtorChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(cxxRecordDecl(hasTrivialCtorDtor()).bind("node"), + this); +} + +void TrivialCtorDtorChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = "class %0 must have trivial constructors and destructors"; + const CXXRecordDecl *Node = Result.Nodes.getNodeAs<CXXRecordDecl>("node"); + + if (!Node->hasDefinition()) { + return; + } + + // We need to accept non-constexpr trivial constructors as well. This occurs + // when a struct contains pod members, which will not be initialized. As + // constexpr values are initialized, the constructor is non-constexpr. + bool BadCtor = !(Node->hasConstexprDefaultConstructor() || + Node->hasTrivialDefaultConstructor()); + bool BadDtor = !Node->hasTrivialDestructor(); + if (BadCtor || BadDtor) + diag(Node->getBeginLoc(), Error, DiagnosticIDs::Error) << Node; +} diff --git a/build/clang-plugin/TrivialCtorDtorChecker.h b/build/clang-plugin/TrivialCtorDtorChecker.h new file mode 100644 index 0000000000..6b44016781 --- /dev/null +++ b/build/clang-plugin/TrivialCtorDtorChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef TrivialCtorDtorChecker_h__ +#define TrivialCtorDtorChecker_h__ + +#include "plugin.h" + +class TrivialCtorDtorChecker : public BaseCheck { +public: + TrivialCtorDtorChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/TrivialDtorChecker.cpp b/build/clang-plugin/TrivialDtorChecker.cpp new file mode 100644 index 0000000000..ffcd2ae101 --- /dev/null +++ b/build/clang-plugin/TrivialDtorChecker.cpp @@ -0,0 +1,23 @@ +/* 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 "TrivialDtorChecker.h" +#include "CustomMatchers.h" + +void TrivialDtorChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher(cxxRecordDecl(hasTrivialDtor()).bind("node"), this); +} + +void TrivialDtorChecker::check(const MatchFinder::MatchResult &Result) { + const char *Error = "class %0 must have a trivial destructor"; + const CXXRecordDecl *Node = Result.Nodes.getNodeAs<CXXRecordDecl>("node"); + + if (!Node->hasDefinition()) { + return; + } + + bool BadDtor = !Node->hasTrivialDestructor(); + if (BadDtor) + diag(Node->getBeginLoc(), Error, DiagnosticIDs::Error) << Node; +} diff --git a/build/clang-plugin/TrivialDtorChecker.h b/build/clang-plugin/TrivialDtorChecker.h new file mode 100644 index 0000000000..dd0be727e6 --- /dev/null +++ b/build/clang-plugin/TrivialDtorChecker.h @@ -0,0 +1,18 @@ +/* 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/. */ + +#ifndef TrivialDtorChecker_h__ +#define TrivialDtorChecker_h__ + +#include "plugin.h" + +class TrivialDtorChecker : public BaseCheck { +public: + TrivialDtorChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; +}; + +#endif diff --git a/build/clang-plugin/Utils.h b/build/clang-plugin/Utils.h new file mode 100644 index 0000000000..c25caf43ee --- /dev/null +++ b/build/clang-plugin/Utils.h @@ -0,0 +1,499 @@ +/* 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/. */ + +#ifndef Utils_h__ +#define Utils_h__ + +#include "CustomAttributes.h" +#include "ThirdPartyPaths.h" +#include "ThreadAllows.h" +#include "plugin.h" + +#if CLANG_VERSION_FULL >= 1300 +// Starting with clang-13 some functions from StringRef have been renamed +#define compare_lower compare_insensitive +#endif + +inline StringRef getFilename(const SourceManager &SM, SourceLocation Loc) { + // We use the presumed location to handle #line directives and such, so the + // plugin is friendly to icecc / sccache users. + auto PL = SM.getPresumedLoc(Loc); + if (PL.isValid()) { + return StringRef(PL.getFilename()); + } + return SM.getFilename(Loc); +} + +// Check if the given expression contains an assignment expression. +// This can either take the form of a Binary Operator or a +// Overloaded Operator Call. +inline bool hasSideEffectAssignment(const Expr *Expression) { + if (auto OpCallExpr = dyn_cast_or_null<CXXOperatorCallExpr>(Expression)) { + auto BinOp = OpCallExpr->getOperator(); + if (BinOp == OO_Equal || (BinOp >= OO_PlusEqual && BinOp <= OO_PipeEqual)) { + return true; + } + } else if (auto BinOpExpr = dyn_cast_or_null<BinaryOperator>(Expression)) { + if (BinOpExpr->isAssignmentOp()) { + return true; + } + } + + // Recurse to children. + for (const Stmt *SubStmt : Expression->children()) { + auto ChildExpr = dyn_cast_or_null<Expr>(SubStmt); + if (ChildExpr && hasSideEffectAssignment(ChildExpr)) { + return true; + } + } + + return false; +} + +template <class T> +inline bool ASTIsInSystemHeader(const ASTContext &AC, const T &D) { + auto &SourceManager = AC.getSourceManager(); + auto ExpansionLoc = SourceManager.getExpansionLoc(D.getBeginLoc()); + if (ExpansionLoc.isInvalid()) { + return false; + } + return SourceManager.isInSystemHeader(ExpansionLoc); +} + +template <typename T> inline StringRef getNameChecked(const T &D) { + return D->getIdentifier() ? D->getName() : ""; +} + +/// A cached data of whether classes are refcounted or not. +typedef DenseMap<const CXXRecordDecl *, std::pair<const Decl *, bool>> + RefCountedMap; +extern RefCountedMap RefCountedClasses; + +inline bool classHasAddRefRelease(const CXXRecordDecl *D) { + const RefCountedMap::iterator &It = RefCountedClasses.find(D); + if (It != RefCountedClasses.end()) { + return It->second.second; + } + + bool SeenAddRef = false; + bool SeenRelease = false; + for (CXXRecordDecl::method_iterator Method = D->method_begin(); + Method != D->method_end(); ++Method) { + const auto &Name = getNameChecked(Method); + if (Name == "AddRef") { + SeenAddRef = true; + } else if (Name == "Release") { + SeenRelease = true; + } + } + RefCountedClasses[D] = std::make_pair(D, SeenAddRef && SeenRelease); + return SeenAddRef && SeenRelease; +} + +inline bool isClassRefCounted(QualType T); + +inline bool isClassRefCounted(const CXXRecordDecl *D) { + // Normalize so that D points to the definition if it exists. + if (!D->hasDefinition()) + return false; + D = D->getDefinition(); + // Base class: anyone with AddRef/Release is obviously a refcounted class. + if (classHasAddRefRelease(D)) + return true; + + // Look through all base cases to figure out if the parent is a refcounted + // class. + for (CXXRecordDecl::base_class_const_iterator Base = D->bases_begin(); + Base != D->bases_end(); ++Base) { + bool Super = isClassRefCounted(Base->getType()); + if (Super) { + return true; + } + } + + return false; +} + +inline bool isClassRefCounted(QualType T) { + while (const clang::ArrayType *ArrTy = T->getAsArrayTypeUnsafe()) + T = ArrTy->getElementType(); + CXXRecordDecl *Clazz = T->getAsCXXRecordDecl(); + return Clazz ? isClassRefCounted(Clazz) : false; +} + +inline const FieldDecl *getClassRefCntMember(const CXXRecordDecl *D) { + for (RecordDecl::field_iterator Field = D->field_begin(), E = D->field_end(); + Field != E; ++Field) { + if (getNameChecked(Field) == "mRefCnt") { + return *Field; + } + } + return 0; +} + +inline bool typeHasVTable(QualType T) { + while (const clang::ArrayType *ArrTy = T->getAsArrayTypeUnsafe()) + T = ArrTy->getElementType(); + CXXRecordDecl *Offender = T->getAsCXXRecordDecl(); + return Offender && Offender->hasDefinition() && Offender->isDynamicClass(); +} + +inline StringRef getDeclarationNamespace(const Decl *Declaration) { + const DeclContext *DC = + Declaration->getDeclContext()->getEnclosingNamespaceContext(); + const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); + if (!ND) { + return ""; + } + + while (const DeclContext *ParentDC = ND->getParent()) { + if (!isa<NamespaceDecl>(ParentDC)) { + break; + } + ND = cast<NamespaceDecl>(ParentDC); + } + + const auto &Name = ND->getName(); + return Name; +} + +inline bool isInIgnoredNamespaceForImplicitCtor(const Decl *Declaration) { + StringRef Name = getDeclarationNamespace(Declaration); + if (Name == "") { + return false; + } + + return Name == "std" || // standard C++ lib + Name == "__gnu_cxx" || // gnu C++ lib + Name == "boost" || // boost + Name == "webrtc" || // upstream webrtc + Name == "rtc" || // upstream webrtc 'base' package + Name.startswith("icu_") || // icu + Name == "google" || // protobuf + Name == "google_breakpad" || // breakpad + Name == "soundtouch" || // libsoundtouch + Name == "stagefright" || // libstagefright + Name == "MacFileUtilities" || // MacFileUtilities + Name == "dwarf2reader" || // dwarf2reader + Name == "arm_ex_to_module" || // arm_ex_to_module + Name == "testing" || // gtest + Name == "Json" || // jsoncpp + Name == "rlbox" || // rlbox + Name == "v8"; // irregexp +} + +inline bool isInIgnoredNamespaceForImplicitConversion(const Decl *Declaration) { + StringRef Name = getDeclarationNamespace(Declaration); + if (Name == "") { + return false; + } + + return Name == "std" || // standard C++ lib + Name == "__gnu_cxx" || // gnu C++ lib + Name == "google_breakpad" || // breakpad + Name == "webrtc" || // libwebrtc + Name == "testing" || // gtest + Name == "rlbox"; // rlbox +} + +inline bool isIgnoredPathForImplicitConversion(const Decl *Declaration) { + Declaration = Declaration->getCanonicalDecl(); + SourceLocation Loc = Declaration->getLocation(); + const SourceManager &SM = Declaration->getASTContext().getSourceManager(); + SmallString<1024> FileName = getFilename(SM, Loc); + llvm::sys::fs::make_absolute(FileName); + llvm::sys::path::reverse_iterator Begin = llvm::sys::path::rbegin(FileName), + End = llvm::sys::path::rend(FileName); + for (; Begin != End; ++Begin) { + if (Begin->compare_lower(StringRef("graphite2")) == 0) { + return true; + } + if (Begin->compare_lower(StringRef("chromium")) == 0) { + // Ignore security/sandbox/chromium but not ipc/chromium. + ++Begin; + return Begin != End && Begin->compare_lower(StringRef("sandbox")) == 0; + } + } + return false; +} + +inline bool isIgnoredPathForSprintfLiteral(const CallExpr *Call, + const SourceManager &SM) { + SourceLocation Loc = Call->getBeginLoc(); + SmallString<1024> FileName = getFilename(SM, Loc); + llvm::sys::fs::make_absolute(FileName); + llvm::sys::path::reverse_iterator Begin = llvm::sys::path::rbegin(FileName), + End = llvm::sys::path::rend(FileName); + for (; Begin != End; ++Begin) { + if (Begin->compare_lower(StringRef("angle")) == 0 || + Begin->compare_lower(StringRef("chromium")) == 0 || + Begin->compare_lower(StringRef("crashreporter")) == 0 || + Begin->compare_lower(StringRef("google-breakpad")) == 0 || + Begin->compare_lower(StringRef("gflags")) == 0 || + Begin->compare_lower(StringRef("harfbuzz")) == 0 || + Begin->compare_lower(StringRef("icu")) == 0 || + Begin->compare_lower(StringRef("jsoncpp")) == 0 || + Begin->compare_lower(StringRef("libstagefright")) == 0 || + Begin->compare_lower(StringRef("transport")) == 0 || + Begin->compare_lower(StringRef("protobuf")) == 0 || + Begin->compare_lower(StringRef("skia")) == 0 || + Begin->compare_lower(StringRef("sfntly")) == 0 || + // Gtest uses snprintf as GTEST_SNPRINTF_ with sizeof + Begin->compare_lower(StringRef("testing")) == 0) { + return true; + } + if (Begin->compare_lower(StringRef("webrtc")) == 0) { + // Ignore trunk/webrtc, but not media/webrtc + ++Begin; + return Begin != End && Begin->compare_lower(StringRef("trunk")) == 0; + } + } + return false; +} + +inline bool isInterestingDeclForImplicitConversion(const Decl *Declaration) { + return !isInIgnoredNamespaceForImplicitConversion(Declaration) && + !isIgnoredPathForImplicitConversion(Declaration); +} + +inline bool isIgnoredExprForMustUse(const Expr *E) { + if (const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) { + switch (OpCall->getOperator()) { + case OO_Equal: + case OO_PlusEqual: + case OO_MinusEqual: + case OO_StarEqual: + case OO_SlashEqual: + case OO_PercentEqual: + case OO_CaretEqual: + case OO_AmpEqual: + case OO_PipeEqual: + case OO_LessLessEqual: + case OO_GreaterGreaterEqual: + return true; + default: + return false; + } + } + + if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) { + return Op->isAssignmentOp(); + } + + return false; +} + +inline bool typeIsRefPtr(QualType Q) { + CXXRecordDecl *D = Q->getAsCXXRecordDecl(); + if (!D || !D->getIdentifier()) { + return false; + } + + StringRef name = D->getName(); + if (name == "RefPtr" || name == "nsCOMPtr") { + return true; + } + return false; +} + +// The method defined in clang for ignoring implicit nodes doesn't work with +// some AST trees. To get around this, we define our own implementation of +// IgnoreTrivials. +inline const Stmt *MaybeSkipOneTrivial(const Stmt *s) { + if (!s) { + return nullptr; + } + if (auto *ewc = dyn_cast<ExprWithCleanups>(s)) { + return ewc->getSubExpr(); + } + if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) { + // With clang 10 and up `getTemporary` has been replaced with the more + // versatile `getSubExpr`. +#if CLANG_VERSION_FULL >= 1000 + return mte->getSubExpr(); +#else + return mte->GetTemporaryExpr(); +#endif + } + if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) { + return bte->getSubExpr(); + } + if (auto *ce = dyn_cast<CastExpr>(s)) { + s = ce->getSubExpr(); + } + if (auto *pe = dyn_cast<ParenExpr>(s)) { + s = pe->getSubExpr(); + } + // Not a trivial. + return s; +} + +inline const Stmt *IgnoreTrivials(const Stmt *s) { + while (true) { + const Stmt *newS = MaybeSkipOneTrivial(s); + if (newS == s) { + return newS; + } + s = newS; + } + + // Unreachable + return nullptr; +} + +inline const Expr *IgnoreTrivials(const Expr *e) { + return cast_or_null<Expr>(IgnoreTrivials(static_cast<const Stmt *>(e))); +} + +// Returns the input if the input is not a trivial. +inline const Expr *MaybeSkipOneTrivial(const Expr *e) { + return cast_or_null<Expr>(MaybeSkipOneTrivial(static_cast<const Stmt *>(e))); +} + +const FieldDecl *getBaseRefCntMember(QualType T); + +inline const FieldDecl *getBaseRefCntMember(const CXXRecordDecl *D) { + const FieldDecl *RefCntMember = getClassRefCntMember(D); + if (RefCntMember && isClassRefCounted(D)) { + return RefCntMember; + } + + for (CXXRecordDecl::base_class_const_iterator Base = D->bases_begin(), + E = D->bases_end(); + Base != E; ++Base) { + RefCntMember = getBaseRefCntMember(Base->getType()); + if (RefCntMember) { + return RefCntMember; + } + } + return 0; +} + +inline const FieldDecl *getBaseRefCntMember(QualType T) { + while (const clang::ArrayType *ArrTy = T->getAsArrayTypeUnsafe()) + T = ArrTy->getElementType(); + CXXRecordDecl *Clazz = T->getAsCXXRecordDecl(); + return Clazz ? getBaseRefCntMember(Clazz) : 0; +} + +inline bool isPlacementNew(const CXXNewExpr *Expression) { + // Regular new expressions aren't placement new + if (Expression->getNumPlacementArgs() == 0) + return false; + const FunctionDecl *Declaration = Expression->getOperatorNew(); + if (Declaration && hasCustomAttribute<moz_heap_allocator>(Declaration)) { + return false; + } + return true; +} + +extern DenseMap<StringRef, bool> InThirdPartyPathCache; + +inline bool inThirdPartyPath(SourceLocation Loc, const SourceManager &SM) { + StringRef OriginalFileName = getFilename(SM, Loc); + auto pair = InThirdPartyPathCache.find(OriginalFileName); + if (pair != InThirdPartyPathCache.end()) { + return pair->second; + } + + SmallString<1024> FileName = OriginalFileName; + llvm::sys::fs::make_absolute(FileName); + + for (uint32_t i = 0; i < MOZ_THIRD_PARTY_PATHS_COUNT; ++i) { + auto PathB = sys::path::begin(FileName); + auto PathE = sys::path::end(FileName); + + auto ThirdPartyB = sys::path::begin(MOZ_THIRD_PARTY_PATHS[i]); + auto ThirdPartyE = sys::path::end(MOZ_THIRD_PARTY_PATHS[i]); + + for (; PathB != PathE; ++PathB) { + // Perform an inner loop to compare path segments, checking if the current + // segment is the start of the current third party path. + auto IPathB = PathB; + auto IThirdPartyB = ThirdPartyB; + for (; IPathB != PathE && IThirdPartyB != ThirdPartyE; + ++IPathB, ++IThirdPartyB) { + if (IPathB->compare_lower(*IThirdPartyB) != 0) { + break; + } + } + + // We found a match! + if (IThirdPartyB == ThirdPartyE) { + InThirdPartyPathCache.insert(std::make_pair(OriginalFileName, true)); + return true; + } + } + } + + InThirdPartyPathCache.insert(std::make_pair(OriginalFileName, false)); + return false; +} + +inline bool inThirdPartyPath(const Decl *D, ASTContext *context) { + D = D->getCanonicalDecl(); + SourceLocation Loc = D->getLocation(); + const SourceManager &SM = context->getSourceManager(); + + return inThirdPartyPath(Loc, SM); +} + +inline CXXRecordDecl *getNonTemplateSpecializedCXXRecordDecl(QualType Q) { + auto *D = Q->getAsCXXRecordDecl(); + + if (!D) { + auto TemplateQ = Q->getAs<TemplateSpecializationType>(); + if (!TemplateQ) { + return nullptr; + } + + auto TemplateDecl = TemplateQ->getTemplateName().getAsTemplateDecl(); + if (!TemplateDecl) { + return nullptr; + } + + D = dyn_cast_or_null<CXXRecordDecl>(TemplateDecl->getTemplatedDecl()); + if (!D) { + return nullptr; + } + } + + return D; +} + +inline bool inThirdPartyPath(const Decl *D) { + return inThirdPartyPath(D, &D->getASTContext()); +} + +inline bool inThirdPartyPath(const Stmt *S, ASTContext *context) { + SourceLocation Loc = S->getBeginLoc(); + const SourceManager &SM = context->getSourceManager(); + auto ExpansionLoc = SM.getExpansionLoc(Loc); + if (ExpansionLoc.isInvalid()) { + return inThirdPartyPath(Loc, SM); + } + return inThirdPartyPath(ExpansionLoc, SM); +} + +/// Polyfill for CXXOperatorCallExpr::isInfixBinaryOp() +inline bool isInfixBinaryOp(const CXXOperatorCallExpr *OpCall) { +#if CLANG_VERSION_FULL >= 400 + return OpCall->isInfixBinaryOp(); +#else + // Taken from clang source. + if (OpCall->getNumArgs() != 2) + return false; + + switch (OpCall->getOperator()) { + case OO_Call: + case OO_Subscript: + return false; + default: + return true; + } +#endif +} + +#undef compare_lower +#endif diff --git a/build/clang-plugin/VariableUsageHelpers.cpp b/build/clang-plugin/VariableUsageHelpers.cpp new file mode 100644 index 0000000000..abb9eb280f --- /dev/null +++ b/build/clang-plugin/VariableUsageHelpers.cpp @@ -0,0 +1,275 @@ +/* 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 "VariableUsageHelpers.h" +#include "Utils.h" + +std::vector<const Stmt *> getUsageAsRvalue(const ValueDecl *ValueDeclaration, + const FunctionDecl *FuncDecl) { + std::vector<const Stmt *> UsageStatements; + + // We check the function declaration has a body. + auto Body = FuncDecl->getBody(); + if (!Body) { + return std::vector<const Stmt *>(); + } + + // We build a Control Flow Graph (CFG) fron the body of the function + // declaration. + std::unique_ptr<CFG> StatementCFG = CFG::buildCFG( + FuncDecl, Body, &FuncDecl->getASTContext(), CFG::BuildOptions()); + + // We iterate through all the CFGBlocks, which basically means that we go over + // all the possible branches of the code and therefore cover all statements. + for (auto &Block : *StatementCFG) { + // We iterate through all the statements of the block. + for (auto &BlockItem : *Block) { + auto CFGStatement = BlockItem.getAs<CFGStmt>(); + if (!CFGStatement) { + continue; + } + + // FIXME: Right now this function/if chain is very basic and only covers + // the cases we need for escapesFunction() + if (auto BinOp = dyn_cast<BinaryOperator>(CFGStatement->getStmt())) { + // We only care about assignments. + if (BinOp->getOpcode() != BO_Assign) { + continue; + } + + // We want our declaration to be used on the right hand side of the + // assignment. + auto DeclRef = dyn_cast<DeclRefExpr>(IgnoreTrivials(BinOp->getRHS())); + if (!DeclRef) { + continue; + } + + if (DeclRef->getDecl() != ValueDeclaration) { + continue; + } + } else if (auto Return = dyn_cast<ReturnStmt>(CFGStatement->getStmt())) { + // We want our declaration to be used as the expression of the return + // statement. + auto DeclRef = dyn_cast_or_null<DeclRefExpr>( + IgnoreTrivials(Return->getRetValue())); + if (!DeclRef) { + continue; + } + + if (DeclRef->getDecl() != ValueDeclaration) { + continue; + } + } else { + continue; + } + + // We didn't early-continue, so we add the statement to the list. + UsageStatements.push_back(CFGStatement->getStmt()); + } + } + + return UsageStatements; +} + +// We declare our EscapesFunctionError enum to be an error code enum. +namespace std { +template <> struct is_error_code_enum<EscapesFunctionError> : true_type {}; +} // namespace std + +// We define the EscapesFunctionErrorCategory which contains the error messages +// corresponding to each enum variant. +namespace { +struct EscapesFunctionErrorCategory : std::error_category { + const char *name() const noexcept override; + std::string message(int ev) const override; +}; + +const char *EscapesFunctionErrorCategory::name() const noexcept { + return "escapes function"; +} + +std::string EscapesFunctionErrorCategory::message(int ev) const { + switch (static_cast<EscapesFunctionError>(ev)) { + case EscapesFunctionError::ConstructorDeclNotFound: + return "constructor declaration not found"; + + case EscapesFunctionError::FunctionDeclNotFound: + return "function declaration not found"; + + case EscapesFunctionError::FunctionIsBuiltin: + return "function is builtin"; + + case EscapesFunctionError::FunctionIsVariadic: + return "function is variadic"; + + case EscapesFunctionError::ExprNotInCall: + return "expression is not in call"; + + case EscapesFunctionError::NoParamForArg: + return "no parameter for argument"; + + case EscapesFunctionError::ArgAndParamNotPointers: + return "argument and parameter are not pointers"; + } +} + +const EscapesFunctionErrorCategory TheEscapesFunctionErrorCategory{}; +} // namespace + +std::error_code make_error_code(EscapesFunctionError e) { + return {static_cast<int>(e), TheEscapesFunctionErrorCategory}; +} + +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const CXXConstructExpr *Construct) { + // We get the function declaration corresponding to the call. + auto CtorDecl = Construct->getConstructor(); + if (!CtorDecl) { + return EscapesFunctionError::ConstructorDeclNotFound; + } + + return escapesFunction(Arg, CtorDecl, Construct->getArgs(), + Construct->getNumArgs()); +} + +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const CallExpr *Call) { + // We get the function declaration corresponding to the call. + auto FuncDecl = Call->getDirectCallee(); + if (!FuncDecl) { + return EscapesFunctionError::FunctionDeclNotFound; + } + + return escapesFunction(Arg, FuncDecl, Call->getArgs(), Call->getNumArgs()); +} + +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const CXXOperatorCallExpr *OpCall) { + // We get the function declaration corresponding to the operator call. + auto FuncDecl = OpCall->getDirectCallee(); + if (!FuncDecl) { + return EscapesFunctionError::FunctionDeclNotFound; + } + + auto Args = OpCall->getArgs(); + auto NumArgs = OpCall->getNumArgs(); + // If this is an infix binary operator defined as a one-param method, we + // remove the first argument as it is inserted explicitly and creates a + // mismatch with the parameters of the method declaration. + if (isInfixBinaryOp(OpCall) && FuncDecl->getNumParams() == 1) { + Args++; + NumArgs--; + } + + return escapesFunction(Arg, FuncDecl, Args, NumArgs); +} + +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const FunctionDecl *FuncDecl, + const Expr *const *Arguments, unsigned NumArgs) { + if (!NumArgs) { + return std::make_tuple((const Stmt *)nullptr, (const Decl *)nullptr); + } + + if (FuncDecl->getBuiltinID() != 0 || + ASTIsInSystemHeader(FuncDecl->getASTContext(), *FuncDecl)) { + return EscapesFunctionError::FunctionIsBuiltin; + } + + // FIXME: should probably be handled at some point, but it's too annoying + // for now. + if (FuncDecl->isVariadic()) { + return EscapesFunctionError::FunctionIsVariadic; + } + + // We find the argument number corresponding to the Arg expression. + unsigned ArgNum = 0; + for (unsigned i = 0; i < NumArgs; i++) { + if (IgnoreTrivials(Arg) == IgnoreTrivials(Arguments[i])) { + break; + } + ++ArgNum; + } + // If we don't find it, we early-return NoneType. + if (ArgNum >= NumArgs) { + return EscapesFunctionError::ExprNotInCall; + } + + // Now we get the associated parameter. + if (ArgNum >= FuncDecl->getNumParams()) { + return EscapesFunctionError::NoParamForArg; + } + auto Param = FuncDecl->getParamDecl(ArgNum); + + // We want both the argument and the parameter to be of pointer type. + // FIXME: this is enough for the DanglingOnTemporaryChecker, because the + // analysed methods only return pointers, but more cases should probably be + // handled when we want to use this function more broadly. + if ((!Arg->getType().getNonReferenceType()->isPointerType() && + Arg->getType().getNonReferenceType()->isBuiltinType()) || + (!Param->getType().getNonReferenceType()->isPointerType() && + Param->getType().getNonReferenceType()->isBuiltinType())) { + return EscapesFunctionError::ArgAndParamNotPointers; + } + + // We retrieve the usages of the parameter in the function. + auto Usages = getUsageAsRvalue(Param, FuncDecl); + + // For each usage, we check if it doesn't allow the parameter to escape the + // function scope. + for (auto Usage : Usages) { + // In the case of an assignment. + if (auto BinOp = dyn_cast<BinaryOperator>(Usage)) { + // We retrieve the declaration the parameter is assigned to. + auto DeclRef = dyn_cast<DeclRefExpr>(BinOp->getLHS()); + if (!DeclRef) { + continue; + } + + if (auto ParamDeclaration = dyn_cast<ParmVarDecl>(DeclRef->getDecl())) { + // This is the case where the parameter escapes through another + // parameter. + + // FIXME: for now we only care about references because we only detect + // trivial LHS with just a DeclRefExpr, and not more complex cases like: + // void func(Type* param1, Type** param2) { + // *param2 = param1; + // } + // This should be fixed when we have better/more helper functions to + // help deal with this kind of lvalue expressions. + if (!ParamDeclaration->getType()->isReferenceType()) { + continue; + } + + return std::make_tuple(Usage, (const Decl *)ParamDeclaration); + } else if (auto VarDeclaration = dyn_cast<VarDecl>(DeclRef->getDecl())) { + // This is the case where the parameter escapes through a global/static + // variable. + if (!VarDeclaration->hasGlobalStorage()) { + continue; + } + + return std::make_tuple(Usage, (const Decl *)VarDeclaration); + } else if (auto FieldDeclaration = + dyn_cast<FieldDecl>(DeclRef->getDecl())) { + // This is the case where the parameter escapes through a field. + + return std::make_tuple(Usage, (const Decl *)FieldDeclaration); + } + } else if (isa<ReturnStmt>(Usage)) { + // This is the case where the parameter escapes through the return value + // of the function. + if (!FuncDecl->getReturnType()->isPointerType() && + !FuncDecl->getReturnType()->isReferenceType()) { + continue; + } + + return std::make_tuple(Usage, (const Decl *)FuncDecl); + } + } + + // No early-return, this means that we haven't found any case of funciton + // escaping and that therefore the parameter remains in the function scope. + return std::make_tuple((const Stmt *)nullptr, (const Decl *)nullptr); +} diff --git a/build/clang-plugin/VariableUsageHelpers.h b/build/clang-plugin/VariableUsageHelpers.h new file mode 100644 index 0000000000..d498857eea --- /dev/null +++ b/build/clang-plugin/VariableUsageHelpers.h @@ -0,0 +1,63 @@ +/* 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/. */ + +#ifndef VariableUsageHelpers_h__ +#define VariableUsageHelpers_h__ + +#include "plugin.h" + +/// Returns a list of the statements where the given declaration is used as an +/// rvalue (within the provided function). +/// +/// WARNING: incomplete behaviour/implementation for general-purpose use outside +/// of escapesFunction(). This only detects very basic usages (see +/// implementation for more details). +std::vector<const Stmt *> getUsageAsRvalue(const ValueDecl *ValueDeclaration, + const FunctionDecl *FuncDecl); + +/// This is the error enumeration for escapesFunction(), describing all the +/// possible error cases. +enum class EscapesFunctionError { + ConstructorDeclNotFound = 1, + FunctionDeclNotFound, + FunctionIsBuiltin, + FunctionIsVariadic, + ExprNotInCall, + NoParamForArg, + ArgAndParamNotPointers +}; + +/// Required by the std::error_code system to convert our enum into a general +/// error code. +std::error_code make_error_code(EscapesFunctionError); + +/// Returns a (statement, decl) tuple if an argument from an argument list +/// escapes the function scope through globals/statics/other things. The +/// statement is where the value escapes the function, while the declaration +/// points to what it escapes through. If the argument doesn't escape the +/// function, the tuple will only contain nullptrs. +/// If the analysis runs into an unexpected error or into an unimplemented +/// configuration, it will return an error_code of type EscapesFunctionError +/// representing the precise issue. +/// +/// WARNING: incomplete behaviour/implementation for general-purpose use outside +/// of DanglingOnTemporaryChecker. This only covers a limited set of cases, +/// mainly in terms of arguments and parameter types. +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const FunctionDecl *FuncDecl, + const Expr *const *Arguments, unsigned NumArgs); + +/// Helper function taking a call expression. +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const CallExpr *Call); + +/// Helper function taking a construct expression. +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const CXXConstructExpr *Construct); + +/// Helper function taking an operator call expression. +ErrorOr<std::tuple<const Stmt *, const Decl *>> +escapesFunction(const Expr *Arg, const CXXOperatorCallExpr *OpCall); + +#endif diff --git a/build/clang-plugin/alpha/AlphaChecks.inc b/build/clang-plugin/alpha/AlphaChecks.inc new file mode 100644 index 0000000000..4e0d050edd --- /dev/null +++ b/build/clang-plugin/alpha/AlphaChecks.inc @@ -0,0 +1,10 @@ +/* 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/. */ + +// The list of checker classes that are compatible with clang-tidy and are considered +// to be in alpha stage development. + +// CHECK(AlphaChecker, "alpha-checker") +CHECK(NonStdMoveChecker, "non-std-move") +CHECK(TempRefPtrChecker, "performance-temp-refptr") diff --git a/build/clang-plugin/alpha/AlphaIncludes.inc b/build/clang-plugin/alpha/AlphaIncludes.inc new file mode 100644 index 0000000000..376c35b878 --- /dev/null +++ b/build/clang-plugin/alpha/AlphaIncludes.inc @@ -0,0 +1,2 @@ +#include "NonStdMoveChecker.h" +#include "TempRefPtrChecker.h" diff --git a/build/clang-plugin/alpha/NonStdMoveChecker.cpp b/build/clang-plugin/alpha/NonStdMoveChecker.cpp new file mode 100644 index 0000000000..e9ede00cea --- /dev/null +++ b/build/clang-plugin/alpha/NonStdMoveChecker.cpp @@ -0,0 +1,115 @@ +/* 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 "NonStdMoveChecker.h" +#include "CustomMatchers.h" +#include "clang/Lex/Lexer.h" + +constexpr const char *kConstructExpr = "construct"; +constexpr const char *kOperatorCallExpr = "operator-call"; +constexpr const char *kSourceExpr = "source-expr"; +constexpr const char *kMaterializeExpr = "materialize-expr"; + +void NonStdMoveChecker::registerMatchers(MatchFinder *AstMatcher) { + + // Assignment through forget + AstMatcher->addMatcher( + cxxOperatorCallExpr( + hasOverloadedOperatorName("="), + hasAnyArgument(materializeTemporaryExpr( + has(cxxBindTemporaryExpr(has(cxxMemberCallExpr( + has(memberExpr(member(hasName("forget")))), + on(expr().bind(kSourceExpr))))))) + .bind(kMaterializeExpr))) + .bind(kOperatorCallExpr), + this); + + // Construction through forget + + AstMatcher->addMatcher( + cxxConstructExpr(has(materializeTemporaryExpr( + has(cxxBindTemporaryExpr(has(cxxMemberCallExpr( + has(memberExpr(member(hasName("forget")))), + on(expr().bind(kSourceExpr))))))) + .bind(kMaterializeExpr))) + .bind(kConstructExpr), + this); +} + +#if CLANG_VERSION_FULL >= 1600 +std::optional<FixItHint> +#else +Optional<FixItHint> +#endif +NonStdMoveChecker::makeFixItHint(const MatchFinder::MatchResult &Result, + const Expr *const TargetExpr) { + const auto *MaterializeExpr = Result.Nodes.getNodeAs<Expr>(kMaterializeExpr); + + // TODO: In principle, we should check here if TargetExpr if + // assignable/constructible from std::move(SourceExpr). Not sure how to do + // this. Currently, we only filter out the case where the targetTypeTemplate + // is already_AddRefed, where this is known to fail. + + const auto *targetTypeTemplate = getNonTemplateSpecializedCXXRecordDecl( + TargetExpr->getType().getCanonicalType()); + const auto *sourceTypeTemplate = getNonTemplateSpecializedCXXRecordDecl( + MaterializeExpr->getType().getCanonicalType()); + + if (targetTypeTemplate && sourceTypeTemplate) { + // TODO is there a better way to check this than by name? otherwise, the + // names probably are necessarily unique in the scope + if (targetTypeTemplate->getName() == sourceTypeTemplate->getName() && + targetTypeTemplate->getName() == "already_AddRefed") { + return {}; + } + } + + const auto *SourceExpr = Result.Nodes.getNodeAs<Expr>(kSourceExpr); + + const auto sourceText = Lexer::getSourceText( + CharSourceRange::getTokenRange(SourceExpr->getSourceRange()), + Result.Context->getSourceManager(), Result.Context->getLangOpts()); + + return FixItHint::CreateReplacement(MaterializeExpr->getSourceRange(), + ("std::move(" + sourceText + ")").str()); +} + +void NonStdMoveChecker::check(const MatchFinder::MatchResult &Result) { + // TODO: Include source and target type name in messages. + + const auto *OCE = + Result.Nodes.getNodeAs<CXXOperatorCallExpr>(kOperatorCallExpr); + + if (OCE) { + const auto *refPtrDecl = + dyn_cast<const CXXRecordDecl>(OCE->getCalleeDecl()->getDeclContext()); + + const auto XFixItHint = makeFixItHint(Result, OCE); + // TODO: produce diagnostic but no FixItHint in this case? + if (XFixItHint) { + diag(OCE->getBeginLoc(), "non-standard move assignment to %0 obscures " + "move, use std::move instead") + << refPtrDecl << *XFixItHint; + } + } + + const auto *CoE = Result.Nodes.getNodeAs<CXXConstructExpr>(kConstructExpr); + + if (CoE) { + const auto *refPtrDecl = + dyn_cast<const CXXRecordDecl>(CoE->getConstructor()->getDeclContext()); + + const auto XFixItHint = makeFixItHint(Result, CoE); + // TODO: produce diagnostic but no FixItHint in this case? + if (XFixItHint) { + diag(CoE->getBeginLoc(), "non-standard move construction of %0 obscures " + "move, use std::move instead") + << refPtrDecl << *XFixItHint; + } + } + + // TODO: What about swap calls immediately after default-construction? These + // can also be replaced by move-construction, but this may require + // control-flow analysis. +} diff --git a/build/clang-plugin/alpha/NonStdMoveChecker.h b/build/clang-plugin/alpha/NonStdMoveChecker.h new file mode 100644 index 0000000000..bb0565cdf0 --- /dev/null +++ b/build/clang-plugin/alpha/NonStdMoveChecker.h @@ -0,0 +1,29 @@ +/* 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/. */ + +#ifndef NonStdMoveChecker_h__ +#define NonStdMoveChecker_h__ + +#include "plugin.h" + +class NonStdMoveChecker final : public BaseCheck { +public: + NonStdMoveChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; + +private: + CompilerInstance *CI; + + static +#if CLANG_VERSION_FULL >= 1600 + std::optional<FixItHint> +#else + Optional<FixItHint> +#endif + makeFixItHint(const MatchFinder::MatchResult &Result, const Expr *TargetExpr); +}; + +#endif diff --git a/build/clang-plugin/alpha/TempRefPtrChecker.cpp b/build/clang-plugin/alpha/TempRefPtrChecker.cpp new file mode 100644 index 0000000000..0a4d078368 --- /dev/null +++ b/build/clang-plugin/alpha/TempRefPtrChecker.cpp @@ -0,0 +1,57 @@ +/* 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 "TempRefPtrChecker.h" +#include "CustomMatchers.h" + +constexpr const char *kCallExpr = "call-expr"; +constexpr const char *kOperatorCallExpr = "operator-call"; + +void TempRefPtrChecker::registerMatchers(MatchFinder *AstMatcher) { + AstMatcher->addMatcher( + cxxOperatorCallExpr( + hasOverloadedOperatorName("->"), + hasAnyArgument(implicitCastExpr( + hasSourceExpression(materializeTemporaryExpr(anyOf( + hasDescendant(callExpr().bind(kCallExpr)), anything()))))), + callee(hasDeclContext(classTemplateSpecializationDecl( + isSmartPtrToRefCountedDecl(), + // ignore any calls on temporary RefPtr<MozPromise<T>>, + // since these typically need to be locally ref-counted, + // e.g. in Then chains where the promise might be resolved + // concurrently + unless(hasTemplateArgument( + 0, refersToType(hasDeclaration( + cxxRecordDecl(hasName("mozilla::MozPromise")))))))))) + .bind(kOperatorCallExpr), + this); +} + +void TempRefPtrChecker::check(const MatchFinder::MatchResult &Result) { + const auto *OCE = + Result.Nodes.getNodeAs<CXXOperatorCallExpr>(kOperatorCallExpr); + + const auto *refPtrDecl = + dyn_cast<const CXXRecordDecl>(OCE->getCalleeDecl()->getDeclContext()); + + diag(OCE->getOperatorLoc(), + "performance issue: temporary %0 is only dereferenced here once which " + "involves short-lived AddRef/Release calls") + << refPtrDecl; + + const auto *InnerCE = Result.Nodes.getNodeAs<CallExpr>(kCallExpr); + if (InnerCE) { + const auto functionName = + InnerCE->getCalleeDecl()->getAsFunction()->getQualifiedNameAsString(); + + if (functionName != "mozilla::MakeRefPtr") { + diag( + OCE->getOperatorLoc(), + "consider changing function %0 to return a raw reference instead (be " + "sure that the pointee is held alive by someone else though!)", + DiagnosticIDs::Note) + << functionName; + } + } +} diff --git a/build/clang-plugin/alpha/TempRefPtrChecker.h b/build/clang-plugin/alpha/TempRefPtrChecker.h new file mode 100644 index 0000000000..ebed50c3a0 --- /dev/null +++ b/build/clang-plugin/alpha/TempRefPtrChecker.h @@ -0,0 +1,21 @@ +/* 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/. */ + +#ifndef TempRefPtrChecker_h__ +#define TempRefPtrChecker_h__ + +#include "plugin.h" + +class TempRefPtrChecker final : public BaseCheck { +public: + TempRefPtrChecker(StringRef CheckName, ContextType *Context = nullptr) + : BaseCheck(CheckName, Context) {} + void registerMatchers(MatchFinder *AstMatcher) override; + void check(const MatchFinder::MatchResult &Result) override; + +private: + CompilerInstance *CI; +}; + +#endif diff --git a/build/clang-plugin/alpha/sources.mozbuild b/build/clang-plugin/alpha/sources.mozbuild new file mode 100644 index 0000000000..03ed90d3c1 --- /dev/null +++ b/build/clang-plugin/alpha/sources.mozbuild @@ -0,0 +1,10 @@ +# -*- 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/. + +HOST_SOURCES += [ + "NonStdMoveChecker.cpp", + "TempRefPtrChecker.cpp", +] diff --git a/build/clang-plugin/alpha/tests/TestNonStdMove.cpp b/build/clang-plugin/alpha/tests/TestNonStdMove.cpp new file mode 100644 index 0000000000..379f9655dd --- /dev/null +++ b/build/clang-plugin/alpha/tests/TestNonStdMove.cpp @@ -0,0 +1,125 @@ +#include <mozilla/RefPtr.h> + +// we can't include nsCOMPtr.h here, so let's redefine a basic version +template<typename T> +struct nsCOMPtr { + nsCOMPtr() = default; + + template<typename U> + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>&& aSrc); + + template<typename U> + nsCOMPtr& operator=(already_AddRefed<U>&& aSrc); +}; + + +using namespace mozilla; + +struct RefCountedBase { + void AddRef(); + void Release(); + + void method_test(); +}; + +struct RefCountedDerived : RefCountedBase {}; + +struct RefCountedBaseHolder { + RefPtr<RefCountedBase> GetRefCountedBase() const { + return mRefCountedBase; + } + +private: + RefPtr<RefCountedBase> mRefCountedBase = MakeRefPtr<RefCountedBase>(); +}; + + +void test_assign_same_type() { + RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>(); + RefPtr<RefCountedBase> b; + + b = a.forget(); // expected-warning {{non-standard move assignment}} +} + +void test_assign_implicit_cast() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + RefPtr<RefCountedBase> b; + + b = a.forget(); // expected-warning {{non-standard move assignment}} +} + +void test_assign_different_template() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + nsCOMPtr<RefCountedBase> b; + + b = a.forget(); // expected-warning {{non-standard move assignment}} +} + +void test_construct_different_template() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + nsCOMPtr<RefCountedBase> b = a.forget(); // expected-warning {{non-standard move construction}} +} + +void test_assign_already_addrefed() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + already_AddRefed<RefCountedDerived> b; + + b = a.forget(); +} + +void test_construct_already_addrefed() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + already_AddRefed<RefCountedDerived> b = a.forget(); +} + +void test_construct_same_type() { + RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>(); + RefPtr<RefCountedBase> b = a.forget(); // expected-warning {{non-standard move construction}} +} + +void test_construct_implicit_cast() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + RefPtr<RefCountedBase> b = a.forget(); // expected-warning {{non-standard move construction}} +} + +void test_construct_brace_same_type() { + RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>(); + auto b = RefPtr<RefCountedBase>{a.forget()}; // expected-warning {{non-standard move construction}} +} + +void test_construct_brace_implicit_cast() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + auto b = RefPtr<RefCountedBase>{a.forget()}; // expected-warning {{non-standard move construction}} +} + +void test_construct_function_style_same_type() { + RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>(); + auto b = RefPtr<RefCountedBase>(a.forget()); // expected-warning {{non-standard move construction}} +} + +void test_construct_function_style_implicit_cast() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + auto b = RefPtr<RefCountedBase>(a.forget()); // expected-warning {{non-standard move construction}} +} + +void test_construct_result_type() { + RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>(); + already_AddRefed<RefCountedBase> b = a.forget(); +} + +void test_construct_implicitly_cast_result_type() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + already_AddRefed<RefCountedBase> b = a.forget(); +} + +void foo(already_AddRefed<RefCountedBase>&& aArg); + +void test_call_with_result_type() { + RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>(); + foo(a.forget()); +} + +void test_call_with_implicitly_cast_result_type() { + RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>(); + foo(a.forget()); +} diff --git a/build/clang-plugin/alpha/tests/TestTempRefPtr.cpp b/build/clang-plugin/alpha/tests/TestTempRefPtr.cpp new file mode 100644 index 0000000000..51f756b8e6 --- /dev/null +++ b/build/clang-plugin/alpha/tests/TestTempRefPtr.cpp @@ -0,0 +1,52 @@ +#include <mozilla/RefPtr.h> + +using namespace mozilla; + +struct RefCountedBase { + void AddRef(); + void Release(); + + void method_test(); +}; + +struct RefCountedBaseHolder { + RefPtr<RefCountedBase> GetRefCountedBase() const { + return mRefCountedBase; + } + +private: + RefPtr<RefCountedBase> mRefCountedBase = MakeRefPtr<RefCountedBase>(); +}; + + +void test_arrow_temporary_new_refptr_function_style_cast() { + RefPtr<RefCountedBase>(new RefCountedBase())->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} +} + +void test_arrow_temporary_new_refptr_brace() { + RefPtr<RefCountedBase>{new RefCountedBase()}->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} +} + +void test_arrow_temporary_new_c_style_cast() { + ((RefPtr<RefCountedBase>)(new RefCountedBase()))->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} +} + +void test_arrow_temporary_new_static_cast() { + static_cast<RefPtr<RefCountedBase>>(new RefCountedBase())->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} +} + +void test_arrow_temporary_new_refptr_makerefptr() { + MakeRefPtr<RefCountedBase>()->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} +} + +void test_arrow_temporary_get_refptr_from_member_function() { + const RefCountedBaseHolder holder; + holder.GetRefCountedBase()->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} expected-note {{consider changing function RefCountedBaseHolder::GetRefCountedBase to return a raw reference instead}} +} + +void test_ref(RefCountedBase &aRefCountedBase); + +void test_star_temporary_new_refptr_function_style_cast() { + // TODO: Should we warn about operator* as well? + test_ref(*RefPtr<RefCountedBase>(new RefCountedBase())); +} diff --git a/build/clang-plugin/alpha/tests/sources.mozbuild b/build/clang-plugin/alpha/tests/sources.mozbuild new file mode 100644 index 0000000000..6268746232 --- /dev/null +++ b/build/clang-plugin/alpha/tests/sources.mozbuild @@ -0,0 +1,10 @@ +# -*- 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/. + +SOURCES += [ + "TestNonStdMove.cpp", + "TestTempRefPtr.cpp", +] diff --git a/build/clang-plugin/external/CustomAttributes.inc b/build/clang-plugin/external/CustomAttributes.inc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/build/clang-plugin/external/CustomAttributes.inc diff --git a/build/clang-plugin/external/ExternalChecks.inc b/build/clang-plugin/external/ExternalChecks.inc new file mode 100644 index 0000000000..d5f0b0334c --- /dev/null +++ b/build/clang-plugin/external/ExternalChecks.inc @@ -0,0 +1,8 @@ +/* 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/. */ + +// Placeholder file to be overwritten with external checks during build +// The list of checker classes that are compatible with clang-tidy-external. + +// CHECK(ExternalChecker, "external-checker") diff --git a/build/clang-plugin/external/ExternalIncludes.inc b/build/clang-plugin/external/ExternalIncludes.inc new file mode 100644 index 0000000000..9fda16de8a --- /dev/null +++ b/build/clang-plugin/external/ExternalIncludes.inc @@ -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/. */ + +// Placeholder file to be overwritten with external checks during build +// The list of #include directives necessary for the checker classes that +// are compatible with clang-tidy-external. + +// #include "ExternalChecker.h" diff --git a/build/clang-plugin/external/sources.mozbuild b/build/clang-plugin/external/sources.mozbuild new file mode 100644 index 0000000000..01daf87080 --- /dev/null +++ b/build/clang-plugin/external/sources.mozbuild @@ -0,0 +1,10 @@ +# -*- 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/. + +# Placeholder file to be overwritten with external checks during build +HOST_SOURCES += [ + # 'ExternalChecker.cpp', +] diff --git a/build/clang-plugin/external/tests/sources.mozbuild b/build/clang-plugin/external/tests/sources.mozbuild new file mode 100644 index 0000000000..1f3b4a61c9 --- /dev/null +++ b/build/clang-plugin/external/tests/sources.mozbuild @@ -0,0 +1,10 @@ +# -*- 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/. + +# Placeholder file to be overwritten with external checks during build +SOURCES += [ + # 'ExternalTest.cpp', +] diff --git a/build/clang-plugin/import_mozilla_checks.py b/build/clang-plugin/import_mozilla_checks.py new file mode 100755 index 0000000000..d573dafcf1 --- /dev/null +++ b/build/clang-plugin/import_mozilla_checks.py @@ -0,0 +1,177 @@ +#!/usr/bin/python3 +# 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/. + +import errno +import glob +import os +import shutil + +import ThirdPartyPaths +import ThreadAllows + + +def copy_dir_contents(src, dest): + for f in glob.glob("%s/*" % src): + try: + destname = "%s/%s" % (dest, os.path.basename(f)) + if os.path.isdir(f): + shutil.copytree(f, destname) + else: + shutil.copy2(f, destname) + except OSError as e: + if e.errno == errno.ENOTDIR: + shutil.copy2(f, destname) + elif e.errno == errno.EEXIST: + if os.path.isdir(f): + copy_dir_contents(f, destname) + else: + os.remove(destname) + shutil.copy2(f, destname) + else: + raise Exception("Directory not copied. Error: %s" % e) + + +def write_cmake(module_path, import_options): + names = [" " + os.path.basename(f) for f in glob.glob("%s/*.cpp" % module_path)] + + if import_options["external"]: + names += [ + " " + os.path.join("external", os.path.basename(f)) + for f in glob.glob("%s/external/*.cpp" % (module_path)) + ] + + if import_options["alpha"]: + names += [ + " " + os.path.join("alpha", os.path.basename(f)) + for f in glob.glob("%s/alpha/*.cpp" % (module_path)) + ] + + with open(os.path.join(module_path, "CMakeLists.txt"), "w") as f: + f.write( + """set(LLVM_LINK_COMPONENTS support) + +add_definitions( -DCLANG_TIDY ) + +add_clang_library(clangTidyMozillaModule + ThirdPartyPaths.cpp +%(names)s + + LINK_LIBS + clangTidy + clangTidyReadabilityModule + clangTidyUtils + clangTidyMPIModule + ) + +clang_target_link_libraries(clangTidyMozillaModule + PRIVATE + clangAST + clangASTMatchers + clangBasic + clangLex + )""" + % {"names": "\n".join(names)} + ) + + +def add_moz_module(cmake_path): + with open(cmake_path, "r") as f: + lines = f.readlines() + f.close() + + try: + idx = lines.index("set(ALL_CLANG_TIDY_CHECKS\n") + lines.insert(idx + 1, " clangTidyMozillaModule\n") + + with open(cmake_path, "w") as f: + for line in lines: + f.write(line) + except ValueError: + raise Exception("Unable to find ALL_CLANG_TIDY_CHECKS in {}".format(cmake_path)) + + +def write_third_party_paths(mozilla_path, module_path): + tpp_txt = os.path.join(mozilla_path, "../../tools/rewriting/ThirdPartyPaths.txt") + generated_txt = os.path.join(mozilla_path, "../../tools/rewriting/Generated.txt") + with open(os.path.join(module_path, "ThirdPartyPaths.cpp"), "w") as f: + ThirdPartyPaths.generate(f, tpp_txt, generated_txt) + + +def generate_thread_allows(mozilla_path, module_path): + names = os.path.join(mozilla_path, "../../build/clang-plugin/ThreadAllows.txt") + files = os.path.join(mozilla_path, "../../build/clang-plugin/ThreadFileAllows.txt") + with open(os.path.join(module_path, "ThreadAllows.h"), "w") as f: + f.write( + ThreadAllows.generate_allows(allowed_names=[names], allowed_files=[files]) + ) + + +def do_import(mozilla_path, clang_tidy_path, import_options): + module = "mozilla" + module_path = os.path.join(clang_tidy_path, module) + try: + os.makedirs(module_path) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + copy_dir_contents(mozilla_path, module_path) + write_third_party_paths(mozilla_path, module_path) + generate_thread_allows(mozilla_path, module_path) + write_cmake(module_path, import_options) + add_moz_module(os.path.join(module_path, "..", "CMakeLists.txt")) + with open(os.path.join(module_path, "..", "CMakeLists.txt"), "a") as f: + f.write("add_subdirectory(%s)\n" % module) + # A better place for this would be in `ClangTidyForceLinker.h` but `ClangTidyMain.cpp` + # is also OK. + with open(os.path.join(module_path, "..", "tool", "ClangTidyMain.cpp"), "a") as f: + f.write( + """ +// This anchor is used to force the linker to link the MozillaModule. +extern volatile int MozillaModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED MozillaModuleAnchorDestination = + MozillaModuleAnchorSource; +""" + ) + + +def main(): + import argparse + + parser = argparse.ArgumentParser( + usage="import_mozilla_checks.py <mozilla-clang-plugin-path> <clang-tidy-path> [option]", + description="Imports the Mozilla static analysis checks into a clang-tidy source tree.", + ) + parser.add_argument( + "mozilla_path", help="Full path to mozilla-central/build/clang-plugin" + ) + parser.add_argument( + "clang_tidy_path", help="Full path to llvm-project/clang-tools-extra/clang-tidy" + ) + parser.add_argument( + "--import-alpha", + help="Enable import of in-tree alpha checks", + action="store_true", + ) + parser.add_argument( + "--import-external", + help="Enable import of in-tree external checks", + action="store_true", + ) + args = parser.parse_args() + + if not os.path.isdir(args.mozilla_path): + print("Invalid path to mozilla clang plugin") + + if not os.path.isdir(args.clang_tidy_path): + print("Invalid path to clang-tidy source directory") + + import_options = {"alpha": args.import_alpha, "external": args.import_external} + + do_import(args.mozilla_path, args.clang_tidy_path, import_options) + + +if __name__ == "__main__": + main() diff --git a/build/clang-plugin/moz.build b/build/clang-plugin/moz.build new file mode 100644 index 0000000000..c9c2c520db --- /dev/null +++ b/build/clang-plugin/moz.build @@ -0,0 +1,129 @@ +# -*- 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/. + +HostSharedLibrary("clang-plugin") + +HOST_SOURCES += ["!ThirdPartyPaths.cpp"] + +HOST_SOURCES += [ + "ArithmeticArgChecker.cpp", + "AssertAssignmentChecker.cpp", + "CanRunScriptChecker.cpp", + "CustomAttributes.cpp", + "CustomTypeAnnotation.cpp", + "DanglingOnTemporaryChecker.cpp", + "DiagnosticsMatcher.cpp", + "ExplicitImplicitChecker.cpp", + "ExplicitOperatorBoolChecker.cpp", + "JSHandleRootedTypedefChecker.cpp", + "KnownLiveChecker.cpp", + "KungFuDeathGripChecker.cpp", + "MozCheckAction.cpp", + "MustOverrideChecker.cpp", + "MustReturnFromCallerChecker.cpp", + "NaNExprChecker.cpp", + "NeedsNoVTableTypeChecker.cpp", + "NoAddRefReleaseOnReturnChecker.cpp", + "NoAutoTypeChecker.cpp", + "NoDuplicateRefCntMemberChecker.cpp", + "NoExplicitMoveConstructorChecker.cpp", + "NoNewThreadsChecker.cpp", + "NonMemMovableMemberChecker.cpp", + "NonMemMovableTemplateArgChecker.cpp", + "NonParamInsideFunctionDeclChecker.cpp", + "NonTrivialTypeInFfiChecker.cpp", + "NoPrincipalGetURI.cpp", + "NoUsingNamespaceMozillaJavaChecker.cpp", + "OverrideBaseCallChecker.cpp", + "OverrideBaseCallUsageChecker.cpp", + "ParamTraitsEnumChecker.cpp", + "RefCountedCopyConstructorChecker.cpp", + "RefCountedInsideLambdaChecker.cpp", + "RefCountedThisInsideConstructorChecker.cpp", + "ScopeChecker.cpp", + "SprintfLiteralChecker.cpp", + "TrivialCtorDtorChecker.cpp", + "TrivialDtorChecker.cpp", + "VariableUsageHelpers.cpp", +] + +# Ideally, we wouldn't have compile-time choices wrt checks. bug 1617153. +if CONFIG["OS_ARCH"] == "WINNT": + HOST_DEFINES["TARGET_IS_WINDOWS"] = True + HOST_SOURCES += [ + "FopenUsageChecker.cpp", + "LoadLibraryUsageChecker.cpp", + ] + +if CONFIG["ENABLE_MOZSEARCH_PLUGIN"]: + HOST_SOURCES += [ + "mozsearch-plugin/BindingOperations.cpp", + "mozsearch-plugin/FileOperations.cpp", + "mozsearch-plugin/from-clangd/HeuristicResolver.cpp", + "mozsearch-plugin/MozsearchIndexer.cpp", + "mozsearch-plugin/StringOperations.cpp", + ] + +GeneratedFile( + "ThirdPartyPaths.cpp", + script="ThirdPartyPaths.py", + entry_point="generate", + inputs=[ + "/tools/rewriting/ThirdPartyPaths.txt", + "/tools/rewriting/Generated.txt", + ], +) + +GeneratedFile( + "ThreadAllows.h", + script="ThreadAllows.py", + entry_point="generate_file", + inputs=[ + "/build/clang-plugin/ThreadAllows.txt", + "/build/clang-plugin/ThreadFileAllows.txt", + ], +) + +HOST_COMPILE_FLAGS["STL"] = [] +HOST_COMPILE_FLAGS["VISIBILITY"] = [] + +# libc++ is required to build plugins against clang on OS X. +if CONFIG["HOST_OS_ARCH"] == "Darwin": + HOST_CXXFLAGS += ["-stdlib=libc++"] + +# As of clang 8, llvm-config doesn't output the flags used to build clang +# itself, so we don't end up with -fPIC as a side effect. llvm.org/PR8220 +if CONFIG["HOST_OS_ARCH"] != "WINNT": + HOST_CXXFLAGS += ["-fPIC"] + +DIRS += [ + "tests", +] + +include("external/sources.mozbuild") + +if CONFIG["ENABLE_CLANG_PLUGIN_ALPHA"]: + HOST_DEFINES["MOZ_CLANG_PLUGIN_ALPHA"] = "1" + include("alpha/sources.mozbuild") + +# In the current moz.build world, we need to override essentially every +# variable to limit ourselves to what we need to build the clang plugin. +if CONFIG["HOST_OS_ARCH"] == "WINNT": + extra_cxxflags = ["-GR-", "-EHsc"] + # Clang 14 headers enforce a requirement upon Visual Studio 2019 headers, + # for support of newer C++ versions, which is necessary for clang itself, + # but as of writing, it's not necessary for the plugin code, so enable + # the escape hatch, at least until we generally upgrade to VS 2019. + HOST_DEFINES["LLVM_FORCE_USE_OLD_TOOLCHAIN"] = True +else: + extra_cxxflags = ["-fno-rtti", "-fno-exceptions"] + +if CONFIG["LLVM_CXXFLAGS"]: + HOST_COMPILE_FLAGS["HOST_CXXFLAGS"] = CONFIG["LLVM_CXXFLAGS"] + extra_cxxflags + +# Avoid -DDEBUG=1 on the command line, which conflicts with a #define +# DEBUG(...) in llvm headers. +DEFINES["DEBUG"] = False diff --git a/build/clang-plugin/mozsearch-plugin/BindingOperations.cpp b/build/clang-plugin/mozsearch-plugin/BindingOperations.cpp new file mode 100644 index 0000000000..79f7f3aebf --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/BindingOperations.cpp @@ -0,0 +1,792 @@ +/* -*- 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 "BindingOperations.h" + +#include <clang/AST/Attr.h> +#include <clang/AST/Expr.h> +#include <clang/AST/RecursiveASTVisitor.h> + +#include <algorithm> +#include <array> +#include <cuchar> +#include <set> +#include <string> +#include <unordered_map> +#include <vector> + +#ifdef __cpp_lib_optional +#include <optional> +template<typename T> using optional = std::optional<T>; +#else +#include <llvm/ADT/Optional.h> +template<typename T> using optional = clang::Optional<T>; +#endif + +using namespace clang; + +namespace { + +template<typename InputIt> +bool hasReverseQualifiedName(InputIt first, InputIt last, const NamedDecl &tag) +{ + const NamedDecl *currentDecl = &tag; + InputIt currentName; + for (currentName = first; currentName != last; currentName++) { + if (!currentDecl || !currentDecl->getIdentifier() || currentDecl->getName() != *currentName) + return false; + + currentDecl = dyn_cast<NamedDecl>(currentDecl->getDeclContext()); + } + if (currentName != last) + return false; + + if (currentDecl != nullptr) + return false; + + return true; +} + +bool isMozillaJniObjectBase(const CXXRecordDecl &klass) +{ + const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"}; + return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass); +} + +bool isMozillaJniNativeImpl(const CXXRecordDecl &klass) +{ + const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"}; + return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass); +} + +const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt) +{ + for (const auto *decl : strukt.decls()) { + const auto *namedDecl = dyn_cast<VarDecl>(decl); + if (!namedDecl) + continue; + + if (!namedDecl->getIdentifier() || namedDecl->getName() != name) + continue; + + return namedDecl; + } + + return {}; +} + +optional<StringRef> nameFieldValue(const RecordDecl &strukt) +{ + const auto *nameField = dyn_cast_or_null<VarDecl>(fieldNamed("name", strukt)); + if (!nameField) + return {}; + + const auto *def = nameField->getDefinition(); + if (!def) + return {}; + + const auto *name = dyn_cast_or_null<StringLiteral>(def->getInit()); + if (!name) + return {}; + + return name->getString(); +} + +struct AbstractBinding { + // Subset of tools/analysis/BindingSlotLang + enum class Lang { + Cpp, + Jvm, + }; + static constexpr size_t LangLength = 2; + static constexpr std::array<StringRef, LangLength> langNames = { + "cpp", + "jvm", + }; + + static optional<Lang> langFromString(StringRef langName) + { + const auto it = std::find(langNames.begin(), langNames.end(), langName); + if (it == langNames.end()) + return {}; + + return Lang(it - langNames.begin()); + } + static StringRef stringFromLang(Lang lang) + { + return langNames[size_t(lang)]; + } + + // Subset of tools/analysis/BindingSlotKind + enum class Kind { + Class, + Method, + Getter, + Setter, + Const, + }; + static constexpr size_t KindLength = 5; + static constexpr std::array<StringRef, KindLength> kindNames = { + "class", + "method", + "getter", + "setter", + "const", + }; + + static optional<Kind> kindFromString(StringRef kindName) + { + const auto it = std::find(kindNames.begin(), kindNames.end(), kindName); + if (it == kindNames.end()) + return {}; + + return Kind(it - kindNames.begin()); + } + static StringRef stringFromKind(Kind kind) + { + return kindNames[size_t(kind)]; + } + + Lang lang; + Kind kind; + StringRef symbol; +}; +constexpr size_t AbstractBinding::KindLength; +constexpr std::array<StringRef, AbstractBinding::KindLength> AbstractBinding::kindNames; +constexpr size_t AbstractBinding::LangLength; +constexpr std::array<StringRef, AbstractBinding::LangLength> AbstractBinding::langNames; + +struct BindingTo : public AbstractBinding { + BindingTo(AbstractBinding b) : AbstractBinding(std::move(b)) {} + static constexpr StringRef ANNOTATION = "binding_to"; +}; +constexpr StringRef BindingTo::ANNOTATION; + +struct BoundAs : public AbstractBinding { + BoundAs(AbstractBinding b) : AbstractBinding(std::move(b)) {} + static constexpr StringRef ANNOTATION = "bound_as"; +}; +constexpr StringRef BoundAs::ANNOTATION; + +template<typename B> +void setBindingAttr(ASTContext &C, Decl &decl, B binding) +{ + // recent LLVM: CreateImplicit then setDelayedArgs + Expr *langExpr = StringLiteral::Create(C, AbstractBinding::stringFromLang(binding.lang), StringLiteral::UTF8, false, {}, {}); + Expr *kindExpr = StringLiteral::Create(C, AbstractBinding::stringFromKind(binding.kind), StringLiteral::UTF8, false, {}, {}); + Expr *symbolExpr = StringLiteral::Create(C, binding.symbol, StringLiteral::UTF8, false, {}, {}); + auto **args = new (C, 16) Expr *[3]{langExpr, kindExpr, symbolExpr}; + auto *attr = AnnotateAttr::CreateImplicit(C, B::ANNOTATION, args, 3); + decl.addAttr(attr); +} + +optional<AbstractBinding> readBinding(const AnnotateAttr &attr) +{ + if (attr.args_size() != 3) + return {}; + + const auto *langExpr = attr.args().begin()[0]; + const auto *kindExpr = attr.args().begin()[1]; + const auto *symbolExpr = attr.args().begin()[2]; + if (!langExpr || !kindExpr || !symbolExpr) + return {}; + + const auto *langName = dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource()); + const auto *kindName = dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource()); + const auto *symbol = dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource()); + if (!langName || !kindName || !symbol) + return {}; + + const auto lang = AbstractBinding::langFromString(langName->getString()); + const auto kind = AbstractBinding::kindFromString(kindName->getString()); + + if (!lang || !kind) + return {}; + + return AbstractBinding { + .lang = *lang, + .kind = *kind, + .symbol = symbol->getString(), + }; +} + +optional<BindingTo> getBindingTo(const Decl &decl) +{ + for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) { + if (attr->getAnnotation() != BindingTo::ANNOTATION) + continue; + + const auto binding = readBinding(*attr); + if (!binding) + continue; + + return BindingTo{*binding}; + } + return {}; +} + +// C++23: turn into generator +std::vector<BoundAs> getBoundAs(const Decl &decl) +{ + std::vector<BoundAs> found; + + for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) { + if (attr->getAnnotation() != BoundAs::ANNOTATION) + continue; + + const auto binding = readBinding(*attr); + if (!binding) + continue; + + found.push_back(BoundAs{*binding}); + } + + return found; +} + +class FindCallCall : private RecursiveASTVisitor<FindCallCall> +{ +public: + struct Result { + using Kind = AbstractBinding::Kind; + + Kind kind; + StringRef name; + }; + + static optional<Result> search(Stmt *statement) + { + FindCallCall finder; + finder.TraverseStmt(statement); + return finder.result; + } + +private: + optional<Result> result; + + friend RecursiveASTVisitor<FindCallCall>; + + optional<Result> tryParseCallCall(CallExpr *callExpr){ + const auto *callee = dyn_cast_or_null<CXXMethodDecl>(callExpr->getDirectCallee()); + if (!callee) + return {}; + + if (!callee->getIdentifier()) + return {}; + + const auto action = callee->getIdentifier()->getName(); + + if (action != "Call" && action != "Get" && action != "Set") + return {}; + + const auto *parentClass = dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent()); + + if (!parentClass) + return {}; + + const auto *parentTemplate = parentClass->getTemplateInstantiationPattern(); + + if (!parentTemplate || !parentTemplate->getIdentifier()) + return {}; + + const auto parentName = parentTemplate->getIdentifier()->getName(); + + AbstractBinding::Kind kind; + if (action == "Call") { + if (parentName == "Constructor" || parentName == "Method") { + kind = AbstractBinding::Kind::Method; + } else { + return {}; + } + } else if (parentName == "Field") { + if (action == "Get") { + kind = AbstractBinding::Kind::Getter; + } else if (action == "Set") { + kind = AbstractBinding::Kind::Setter; + } else { + return {}; + } + } else { + return {}; + } + + const auto *templateArg = parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl(); + + if (!templateArg) + return {}; + + const auto name = nameFieldValue(*templateArg); + if (!name) + return {}; + + return Result { + .kind = kind, + .name = *name, + }; + + return {}; + } + bool VisitCallExpr(CallExpr *callExpr) + { + return !(result = tryParseCallCall(callExpr)); + } +}; + +constexpr StringRef JVM_SCIP_SYMBOL_PREFIX = "S_jvm_"; + +std::string javaScipSymbol(StringRef prefix, StringRef name, AbstractBinding::Kind kind) +{ + auto symbol = (prefix + name).str(); + + switch (kind) { + case AbstractBinding::Kind::Class: + std::replace(symbol.begin(), symbol.end(), '$', '#'); + symbol += "#"; + break; + case AbstractBinding::Kind::Method: + symbol += "()."; + break; + case AbstractBinding::Kind::Const: + case AbstractBinding::Kind::Getter: + case AbstractBinding::Kind::Setter: + symbol += "."; + break; + } + + return symbol; +} + +void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl) +{ + if (const auto bindingTo = getBindingTo(decl)) { + J.attributeBegin("slotOwner"); + J.objectBegin(); + J.attribute("slotKind", AbstractBinding::stringFromKind(bindingTo->kind)); + J.attribute("slotLang", "cpp"); + J.attribute("ownerLang", AbstractBinding::stringFromLang(bindingTo->lang)); + J.attribute("sym", bindingTo->symbol); + J.objectEnd(); + J.attributeEnd(); + } +} +void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl) +{ + const auto allBoundAs = getBoundAs(decl); + if (!allBoundAs.empty()) { + J.attributeBegin("bindingSlots"); + J.arrayBegin(); + for (const auto boundAs : allBoundAs) { + J.objectBegin(); + J.attribute("slotKind", AbstractBinding::stringFromKind(boundAs.kind)); + J.attribute("slotLang", AbstractBinding::stringFromLang(boundAs.lang)); + J.attribute("ownerLang", "cpp"); + J.attribute("sym", boundAs.symbol); + J.objectEnd(); + } + J.arrayEnd(); + J.attributeEnd(); + } +} + +// The mangling scheme is documented at https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html +// The main takeaways are: +// - _0xxxx is the utf16 code unit xxxx +// - _1 is _ +// - _2 is ; +// - _3 is [ +// - __ is the separator between function name and overload specification +// - _ is otherwise the separator between packages/classes/methods +// +// This method takes a StringRef & and mutates it and can be called twice on a Jnicall function name to get +// first the demangled name +// second the demangled overload specification +// But we don't use the later for now because we have no way to map that to how SCIP resolves overloads. +optional<std::string> demangleJnicallPart(StringRef &remainder) +{ + std::string demangled; + + std::mbstate_t ps = {}; + + while (!remainder.empty()) { + switch (remainder[0]) { + case '0': { + remainder = remainder.drop_front(1); + + uint16_t codeUnit; + const auto ok = remainder.substr(1, 4).getAsInteger(16, codeUnit); + remainder = remainder.drop_front(4); + + if (!ok) // failed reading xxxx as hexadecimal from _0xxxx + return {}; + + std::array<char, MB_LEN_MAX> codePoint; + const auto mbLen = std::c16rtomb(codePoint.data(), codeUnit, &ps); + + if (mbLen == -1) // failed converting utf16 to utf8 + return {}; + + demangled += StringRef(codePoint.begin(), mbLen); + break; + } + case '1': + remainder = remainder.drop_front(1); + ps = {}; + demangled += '_'; + break; + case '2': + remainder = remainder.drop_front(1); + ps = {}; + demangled += ';'; + break; + case '3': + remainder = remainder.drop_front(1); + ps = {}; + demangled += '['; + break; + case '_': + remainder = remainder.drop_front(1); + ps = {}; + if (remainder.empty()) // the string ends with _ + return {}; + + switch (remainder[0]) { + case '0': + case '1': + case '2': + case '3': + demangled += '.'; + break; + default: + // either: + // * the string began with _[^0-3], which is not supposed to happen; or + // * we reached __[^0-3] meaning we finished the first part of the name and remainder holds the overload specification + return demangled; + } + default: + ps = {}; + demangled += '.'; + break; + } + StringRef token; + std::tie(token, remainder) = remainder.split('_'); + demangled += token; + } + + return demangled; +} + +optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName) +{ + if (!functionName.consume_front("Java_")) + return {}; + + const auto demangledName = demangleJnicallPart(functionName); + + if (!demangledName || demangledName->empty()) + return {}; + + // demangleJavaName returns something like .some.package.Class$InnerClass.method + // - prepend S_jvm_ + // - remove the leading dot + // - replace the last dot with a # + // - replace the other dots with / + // - replace $ with # + // - add the ([+overloadNumber]). suffix + auto symbol = JVM_SCIP_SYMBOL_PREFIX.str(); + symbol += demangledName->substr(1); + const auto lastDot = symbol.rfind('.'); + if (lastDot != std::string::npos) + symbol[lastDot] = '#'; + std::replace(symbol.begin(), symbol.end(), '.', '/'); + std::replace(symbol.begin(), symbol.end(), '$', '#'); + + // Keep track of how many times we have seen this method, to build the ([+overloadNumber]). suffix. + // This assumes this function is called on C function definitions in the same order the matching overloads are declared in Java. + static std::unordered_map<std::string, uint> jnicallFunctions; + auto &overloadNumber = jnicallFunctions[symbol]; + + symbol += '('; + if (overloadNumber) { + symbol += '+'; + symbol += overloadNumber; + overloadNumber++; + } + symbol += ")."; + + return symbol; +}; + +} // anonymous namespace + +// class [wrapper] : public mozilla::jni::ObjectBase<[wrapper]> +// { +// static constexpr char name[] = "[nameFieldValue]"; +// } +void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass) +{ + for (const auto &baseSpecifier : klass.bases()) { + const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl(); + if (!base) + continue; + + if (!isMozillaJniObjectBase(*base)) + continue; + + const auto name = nameFieldValue(klass); + if (!name) + continue; + + const auto symbol = javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BindingTo::Kind::Class); + const auto binding = BindingTo {{ + .lang = BindingTo::Lang::Jvm, + .kind = BindingTo::Kind::Class, + .symbol = symbol, + }}; + + setBindingAttr(C, klass, binding); + return; + } +} + +// When a Java method is marked as native, the JRE looks by default for a function +// named Java_<mangled method name>[__<mangled overload specification>]. +void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function) +{ + const auto *identifier = function.getIdentifier(); + if (!identifier) + return; + + const auto name = identifier->getName(); + const auto symbol = scipSymbolFromJnicallFunctionName(name); + if (!symbol) + return; + + const auto binding = BoundAs {{ + .lang = BindingTo::Lang::Jvm, + .kind = BindingTo::Kind::Method, + .symbol = *symbol, + }}; + + setBindingAttr(C, function, binding); +} + +// class [parent] +// { +// struct [methodStruct] { +// static constexpr char name[] = "[methodNameFieldValue]"; +// } +// [method] +// { +// ... +// mozilla::jni::{Method,Constructor,Field}<[methodStruct]>::{Call,Get,Set}(...) +// ... +// } +// } +void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method) +{ + const auto *parent = method.getParent(); + if (!parent) + return; + const auto classBinding = getBindingTo(*parent); + if (!classBinding) + return; + + auto *body = method.getBody(); + if (!body) + return; + + const auto found = FindCallCall::search(body); + if (!found) + return; + + const auto symbol = javaScipSymbol(classBinding->symbol, found->name, found->kind); + const auto binding = BindingTo {{ + .lang = BindingTo::Lang::Jvm, + .kind = found->kind, + .symbol = symbol, + }}; + + setBindingAttr(C, method, binding); +} + +// class [parent] +// { +// struct [methodStruct] { +// static constexpr char name[] = "[methodNameFieldValue]"; +// } +// [method] +// { +// ... +// mozilla::jni::{Method,Constructor,Field}<[methodStruct]>::{Call,Get,Set}(...) +// ... +// } +// } +void findBindingToJavaConstant(ASTContext &C, VarDecl &field) +{ + const auto *parent = dyn_cast_or_null<CXXRecordDecl>(field.getDeclContext()); + if (!parent) + return; + + const auto classBinding = getBindingTo(*parent); + if (!classBinding) + return; + + const auto symbol = javaScipSymbol(classBinding->symbol, field.getName(), BindingTo::Kind::Const); + const auto binding = BindingTo {{ + .lang = BindingTo::Lang::Jvm, + .kind = BindingTo::Kind::Const, + .symbol = symbol, + }}; + + setBindingAttr(C, field, binding); +} + +// class [klass] : public [wrapper]::Natives<[klass]> {...} +// class [wrapper] : public mozilla::jni::ObjectBase<[wrapper]> +// { +// static constexpr char name[] = "[nameFieldValue]"; +// +// struct [methodStruct] { +// static constexpr char name[] = "[methodNameFieldValue]"; +// } +// +// template<typename T> +// class [wrapper]::Natives : public mozilla::jni::NativeImpl<[wrapper], T> { +// static const JNINativeMethod methods[] = { +// mozilla::jni::MakeNativeMethod<[wrapper]::[methodStruct]>( +// mozilla::jni::NativeStub<[wrapper]::[methodStruct], Impl> +// ::template Wrap<&Impl::[method]>), +// } +// } +// } +void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass) +{ + for (const auto &baseSpecifier : klass.bases()) { + const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl(); + if (!base) + continue; + + for (const auto &baseBaseSpecifier : base->bases()) { + const auto *baseBase = dyn_cast_or_null<ClassTemplateSpecializationDecl>(baseBaseSpecifier.getType()->getAsCXXRecordDecl()); + if (!baseBase) + continue; + + if (!isMozillaJniNativeImpl(*baseBase)) + continue; + + const auto *wrapper = baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl(); + + if (!wrapper) + continue; + + const auto name = nameFieldValue(*wrapper); + if (!name) + continue; + + const auto javaClassSymbol = javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BoundAs::Kind::Class); + const auto classBinding = BoundAs {{ + .lang = BoundAs::Lang::Jvm, + .kind = BoundAs::Kind::Class, + .symbol = javaClassSymbol, + }}; + setBindingAttr(C, klass, classBinding); + + const auto *methodsDecl = dyn_cast_or_null<VarDecl>(fieldNamed("methods", *base)); + if (!methodsDecl) + continue; + + const auto *methodsDef = methodsDecl->getDefinition(); + if (!methodsDef) + continue; + + const auto *inits = dyn_cast_or_null<InitListExpr>(methodsDef->getInit()); + if (!inits) + continue; + + std::set<const CXXMethodDecl *> alreadyBound; + + for (const auto *init : inits->inits()) { + const auto *call = dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource()); + if (!call) + continue; + + const auto *funcDecl = call->getDirectCallee(); + if (!funcDecl) + continue; + + const auto *templateArgs = funcDecl->getTemplateSpecializationArgs(); + if (!templateArgs) + continue; + + const auto *strukt = dyn_cast_or_null<RecordDecl>(templateArgs->get(0).getAsType()->getAsRecordDecl()); + if (!strukt) + continue; + + const auto *wrapperRef = dyn_cast_or_null<DeclRefExpr>(call->getArg(0)->IgnoreUnlessSpelledInSource()); + if (!wrapperRef) + continue; + + const auto *boundRef = dyn_cast_or_null<UnaryOperator>(wrapperRef->template_arguments().front().getArgument().getAsExpr()); + if (!boundRef) + continue; + + auto addToBound = [&](CXXMethodDecl &boundDecl, uint overloadNum) { + const auto methodName = nameFieldValue(*strukt); + if (!methodName) + return; + + auto javaMethodSymbol = javaClassSymbol; + javaMethodSymbol += *methodName; + javaMethodSymbol += '('; + if (overloadNum > 0) { + javaMethodSymbol += '+'; + javaMethodSymbol += std::to_string(overloadNum); + } + javaMethodSymbol += ")."; + + const auto binding = BoundAs {{ + .lang = BoundAs::Lang::Jvm, + .kind = BoundAs::Kind::Method, + .symbol = javaMethodSymbol, + }}; + setBindingAttr(C, boundDecl, binding); + }; + + if (auto *bound = dyn_cast_or_null<DeclRefExpr>(boundRef->getSubExpr())) { + auto *method = dyn_cast_or_null<CXXMethodDecl>(bound->getDecl()); + if (!method) + continue; + addToBound(*method, 0); + } else if (const auto *bound = dyn_cast_or_null<UnresolvedLookupExpr>(boundRef->getSubExpr())) { + // XXX This is hackish + // In case of overloads it's not obvious which one we should use + // this expects the declaration order between C++ and Java to match + auto declarations = std::vector<Decl*>(bound->decls_begin(), bound->decls_end()); + auto byLocation = [](Decl *a, Decl *b){ return a->getLocation() < b->getLocation(); }; + std::sort(declarations.begin(), declarations.end(), byLocation); + + uint i = 0; + for (auto *decl : declarations) { + auto *method = dyn_cast<CXXMethodDecl>(decl); + if (!method) + continue; + if (alreadyBound.find(method) == alreadyBound.end()) { + addToBound(*method, i); + alreadyBound.insert(method); + break; + } + i++; + } + } + } + } + } +} + +void emitBindingAttributes(llvm::json::OStream &J, const Decl &decl) +{ + addSlotOwnerAttribute(J, decl); + addBindingSlotsAttribute(J, decl); +} diff --git a/build/clang-plugin/mozsearch-plugin/BindingOperations.h b/build/clang-plugin/mozsearch-plugin/BindingOperations.h new file mode 100644 index 0000000000..259594c5c3 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/BindingOperations.h @@ -0,0 +1,17 @@ +/* -*- 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 <clang/AST/ASTContext.h> +#include <clang/AST/Decl.h> +#include <clang/AST/DeclCXX.h> +#include <llvm/Support/JSON.h> + +void findBindingToJavaClass(clang::ASTContext &C, clang::CXXRecordDecl &klass); +void findBoundAsJavaClasses(clang::ASTContext &C, clang::CXXRecordDecl &klass); +void findBindingToJavaFunction(clang::ASTContext &C, clang::FunctionDecl &function); +void findBindingToJavaMember(clang::ASTContext &C, clang::CXXMethodDecl &method); +void findBindingToJavaConstant(clang::ASTContext &C, clang::VarDecl &field); + +void emitBindingAttributes(llvm::json::OStream &json, const clang::Decl &decl); diff --git a/build/clang-plugin/mozsearch-plugin/FileOperations.cpp b/build/clang-plugin/mozsearch-plugin/FileOperations.cpp new file mode 100644 index 0000000000..9307f4989d --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/FileOperations.cpp @@ -0,0 +1,140 @@ +/* -*- 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 "FileOperations.h" + +#include <stdio.h> +#include <stdlib.h> + +#if defined(_WIN32) || defined(_WIN64) +#include <direct.h> +#include <io.h> +#include <windows.h> +#include "StringOperations.h" +#else +#include <sys/file.h> +#include <sys/time.h> +#include <unistd.h> +#endif + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +// Make sure that all directories on path exist, excluding the final element of +// the path. +void ensurePath(std::string Path) { + size_t Pos = 0; + if (Path[0] == PATHSEP_CHAR) { + Pos++; + } + + while ((Pos = Path.find(PATHSEP_CHAR, Pos)) != std::string::npos) { + std::string Portion = Path.substr(0, Pos); + if (!Portion.empty()) { +#if defined(_WIN32) || defined(_WIN64) + int Err = _mkdir(Portion.c_str()); +#else + int Err = mkdir(Portion.c_str(), 0775); +#endif + if (Err == -1 && errno != EEXIST) { + perror("mkdir failed"); + exit(1); + } + } + + Pos++; + } +} + +#if defined(_WIN32) || defined(_WIN64) +AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) { + this->Filename = DstFile; + std::string Hash = hash(SrcFile); + std::string MutexName = std::string("Local\\searchfox-") + Hash; + std::wstring WideMutexName; + WideMutexName.assign(MutexName.begin(), MutexName.end()); + Handle = CreateMutex(nullptr, false, WideMutexName.c_str()); + if (Handle == NULL) { + return; + } + + if (WaitForSingleObject(Handle, INFINITE) != WAIT_OBJECT_0) { + return; + } +} + +AutoLockFile::~AutoLockFile() { + ReleaseMutex(Handle); + CloseHandle(Handle); +} + +bool AutoLockFile::success() { + return Handle != NULL; +} + +FILE *AutoLockFile::openTmp() { + int TmpDescriptor = _open((Filename + ".tmp").c_str(), _O_WRONLY | _O_APPEND | _O_CREAT | _O_BINARY, 0666); + return _fdopen(TmpDescriptor, "ab"); +} + +bool AutoLockFile::moveTmp() { + if (_unlink(Filename.c_str()) == -1) { + if (errno != ENOENT) { + return false; + } + } + return rename((Filename + ".tmp").c_str(), Filename.c_str()) == 0; +} + +std::string getAbsolutePath(const std::string &Filename) { + char Full[_MAX_PATH]; + if (!_fullpath(Full, Filename.c_str(), _MAX_PATH)) { + return std::string(""); + } + return std::string(Full); +} +#else +AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) { + this->Filename = DstFile; + FileDescriptor = open(SrcFile.c_str(), O_RDONLY); + if (FileDescriptor == -1) { + return; + } + + do { + int rv = flock(FileDescriptor, LOCK_EX); + if (rv == 0) { + break; + } + } while (true); +} + +AutoLockFile::~AutoLockFile() { close(FileDescriptor); } + +bool AutoLockFile::success() { return FileDescriptor != -1; } + +FILE* AutoLockFile::openTmp() { + int TmpDescriptor = open((Filename + ".tmp").c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666); + return fdopen(TmpDescriptor, "ab"); +} + +bool AutoLockFile::moveTmp() { + if (unlink(Filename.c_str()) == -1) { + if (errno != ENOENT) { + return false; + } + } + return rename((Filename + ".tmp").c_str(), Filename.c_str()) == 0; +} + +std::string getAbsolutePath(const std::string &Filename) { + char Full[4096]; + if (!realpath(Filename.c_str(), Full)) { + return std::string(""); + } + return std::string(Full); +} +#endif diff --git a/build/clang-plugin/mozsearch-plugin/FileOperations.h b/build/clang-plugin/mozsearch-plugin/FileOperations.h new file mode 100644 index 0000000000..90764484da --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/FileOperations.h @@ -0,0 +1,70 @@ +/* -*- 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/. */ + +#ifndef FileOperations_h +#define FileOperations_h + +#include <stdio.h> +#include <string> + +#if defined(_WIN32) || defined(_WIN64) +#include <windows.h> +#define PATHSEP_CHAR '\\' +#define PATHSEP_STRING "\\" +#else +#define PATHSEP_CHAR '/' +#define PATHSEP_STRING "/" +#endif + +// Make sure that all directories on path exist, excluding the final element of +// the path. +void ensurePath(std::string Path); + +std::string getAbsolutePath(const std::string &Filename); + +// Used to synchronize access when writing to an analysis file, so that +// concurrently running clang instances don't clobber each other's data. +// On Windows, we use a named mutex. On POSIX platforms, we use flock on the +// source files. flock is advisory locking, and doesn't interfere with clang's +// own opening of the source files (i.e. to interfere, clang would have to be +// using flock itself, which it does not). +struct AutoLockFile { + // Absolute path to the analysis file + std::string Filename; + +#if defined(_WIN32) || defined(_WIN64) + // Handle for the named Mutex + HANDLE Handle = NULL; +#else + // fd for the *source* file that corresponds to the analysis file. We use + // the source file because it doesn't change while the analysis file gets + // repeatedly replaced by a new version written to a separate tmp file. + // This fd is used when using flock to synchronize access. + int FileDescriptor = -1; +#endif + + // SrcFile should be the absolute path to the source code file, and DstFile + // the absolute path to the corresponding analysis file. This constructor + // will block until exclusive access has been obtained. + AutoLockFile(const std::string &SrcFile, const std::string &DstFile); + ~AutoLockFile(); + + // Check after constructing to ensure the mutex was properly set up. + bool success(); + + // There used to be an `openFile` method here but we switched to directly + // using a std::ifstream for the input file in able to take advantage of its + // support for variable length lines (as opposed to fgets which takes a fixed + // size buffer). + + // Open a new tmp file for writing the new analysis data to. Caller is + // responsible for fclose'ing it. + FILE *openTmp(); + // Replace the existing analysis file with the new "tmp" one that has the new + // data. Returns false on error. + bool moveTmp(); +}; + +#endif diff --git a/build/clang-plugin/mozsearch-plugin/MozsearchIndexer.cpp b/build/clang-plugin/mozsearch-plugin/MozsearchIndexer.cpp new file mode 100644 index 0000000000..f6958384a8 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/MozsearchIndexer.cpp @@ -0,0 +1,2436 @@ +/* -*- 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 "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Mangle.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/Version.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/raw_ostream.h" + +#include <fstream> +#include <iostream> +#include <map> +#include <memory> +#include <sstream> +#include <string> +#include <tuple> +#include <unordered_set> + +#include <stdio.h> +#include <stdlib.h> + +#include "BindingOperations.h" +#include "FileOperations.h" +#include "StringOperations.h" +#include "from-clangd/HeuristicResolver.h" + +#if CLANG_VERSION_MAJOR < 8 +// Starting with Clang 8.0 some basic functions have been renamed +#define getBeginLoc getLocStart +#define getEndLoc getLocEnd +#endif +// We want std::make_unique, but that's only available in c++14. In versions +// prior to that, we need to fall back to llvm's make_unique. It's also the +// case that we expect clang 10 to build with c++14 and clang 9 and earlier to +// build with c++11, at least as suggested by the llvm-config --cxxflags on +// non-windows platforms. mozilla-central seems to build with -std=c++17 on +// windows so we need to make this decision based on __cplusplus instead of +// the CLANG_VERSION_MAJOR. +#if __cplusplus < 201402L +using llvm::make_unique; +#else +using std::make_unique; +#endif + +using namespace clang; + +const std::string GENERATED("__GENERATED__" PATHSEP_STRING); + +// Absolute path to directory containing source code. +std::string Srcdir; + +// Absolute path to objdir (including generated code). +std::string Objdir; + +// Absolute path where analysis JSON output will be stored. +std::string Outdir; + +enum class FileType { + // The file was either in the source tree nor objdir. It might be a system + // include, for example. + Unknown, + // A file from the source tree. + Source, + // A file from the objdir. + Generated, +}; + +// Takes an absolute path to a file, and returns the type of file it is. If +// it's a Source or Generated file, the provided inout path argument is modified +// in-place so that it is relative to the source dir or objdir, respectively. +FileType relativizePath(std::string& path) { + if (path.compare(0, Objdir.length(), Objdir) == 0) { + path.replace(0, Objdir.length(), GENERATED); + return FileType::Generated; + } + // Empty filenames can get turned into Srcdir when they are resolved as + // absolute paths, so we should exclude files that are exactly equal to + // Srcdir or anything outside Srcdir. + if (path.length() > Srcdir.length() && path.compare(0, Srcdir.length(), Srcdir) == 0) { + // Remove the trailing `/' as well. + path.erase(0, Srcdir.length() + 1); + return FileType::Source; + } + return FileType::Unknown; +} + +#if !defined(_WIN32) && !defined(_WIN64) +#include <sys/time.h> + +static double time() { + struct timeval Tv; + gettimeofday(&Tv, nullptr); + return double(Tv.tv_sec) + double(Tv.tv_usec) / 1000000.; +} +#endif + +// Return true if |input| is a valid C++ identifier. We don't want to generate +// analysis information for operators, string literals, etc. by accident since +// it trips up consumers of the data. +static bool isValidIdentifier(std::string Input) { + for (char C : Input) { + if (!(isalpha(C) || isdigit(C) || C == '_')) { + return false; + } + } + return true; +} + +struct RAIITracer { + RAIITracer(const char *log) : mLog(log) { + printf("<%s>\n", mLog); + } + + ~RAIITracer() { + printf("</%s>\n", mLog); + } + + const char* mLog; +}; + +#define TRACEFUNC RAIITracer tracer(__FUNCTION__); + +class IndexConsumer; + +// For each C++ file seen by the analysis (.cpp or .h), we track a +// FileInfo. This object tracks whether the file is "interesting" (i.e., whether +// it's in the source dir or the objdir). We also store the analysis output +// here. +struct FileInfo { + FileInfo(std::string &Rname) : Realname(Rname) { + switch (relativizePath(Realname)) { + case FileType::Generated: + Interesting = true; + Generated = true; + break; + case FileType::Source: + Interesting = true; + Generated = false; + break; + case FileType::Unknown: + Interesting = false; + Generated = false; + break; + } + } + std::string Realname; + std::vector<std::string> Output; + bool Interesting; + bool Generated; +}; + +class IndexConsumer; + +class PreprocessorHook : public PPCallbacks { + IndexConsumer *Indexer; + +public: + PreprocessorHook(IndexConsumer *C) : Indexer(C) {} + + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) override; + + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + StringRef FileName, + bool IsAngled, + CharSourceRange FileNameRange, +#if CLANG_VERSION_MAJOR >= 16 + OptionalFileEntryRef File, +#elif CLANG_VERSION_MAJOR >= 15 + Optional<FileEntryRef> File, +#else + const FileEntry *File, +#endif + StringRef SearchPath, + StringRef RelativePath, + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; + + virtual void MacroDefined(const Token &Tok, + const MacroDirective *Md) override; + + virtual void MacroExpands(const Token &Tok, const MacroDefinition &Md, + SourceRange Range, const MacroArgs *Ma) override; + virtual void MacroUndefined(const Token &Tok, const MacroDefinition &Md, + const MacroDirective *Undef) override; + virtual void Defined(const Token &Tok, const MacroDefinition &Md, + SourceRange Range) override; + virtual void Ifdef(SourceLocation Loc, const Token &Tok, + const MacroDefinition &Md) override; + virtual void Ifndef(SourceLocation Loc, const Token &Tok, + const MacroDefinition &Md) override; +}; + +class IndexConsumer : public ASTConsumer, + public RecursiveASTVisitor<IndexConsumer>, + public DiagnosticConsumer { +private: + CompilerInstance &CI; + SourceManager &SM; + LangOptions &LO; + std::map<FileID, std::unique_ptr<FileInfo>> FileMap; + MangleContext *CurMangleContext; + ASTContext *AstContext; + std::unique_ptr<clangd::HeuristicResolver> Resolver; + + typedef RecursiveASTVisitor<IndexConsumer> Super; + + // Tracks the set of declarations that the current expression/statement is + // nested inside of. + struct AutoSetContext { + AutoSetContext(IndexConsumer *Self, NamedDecl *Context, bool VisitImplicit = false) + : Self(Self), Prev(Self->CurDeclContext), Decl(Context) { + this->VisitImplicit = VisitImplicit || (Prev ? Prev->VisitImplicit : false); + Self->CurDeclContext = this; + } + + ~AutoSetContext() { Self->CurDeclContext = Prev; } + + IndexConsumer *Self; + AutoSetContext *Prev; + NamedDecl *Decl; + bool VisitImplicit; + }; + AutoSetContext *CurDeclContext; + + FileInfo *getFileInfo(SourceLocation Loc) { + FileID Id = SM.getFileID(Loc); + + std::map<FileID, std::unique_ptr<FileInfo>>::iterator It; + It = FileMap.find(Id); + if (It == FileMap.end()) { + // We haven't seen this file before. We need to make the FileInfo + // structure information ourselves + std::string Filename = std::string(SM.getFilename(Loc)); + std::string Absolute; + // If Loc is a macro id rather than a file id, it Filename might be + // empty. Also for some types of file locations that are clang-internal + // like "<scratch>" it can return an empty Filename. In these cases we + // want to leave Absolute as empty. + if (!Filename.empty()) { + Absolute = getAbsolutePath(Filename); + if (Absolute.empty()) { + Absolute = Filename; + } + } + std::unique_ptr<FileInfo> Info = make_unique<FileInfo>(Absolute); + It = FileMap.insert(std::make_pair(Id, std::move(Info))).first; + } + return It->second.get(); + } + + // Helpers for processing declarations + // Should we ignore this location? + bool isInterestingLocation(SourceLocation Loc) { + if (Loc.isInvalid()) { + return false; + } + + return getFileInfo(Loc)->Interesting; + } + + // Convert location to "line:column" or "line:column-column" given length. + // In resulting string rep, line is 1-based and zero-padded to 5 digits, while + // column is 0-based and unpadded. + std::string locationToString(SourceLocation Loc, size_t Length = 0) { + std::pair<FileID, unsigned> Pair = SM.getDecomposedLoc(Loc); + + bool IsInvalid; + unsigned Line = SM.getLineNumber(Pair.first, Pair.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + unsigned Column = SM.getColumnNumber(Pair.first, Pair.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + + if (Length) { + return stringFormat("%05d:%d-%d", Line, Column - 1, Column - 1 + Length); + } else { + return stringFormat("%05d:%d", Line, Column - 1); + } + } + + // Convert SourceRange to "line-line". + // In the resulting string rep, line is 1-based. + std::string lineRangeToString(SourceRange Range) { + std::pair<FileID, unsigned> Begin = SM.getDecomposedLoc(Range.getBegin()); + std::pair<FileID, unsigned> End = SM.getDecomposedLoc(Range.getEnd()); + + bool IsInvalid; + unsigned Line1 = SM.getLineNumber(Begin.first, Begin.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + unsigned Line2 = SM.getLineNumber(End.first, End.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + + return stringFormat("%d-%d", Line1, Line2); + } + + // Convert SourceRange to "line:column-line:column". + // In the resulting string rep, line is 1-based, column is 0-based. + std::string fullRangeToString(SourceRange Range) { + std::pair<FileID, unsigned> Begin = SM.getDecomposedLoc(Range.getBegin()); + std::pair<FileID, unsigned> End = SM.getDecomposedLoc(Range.getEnd()); + + bool IsInvalid; + unsigned Line1 = SM.getLineNumber(Begin.first, Begin.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + unsigned Column1 = SM.getColumnNumber(Begin.first, Begin.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + unsigned Line2 = SM.getLineNumber(End.first, End.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + unsigned Column2 = SM.getColumnNumber(End.first, End.second, &IsInvalid); + if (IsInvalid) { + return ""; + } + + return stringFormat("%d:%d-%d:%d", Line1, Column1 - 1, Line2, Column2 - 1); + } + + // Returns the qualified name of `d` without considering template parameters. + std::string getQualifiedName(const NamedDecl *D) { + const DeclContext *Ctx = D->getDeclContext(); + if (Ctx->isFunctionOrMethod()) { + return D->getQualifiedNameAsString(); + } + + std::vector<const DeclContext *> Contexts; + + // Collect contexts. + while (Ctx && isa<NamedDecl>(Ctx)) { + Contexts.push_back(Ctx); + Ctx = Ctx->getParent(); + } + + std::string Result; + + std::reverse(Contexts.begin(), Contexts.end()); + + for (const DeclContext *DC : Contexts) { + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { + Result += Spec->getNameAsString(); + + if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization) { + std::string Backing; + llvm::raw_string_ostream Stream(Backing); + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + printTemplateArgumentList( + Stream, TemplateArgs.asArray(), PrintingPolicy(CI.getLangOpts())); + Result += Stream.str(); + } + } else if (const auto *Nd = dyn_cast<NamespaceDecl>(DC)) { + if (Nd->isAnonymousNamespace() || Nd->isInline()) { + continue; + } + Result += Nd->getNameAsString(); + } else if (const auto *Rd = dyn_cast<RecordDecl>(DC)) { + if (!Rd->getIdentifier()) { + Result += "(anonymous)"; + } else { + Result += Rd->getNameAsString(); + } + } else if (const auto *Fd = dyn_cast<FunctionDecl>(DC)) { + Result += Fd->getNameAsString(); + } else if (const auto *Ed = dyn_cast<EnumDecl>(DC)) { + // C++ [dcl.enum]p10: Each enum-name and each unscoped + // enumerator is declared in the scope that immediately contains + // the enum-specifier. Each scoped enumerator is declared in the + // scope of the enumeration. + if (Ed->isScoped() || Ed->getIdentifier()) + Result += Ed->getNameAsString(); + else + continue; + } else { + Result += cast<NamedDecl>(DC)->getNameAsString(); + } + Result += "::"; + } + + if (D->getDeclName()) + Result += D->getNameAsString(); + else + Result += "(anonymous)"; + + return Result; + } + + std::string mangleLocation(SourceLocation Loc, + std::string Backup = std::string()) { + FileInfo *F = getFileInfo(Loc); + std::string Filename = F->Realname; + if (Filename.length() == 0 && Backup.length() != 0) { + return Backup; + } + if (F->Generated) { + // Since generated files may be different on different platforms, + // we need to include a platform-specific thing in the hash. Otherwise + // we can end up with hash collisions where different symbols from + // different platforms map to the same thing. + char* Platform = getenv("MOZSEARCH_PLATFORM"); + Filename = std::string(Platform ? Platform : "") + std::string("@") + Filename; + } + return hash(Filename + std::string("@") + locationToString(Loc)); + } + + bool isAcceptableSymbolChar(char c) { + return isalpha(c) || isdigit(c) || c == '_' || c == '/'; + } + + std::string mangleFile(std::string Filename, FileType Type) { + // "Mangle" the file path, such that: + // 1. The majority of paths will still be mostly human-readable. + // 2. The sanitization algorithm doesn't produce collisions where two + // different unsanitized paths can result in the same sanitized paths. + // 3. The produced symbol doesn't cause problems with downstream consumers. + // In order to accomplish this, we keep alphanumeric chars, underscores, + // and slashes, and replace everything else with an "@xx" hex encoding. + // The majority of path characters are letters and slashes which don't get + // encoded, so that satisfies (1). Since "@" characters in the unsanitized + // path get encoded, there should be no "@" characters in the sanitized path + // that got preserved from the unsanitized input, so that should satisfy (2). + // And (3) was done by trial-and-error. Note in particular the dot (.) + // character needs to be encoded, or the symbol-search feature of mozsearch + // doesn't work correctly, as all dot characters in the symbol query get + // replaced by #. + for (size_t i = 0; i < Filename.length(); i++) { + char c = Filename[i]; + if (isAcceptableSymbolChar(c)) { + continue; + } + char hex[4]; + sprintf(hex, "@%02X", ((int)c) & 0xFF); + Filename.replace(i, 1, hex); + i += 2; + } + + if (Type == FileType::Generated) { + // Since generated files may be different on different platforms, + // we need to include a platform-specific thing in the hash. Otherwise + // we can end up with hash collisions where different symbols from + // different platforms map to the same thing. + char* Platform = getenv("MOZSEARCH_PLATFORM"); + Filename = std::string(Platform ? Platform : "") + std::string("@") + Filename; + } + return Filename; + } + + std::string mangleQualifiedName(std::string Name) { + std::replace(Name.begin(), Name.end(), ' ', '_'); + return Name; + } + + std::string getMangledName(clang::MangleContext *Ctx, + const clang::NamedDecl *Decl) { + if (isa<FunctionDecl>(Decl) && cast<FunctionDecl>(Decl)->isExternC()) { + return cast<FunctionDecl>(Decl)->getNameAsString(); + } + + if (isa<FunctionDecl>(Decl) || isa<VarDecl>(Decl)) { + const DeclContext *DC = Decl->getDeclContext(); + if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) || + isa<LinkageSpecDecl>(DC) || + // isa<ExternCContextDecl>(DC) || + isa<TagDecl>(DC)) { + llvm::SmallVector<char, 512> Output; + llvm::raw_svector_ostream Out(Output); +#if CLANG_VERSION_MAJOR >= 11 + // This code changed upstream in version 11: + // https://github.com/llvm/llvm-project/commit/29e1a16be8216066d1ed733a763a749aed13ff47 + GlobalDecl GD; + if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(Decl)) { + GD = GlobalDecl(D, Ctor_Complete); + } else if (const CXXDestructorDecl *D = + dyn_cast<CXXDestructorDecl>(Decl)) { + GD = GlobalDecl(D, Dtor_Complete); + } else { + GD = GlobalDecl(Decl); + } + Ctx->mangleName(GD, Out); +#else + if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(Decl)) { + Ctx->mangleCXXCtor(D, CXXCtorType::Ctor_Complete, Out); + } else if (const CXXDestructorDecl *D = + dyn_cast<CXXDestructorDecl>(Decl)) { + Ctx->mangleCXXDtor(D, CXXDtorType::Dtor_Complete, Out); + } else { + Ctx->mangleName(Decl, Out); + } +#endif + return Out.str().str(); + } else { + return std::string("V_") + mangleLocation(Decl->getLocation()) + + std::string("_") + hash(std::string(Decl->getName())); + } + } else if (isa<TagDecl>(Decl) || isa<ObjCInterfaceDecl>(Decl)) { + if (!Decl->getIdentifier()) { + // Anonymous. + return std::string("T_") + mangleLocation(Decl->getLocation()); + } + + return std::string("T_") + mangleQualifiedName(getQualifiedName(Decl)); + } else if (isa<TypedefNameDecl>(Decl)) { + if (!Decl->getIdentifier()) { + // Anonymous. + return std::string("TA_") + mangleLocation(Decl->getLocation()); + } + + return std::string("TA_") + mangleQualifiedName(getQualifiedName(Decl)); + } else if (isa<NamespaceDecl>(Decl) || isa<NamespaceAliasDecl>(Decl)) { + if (!Decl->getIdentifier()) { + // Anonymous. + return std::string("NS_") + mangleLocation(Decl->getLocation()); + } + + return std::string("NS_") + mangleQualifiedName(getQualifiedName(Decl)); + } else if (const ObjCIvarDecl *D2 = dyn_cast<ObjCIvarDecl>(Decl)) { + const ObjCInterfaceDecl *Iface = D2->getContainingInterface(); + return std::string("F_<") + getMangledName(Ctx, Iface) + ">_" + + D2->getNameAsString(); + } else if (const FieldDecl *D2 = dyn_cast<FieldDecl>(Decl)) { + const RecordDecl *Record = D2->getParent(); + return std::string("F_<") + getMangledName(Ctx, Record) + ">_" + + D2->getNameAsString(); + } else if (const EnumConstantDecl *D2 = dyn_cast<EnumConstantDecl>(Decl)) { + const DeclContext *DC = Decl->getDeclContext(); + if (const NamedDecl *Named = dyn_cast<NamedDecl>(DC)) { + return std::string("E_<") + getMangledName(Ctx, Named) + ">_" + + D2->getNameAsString(); + } + } + + assert(false); + return std::string(""); + } + + void debugLocation(SourceLocation Loc) { + std::string S = locationToString(Loc); + StringRef Filename = SM.getFilename(Loc); + printf("--> %s %s\n", std::string(Filename).c_str(), S.c_str()); + } + + void debugRange(SourceRange Range) { + printf("Range\n"); + debugLocation(Range.getBegin()); + debugLocation(Range.getEnd()); + } + +public: + IndexConsumer(CompilerInstance &CI) + : CI(CI), SM(CI.getSourceManager()), LO(CI.getLangOpts()), CurMangleContext(nullptr), + AstContext(nullptr), CurDeclContext(nullptr), TemplateStack(nullptr) { + CI.getPreprocessor().addPPCallbacks( + make_unique<PreprocessorHook>(this)); + } + + virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { + return new IndexConsumer(CI); + } + +#if !defined(_WIN32) && !defined(_WIN64) + struct AutoTime { + AutoTime(double *Counter) : Counter(Counter), Start(time()) {} + ~AutoTime() { + if (Start) { + *Counter += time() - Start; + } + } + void stop() { + *Counter += time() - Start; + Start = 0; + } + double *Counter; + double Start; + }; +#endif + + // All we need is to follow the final declaration. + virtual void HandleTranslationUnit(ASTContext &Ctx) { + CurMangleContext = + clang::ItaniumMangleContext::create(Ctx, CI.getDiagnostics()); + + AstContext = &Ctx; + Resolver = std::make_unique<clangd::HeuristicResolver>(Ctx); + TraverseDecl(Ctx.getTranslationUnitDecl()); + + // Emit the JSON data for all files now. + std::map<FileID, std::unique_ptr<FileInfo>>::iterator It; + for (It = FileMap.begin(); It != FileMap.end(); It++) { + if (!It->second->Interesting) { + continue; + } + + FileInfo &Info = *It->second; + + std::string Filename = Outdir + Info.Realname; + std::string SrcFilename = Info.Generated + ? Objdir + Info.Realname.substr(GENERATED.length()) + : Srcdir + PATHSEP_STRING + Info.Realname; + + ensurePath(Filename); + + // We lock the output file in case some other clang process is trying to + // write to it at the same time. + AutoLockFile Lock(SrcFilename, Filename); + + if (!Lock.success()) { + fprintf(stderr, "Unable to lock file %s\n", Filename.c_str()); + exit(1); + } + + // Merge our results with the existing lines from the output file. + // This ensures that header files that are included multiple times + // in different ways are analyzed completely. + std::ifstream Fin(Filename.c_str(), std::ios::in | std::ios::binary); + FILE *OutFp = Lock.openTmp(); + if (!OutFp) { + fprintf(stderr, "Unable to open tmp out file for %s\n", Filename.c_str()); + exit(1); + } + + // Sort our new results and get an iterator to them + std::sort(Info.Output.begin(), Info.Output.end()); + std::vector<std::string>::const_iterator NewLinesIter = Info.Output.begin(); + std::string LastNewWritten; + + // Loop over the existing (sorted) lines in the analysis output file. + // (The good() check also handles the case where Fin did not exist when we + // went to open it.) + while(Fin.good()) { + std::string OldLine; + std::getline(Fin, OldLine); + // Skip blank lines. + if (OldLine.length() == 0) { + continue; + } + // We need to put the newlines back that getline() eats. + OldLine.push_back('\n'); + + // Write any results from Info.Output that are lexicographically + // smaller than OldLine (read from the existing file), but make sure + // to skip duplicates. Keep advancing NewLinesIter until we reach an + // entry that is lexicographically greater than OldLine. + for (; NewLinesIter != Info.Output.end(); NewLinesIter++) { + if (*NewLinesIter > OldLine) { + break; + } + if (*NewLinesIter == OldLine) { + continue; + } + if (*NewLinesIter == LastNewWritten) { + // dedupe the new entries being written + continue; + } + if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) != 1) { + fprintf(stderr, "Unable to write %zu bytes[1] to tmp output file for %s\n", + NewLinesIter->length(), Filename.c_str()); + exit(1); + } + LastNewWritten = *NewLinesIter; + } + + // Write the entry read from the existing file. + if (fwrite(OldLine.c_str(), OldLine.length(), 1, OutFp) != 1) { + fprintf(stderr, "Unable to write %zu bytes[2] to tmp output file for %s\n", + OldLine.length(), Filename.c_str()); + exit(1); + } + } + + // We finished reading from Fin + Fin.close(); + + // Finish iterating our new results, discarding duplicates + for (; NewLinesIter != Info.Output.end(); NewLinesIter++) { + if (*NewLinesIter == LastNewWritten) { + continue; + } + if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) != 1) { + fprintf(stderr, "Unable to write %zu bytes[3] to tmp output file for %s\n", + NewLinesIter->length(), Filename.c_str()); + exit(1); + } + LastNewWritten = *NewLinesIter; + } + + // Done writing all the things, close it and replace the old output file + // with the new one. + fclose(OutFp); + if (!Lock.moveTmp()) { + fprintf(stderr, "Unable to move tmp output file into place for %s (err %d)\n", Filename.c_str(), errno); + exit(1); + } + } + } + + // Unfortunately, we have to override all these methods in order to track the + // context we're inside. + + bool TraverseEnumDecl(EnumDecl *D) { + AutoSetContext Asc(this, D); + return Super::TraverseEnumDecl(D); + } + bool TraverseRecordDecl(RecordDecl *D) { + AutoSetContext Asc(this, D); + return Super::TraverseRecordDecl(D); + } + bool TraverseCXXRecordDecl(CXXRecordDecl *D) { + AutoSetContext Asc(this, D); + return Super::TraverseCXXRecordDecl(D); + } + bool TraverseFunctionDecl(FunctionDecl *D) { + AutoSetContext Asc(this, D); + const FunctionDecl *Def; + // (See the larger AutoTemplateContext comment for more information.) If a + // method on a templated class is declared out-of-line, we need to analyze + // the definition inside the scope of the template or else we won't properly + // handle member access on the templated type. + if (TemplateStack && D->isDefined(Def) && Def && D != Def) { + TraverseFunctionDecl(const_cast<FunctionDecl *>(Def)); + } + return Super::TraverseFunctionDecl(D); + } + bool TraverseCXXMethodDecl(CXXMethodDecl *D) { + AutoSetContext Asc(this, D); + const FunctionDecl *Def; + // See TraverseFunctionDecl. + if (TemplateStack && D->isDefined(Def) && Def && D != Def) { + TraverseFunctionDecl(const_cast<FunctionDecl *>(Def)); + } + return Super::TraverseCXXMethodDecl(D); + } + bool TraverseCXXConstructorDecl(CXXConstructorDecl *D) { + AutoSetContext Asc(this, D, /*VisitImplicit=*/true); + const FunctionDecl *Def; + // See TraverseFunctionDecl. + if (TemplateStack && D->isDefined(Def) && Def && D != Def) { + TraverseFunctionDecl(const_cast<FunctionDecl *>(Def)); + } + return Super::TraverseCXXConstructorDecl(D); + } + bool TraverseCXXConversionDecl(CXXConversionDecl *D) { + AutoSetContext Asc(this, D); + const FunctionDecl *Def; + // See TraverseFunctionDecl. + if (TemplateStack && D->isDefined(Def) && Def && D != Def) { + TraverseFunctionDecl(const_cast<FunctionDecl *>(Def)); + } + return Super::TraverseCXXConversionDecl(D); + } + bool TraverseCXXDestructorDecl(CXXDestructorDecl *D) { + AutoSetContext Asc(this, D); + const FunctionDecl *Def; + // See TraverseFunctionDecl. + if (TemplateStack && D->isDefined(Def) && Def && D != Def) { + TraverseFunctionDecl(const_cast<FunctionDecl *>(Def)); + } + return Super::TraverseCXXDestructorDecl(D); + } + + // Used to keep track of the context in which a token appears. + struct Context { + // Ultimately this becomes the "context" JSON property. + std::string Name; + + // Ultimately this becomes the "contextsym" JSON property. + std::string Symbol; + + Context() {} + Context(std::string Name, std::string Symbol) + : Name(Name), Symbol(Symbol) {} + }; + + Context translateContext(NamedDecl *D) { + const FunctionDecl *F = dyn_cast<FunctionDecl>(D); + if (F && F->isTemplateInstantiation()) { + D = F->getTemplateInstantiationPattern(); + } + + return Context(D->getQualifiedNameAsString(), getMangledName(CurMangleContext, D)); + } + + Context getContext(SourceLocation Loc) { + if (SM.isMacroBodyExpansion(Loc)) { + // If we're inside a macro definition, we don't return any context. It + // will probably not be what the user expects if we do. + return Context(); + } + + if (CurDeclContext) { + return translateContext(CurDeclContext->Decl); + } + return Context(); + } + + // Similar to GetContext(SourceLocation), but it skips the declaration passed + // in. This is useful if we want the context of a declaration that's already + // on the stack. + Context getContext(Decl *D) { + if (SM.isMacroBodyExpansion(D->getLocation())) { + // If we're inside a macro definition, we don't return any context. It + // will probably not be what the user expects if we do. + return Context(); + } + + AutoSetContext *Ctxt = CurDeclContext; + while (Ctxt) { + if (Ctxt->Decl != D) { + return translateContext(Ctxt->Decl); + } + Ctxt = Ctxt->Prev; + } + return Context(); + } + + // Analyzing template code is tricky. Suppose we have this code: + // + // template<class T> + // bool Foo(T* ptr) { return T::StaticMethod(ptr); } + // + // If we analyze the body of Foo without knowing the type T, then we will not + // be able to generate any information for StaticMethod. However, analyzing + // Foo for every possible instantiation is inefficient and it also generates + // too much data in some cases. For example, the following code would generate + // one definition of Baz for every instantiation, which is undesirable: + // + // template<class T> + // class Bar { struct Baz { ... }; }; + // + // To solve this problem, we analyze templates only once. We do so in a + // GatherDependent mode where we look for "dependent scoped member + // expressions" (i.e., things like StaticMethod). We keep track of the + // locations of these expressions. If we find one or more of them, we analyze + // the template for each instantiation, in an AnalyzeDependent mode. This mode + // ignores all source locations except for the ones where we found dependent + // scoped member expressions before. For these locations, we generate a + // separate JSON result for each instantiation. + // + // We inherit our parent's mode if it is exists. This is because if our + // parent is in analyze mode, it means we've already lived a full life in + // gather mode and we must not restart in gather mode or we'll cause the + // indexer to visit EVERY identifier, which is way too much data. + struct AutoTemplateContext { + AutoTemplateContext(IndexConsumer *Self) + : Self(Self) + , CurMode(Self->TemplateStack ? Self->TemplateStack->CurMode : Mode::GatherDependent) + , Parent(Self->TemplateStack) { + Self->TemplateStack = this; + } + + ~AutoTemplateContext() { Self->TemplateStack = Parent; } + + // We traverse templates in two modes: + enum class Mode { + // Gather mode does not traverse into specializations. It looks for + // locations where it would help to have more info from template + // specializations. + GatherDependent, + + // Analyze mode traverses into template specializations and records + // information about token locations saved in gather mode. + AnalyzeDependent, + }; + + // We found a dependent scoped member expression! Keep track of it for + // later. + void visitDependent(SourceLocation Loc) { + if (CurMode == Mode::AnalyzeDependent) { + return; + } + + DependentLocations.insert(Loc.getRawEncoding()); + if (Parent) { + Parent->visitDependent(Loc); + } + } + + bool inGatherMode() { + return CurMode == Mode::GatherDependent; + } + + // Do we need to perform the extra AnalyzeDependent passes (one per + // instantiation)? + bool needsAnalysis() const { + if (!DependentLocations.empty()) { + return true; + } + if (Parent) { + return Parent->needsAnalysis(); + } + return false; + } + + void switchMode() { CurMode = Mode::AnalyzeDependent; } + + // Do we want to analyze each template instantiation separately? + bool shouldVisitTemplateInstantiations() const { + if (CurMode == Mode::AnalyzeDependent) { + return true; + } + if (Parent) { + return Parent->shouldVisitTemplateInstantiations(); + } + return false; + } + + // For a given expression/statement, should we emit JSON data for it? + bool shouldVisit(SourceLocation Loc) { + if (CurMode == Mode::GatherDependent) { + return true; + } + if (DependentLocations.find(Loc.getRawEncoding()) != + DependentLocations.end()) { + return true; + } + if (Parent) { + return Parent->shouldVisit(Loc); + } + return false; + } + + private: + IndexConsumer *Self; + Mode CurMode; + std::unordered_set<unsigned> DependentLocations; + AutoTemplateContext *Parent; + }; + + AutoTemplateContext *TemplateStack; + + bool shouldVisitTemplateInstantiations() const { + if (TemplateStack) { + return TemplateStack->shouldVisitTemplateInstantiations(); + } + return false; + } + + bool shouldVisitImplicitCode() const { + return CurDeclContext && CurDeclContext->VisitImplicit; + } + + bool TraverseClassTemplateDecl(ClassTemplateDecl *D) { + AutoTemplateContext Atc(this); + Super::TraverseClassTemplateDecl(D); + + if (!Atc.needsAnalysis()) { + return true; + } + + Atc.switchMode(); + + if (D != D->getCanonicalDecl()) { + return true; + } + + for (auto *Spec : D->specializations()) { + for (auto *Rd : Spec->redecls()) { + // We don't want to visit injected-class-names in this traversal. + if (cast<CXXRecordDecl>(Rd)->isInjectedClassName()) + continue; + + TraverseDecl(Rd); + } + } + + return true; + } + + bool TraverseFunctionTemplateDecl(FunctionTemplateDecl *D) { + AutoTemplateContext Atc(this); + if (Atc.inGatherMode()) { + Super::TraverseFunctionTemplateDecl(D); + } + + if (!Atc.needsAnalysis()) { + return true; + } + + Atc.switchMode(); + + if (D != D->getCanonicalDecl()) { + return true; + } + + for (auto *Spec : D->specializations()) { + for (auto *Rd : Spec->redecls()) { + TraverseDecl(Rd); + } + } + + return true; + } + + bool shouldVisit(SourceLocation Loc) { + if (TemplateStack) { + return TemplateStack->shouldVisit(Loc); + } + return true; + } + + enum { + // Flag to omit the identifier from being cross-referenced across files. + // This is usually desired for local variables. + NoCrossref = 1 << 0, + // Flag to indicate the token with analysis data is not an identifier. Indicates + // we want to skip the check that tries to ensure a sane identifier token. + NotIdentifierToken = 1 << 1, + // This indicates that the end of the provided SourceRange is valid and + // should be respected. If this flag is not set, the visitIdentifier + // function should use only the start of the SourceRange and auto-detect + // the end based on whatever token is found at the start. + LocRangeEndValid = 1 << 2 + }; + + void emitStructuredInfo(SourceLocation Loc, const RecordDecl *decl) { + std::string json_str; + llvm::raw_string_ostream ros(json_str); + llvm::json::OStream J(ros); + // Start the top-level object. + J.objectBegin(); + + unsigned StartOffset = SM.getFileOffset(Loc); + unsigned EndOffset = + StartOffset + Lexer::MeasureTokenLength(Loc, SM, CI.getLangOpts()); + J.attribute("loc", locationToString(Loc, EndOffset - StartOffset)); + J.attribute("structured", 1); + J.attribute("pretty", getQualifiedName(decl)); + J.attribute("sym", getMangledName(CurMangleContext, decl)); + + J.attribute("kind", TypeWithKeyword::getTagTypeKindName(decl->getTagKind())); + + const ASTContext &C = *AstContext; + const ASTRecordLayout &Layout = C.getASTRecordLayout(decl); + + J.attribute("sizeBytes", Layout.getSize().getQuantity()); + + emitBindingAttributes(J, *decl); + + auto cxxDecl = dyn_cast<CXXRecordDecl>(decl); + + if (cxxDecl) { + J.attributeBegin("supers"); + J.arrayBegin(); + for (const CXXBaseSpecifier &Base : cxxDecl->bases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + + J.objectBegin(); + + J.attribute("sym", getMangledName(CurMangleContext, BaseDecl)); + + J.attributeBegin("props"); + J.arrayBegin(); + if (Base.isVirtual()) { + J.value("virtual"); + } + J.arrayEnd(); + J.attributeEnd(); + + J.objectEnd(); + } + J.arrayEnd(); + J.attributeEnd(); + + J.attributeBegin("methods"); + J.arrayBegin(); + for (const CXXMethodDecl *MethodDecl : cxxDecl->methods()) { + J.objectBegin(); + + J.attribute("pretty", getQualifiedName(MethodDecl)); + J.attribute("sym", getMangledName(CurMangleContext, MethodDecl)); + + // TODO: Better figure out what to do for non-isUserProvided methods + // which means there's potentially semantic data that doesn't correspond + // to a source location in the source. Should we be emitting + // structured info for those when we're processing the class here? + + J.attributeBegin("props"); + J.arrayBegin(); + if (MethodDecl->isStatic()) { + J.value("static"); + } + if (MethodDecl->isInstance()) { + J.value("instance"); + } + if (MethodDecl->isVirtual()) { + J.value("virtual"); + } + if (MethodDecl->isUserProvided()) { + J.value("user"); + } + if (MethodDecl->isDefaulted()) { + J.value("defaulted"); + } + if (MethodDecl->isDeleted()) { + J.value("deleted"); + } + if (MethodDecl->isConstexpr()) { + J.value("constexpr"); + } + J.arrayEnd(); + J.attributeEnd(); + + J.objectEnd(); + } + J.arrayEnd(); + J.attributeEnd(); + } + + J.attributeBegin("fields"); + J.arrayBegin(); + uint64_t iField = 0; + for (RecordDecl::field_iterator It = decl->field_begin(), + End = decl->field_end(); It != End; ++It, ++iField) { + const FieldDecl &Field = **It; + uint64_t localOffsetBits = Layout.getFieldOffset(iField); + CharUnits localOffsetBytes = C.toCharUnitsFromBits(localOffsetBits); + + J.objectBegin(); + J.attribute("pretty", getQualifiedName(&Field)); + J.attribute("sym", getMangledName(CurMangleContext, &Field)); + QualType FieldType = Field.getType(); + QualType CanonicalFieldType = FieldType.getCanonicalType(); + J.attribute("type", CanonicalFieldType.getAsString()); + const TagDecl *tagDecl = CanonicalFieldType->getAsTagDecl(); + if (!tagDecl) { + // Try again piercing any pointers/references involved. Note that our + // typesym semantics are dubious-ish and right now crossref just does + // some parsing of "type" itself until we improve this rep. + CanonicalFieldType = CanonicalFieldType->getPointeeType(); + if (!CanonicalFieldType.isNull()) { + tagDecl = CanonicalFieldType->getAsTagDecl(); + } + } + if (tagDecl) { + J.attribute("typesym", getMangledName(CurMangleContext, tagDecl)); + } + J.attribute("offsetBytes", localOffsetBytes.getQuantity()); + if (Field.isBitField()) { + J.attributeBegin("bitPositions"); + J.objectBegin(); + + J.attribute("begin", unsigned(localOffsetBits - C.toBits(localOffsetBytes))); + J.attribute("width", Field.getBitWidthValue(C)); + + J.objectEnd(); + J.attributeEnd(); + } else { + // Try and get the field as a record itself so we can know its size, but + // we don't actually want to recurse into it. + if (auto FieldRec = Field.getType()->getAs<RecordType>()) { + auto const &FieldLayout = C.getASTRecordLayout(FieldRec->getDecl()); + J.attribute("sizeBytes", FieldLayout.getSize().getQuantity()); + } else { + // We were unable to get it as a record, which suggests it's a normal + // type, in which case let's just ask for the type size. (Maybe this + // would also work for the above case too?) + uint64_t typeSizeBits = C.getTypeSize(Field.getType()); + CharUnits typeSizeBytes = C.toCharUnitsFromBits(typeSizeBits); + J.attribute("sizeBytes", typeSizeBytes.getQuantity()); + } + } + J.objectEnd(); + } + J.arrayEnd(); + J.attributeEnd(); + + // End the top-level object. + J.objectEnd(); + + FileInfo *F = getFileInfo(Loc); + // we want a newline. + ros << '\n'; + F->Output.push_back(std::move(ros.str())); + } + + void emitStructuredInfo(SourceLocation Loc, const FunctionDecl *decl) { + std::string json_str; + llvm::raw_string_ostream ros(json_str); + llvm::json::OStream J(ros); + // Start the top-level object. + J.objectBegin(); + + unsigned StartOffset = SM.getFileOffset(Loc); + unsigned EndOffset = + StartOffset + Lexer::MeasureTokenLength(Loc, SM, CI.getLangOpts()); + J.attribute("loc", locationToString(Loc, EndOffset - StartOffset)); + J.attribute("structured", 1); + J.attribute("pretty", getQualifiedName(decl)); + J.attribute("sym", getMangledName(CurMangleContext, decl)); + + emitBindingAttributes(J, *decl); + + J.attributeBegin("args"); + J.arrayBegin(); + + for (auto param : decl->parameters()) { + J.objectBegin(); + + J.attribute("name", param->getName()); + QualType ArgType = param->getOriginalType(); + J.attribute("type", ArgType.getAsString()); + + QualType CanonicalArgType = ArgType.getCanonicalType(); + const TagDecl *canonDecl = CanonicalArgType->getAsTagDecl(); + if (!canonDecl) { + // Try again piercing any pointers/references involved. Note that our + // typesym semantics are dubious-ish and right now crossref just does + // some parsing of "type" itself until we improve this rep. + CanonicalArgType = CanonicalArgType->getPointeeType(); + if (!CanonicalArgType.isNull()) { + canonDecl = CanonicalArgType->getAsTagDecl(); + } + } + if (canonDecl) { + J.attribute("typesym", getMangledName(CurMangleContext, canonDecl)); + } + + J.objectEnd(); + } + + J.arrayEnd(); + J.attributeEnd(); + + + auto cxxDecl = dyn_cast<CXXMethodDecl>(decl); + + if (cxxDecl) { + J.attribute("kind", "method"); + if (auto parentDecl = cxxDecl->getParent()) { + J.attribute("parentsym", getMangledName(CurMangleContext, parentDecl)); + } + + J.attributeBegin("overrides"); + J.arrayBegin(); + for (const CXXMethodDecl *MethodDecl : cxxDecl->overridden_methods()) { + J.objectBegin(); + + // TODO: Make sure we're doing template traversals appropriately... + // findOverriddenMethods (now removed) liked to do: + // if (Decl->isTemplateInstantiation()) { + // Decl = dyn_cast<CXXMethodDecl>(Decl->getTemplateInstantiationPattern()); + // } + // I think our pre-emptive dereferencing/avoidance of templates may + // protect us from this, but it needs more investigation. + + J.attribute("sym", getMangledName(CurMangleContext, MethodDecl)); + + J.objectEnd(); + } + J.arrayEnd(); + J.attributeEnd(); + + } else { + J.attribute("kind", "function"); + } + + // ## Props + J.attributeBegin("props"); + J.arrayBegin(); + // some of these are only possible on a CXXMethodDecl, but we want them all + // in the same array, so condition these first ones. + if (cxxDecl) { + if (cxxDecl->isStatic()) { + J.value("static"); + } + if (cxxDecl->isInstance()) { + J.value("instance"); + } + if (cxxDecl->isVirtual()) { + J.value("virtual"); + } + if (cxxDecl->isUserProvided()) { + J.value("user"); + } + } + if (decl->isDefaulted()) { + J.value("defaulted"); + } + if (decl->isDeleted()) { + J.value("deleted"); + } + if (decl->isConstexpr()) { + J.value("constexpr"); + } + J.arrayEnd(); + J.attributeEnd(); + + // End the top-level object. + J.objectEnd(); + + FileInfo *F = getFileInfo(Loc); + // we want a newline. + ros << '\n'; + F->Output.push_back(std::move(ros.str())); + } + + /** + * Emit structured info for a field. Right now the intent is for this to just + * be a pointer to its parent's structured info with this method entirely + * avoiding getting the ASTRecordLayout. + * + * TODO: Give more thought on where to locate the canonical info on fields and + * how to normalize their exposure over the web. We could relink the info + * both at cross-reference time and web-server lookup time. This is also + * called out in `analysis.md`. + */ + void emitStructuredInfo(SourceLocation Loc, const FieldDecl *decl) { + // XXX the call to decl::getParent will assert below for ObjCIvarDecl + // instances because their DecContext is not a RecordDecl. So just bail + // for now. + // TODO: better support ObjC. + if (const ObjCIvarDecl *D2 = dyn_cast<ObjCIvarDecl>(decl)) { + return; + } + + std::string json_str; + llvm::raw_string_ostream ros(json_str); + llvm::json::OStream J(ros); + // Start the top-level object. + J.objectBegin(); + + unsigned StartOffset = SM.getFileOffset(Loc); + unsigned EndOffset = + StartOffset + Lexer::MeasureTokenLength(Loc, SM, CI.getLangOpts()); + J.attribute("loc", locationToString(Loc, EndOffset - StartOffset)); + J.attribute("structured", 1); + J.attribute("pretty", getQualifiedName(decl)); + J.attribute("sym", getMangledName(CurMangleContext, decl)); + J.attribute("kind", "field"); + + if (auto parentDecl = decl->getParent()) { + J.attribute("parentsym", getMangledName(CurMangleContext, parentDecl)); + } + + // End the top-level object. + J.objectEnd(); + + FileInfo *F = getFileInfo(Loc); + // we want a newline. + ros << '\n'; + F->Output.push_back(std::move(ros.str())); + } + + /** + * Emit structured info for a variable if it is a static class member. + */ + void emitStructuredInfo(SourceLocation Loc, const VarDecl *decl) { + const auto *parentDecl = dyn_cast_or_null<RecordDecl>(decl->getDeclContext()); + + std::string json_str; + llvm::raw_string_ostream ros(json_str); + llvm::json::OStream J(ros); + // Start the top-level object. + J.objectBegin(); + + unsigned StartOffset = SM.getFileOffset(Loc); + unsigned EndOffset = + StartOffset + Lexer::MeasureTokenLength(Loc, SM, CI.getLangOpts()); + J.attribute("loc", locationToString(Loc, EndOffset - StartOffset)); + J.attribute("structured", 1); + J.attribute("pretty", getQualifiedName(decl)); + J.attribute("sym", getMangledName(CurMangleContext, decl)); + J.attribute("kind", "field"); + + if (parentDecl) { + J.attribute("parentsym", getMangledName(CurMangleContext, parentDecl)); + } + + emitBindingAttributes(J, *decl); + + // End the top-level object. + J.objectEnd(); + + FileInfo *F = getFileInfo(Loc); + // we want a newline. + ros << '\n'; + F->Output.push_back(std::move(ros.str())); + } + + // XXX Type annotating. + // QualType is the type class. It has helpers like TagDecl via getAsTagDecl. + // ValueDecl exposes a getType() method. + // + // Arguably it makes sense to only expose types that Searchfox has definitions + // for as first-class. Probably the way to go is like context/contextsym. + // We expose a "type" which is just a human-readable string which has no + // semantic purposes and is just a display string, plus then a "typesym" which + // we expose if we were able to map the type. + // + // Other meta-info: field offsets. Ancestor types. + + // This is the only function that emits analysis JSON data. It should be + // called for each identifier that corresponds to a symbol. + void visitIdentifier(const char *Kind, const char *SyntaxKind, + llvm::StringRef QualName, SourceRange LocRange, + std::string Symbol, + QualType MaybeType = QualType(), + Context TokenContext = Context(), int Flags = 0, + SourceRange PeekRange = SourceRange(), + SourceRange NestingRange = SourceRange(), + std::vector<SourceRange> *ArgRanges = nullptr) { + SourceLocation Loc = LocRange.getBegin(); + if (!shouldVisit(Loc)) { + return; + } + + // Find the file positions corresponding to the token. + unsigned StartOffset = SM.getFileOffset(Loc); + unsigned EndOffset = (Flags & LocRangeEndValid) + ? SM.getFileOffset(LocRange.getEnd()) + : StartOffset + Lexer::MeasureTokenLength(Loc, SM, CI.getLangOpts()); + + std::string LocStr = locationToString(Loc, EndOffset - StartOffset); + std::string RangeStr = locationToString(Loc, EndOffset - StartOffset); + std::string PeekRangeStr; + + if (!(Flags & NotIdentifierToken)) { + // Get the token's characters so we can make sure it's a valid token. + const char *StartChars = SM.getCharacterData(Loc); + std::string Text(StartChars, EndOffset - StartOffset); + if (!isValidIdentifier(Text)) { + return; + } + } + + FileInfo *F = getFileInfo(Loc); + + if (!(Flags & NoCrossref)) { + std::string json_str; + llvm::raw_string_ostream ros(json_str); + llvm::json::OStream J(ros); + // Start the top-level object. + J.objectBegin(); + + J.attribute("loc", LocStr); + J.attribute("target", 1); + J.attribute("kind", Kind); + J.attribute("pretty", QualName.data()); + J.attribute("sym", Symbol); + if (!TokenContext.Name.empty()) { + J.attribute("context", TokenContext.Name); + } + if (!TokenContext.Symbol.empty()) { + J.attribute("contextsym", TokenContext.Symbol); + } + if (PeekRange.isValid()) { + PeekRangeStr = lineRangeToString(PeekRange); + if (!PeekRangeStr.empty()) { + J.attribute("peekRange", PeekRangeStr); + } + } + + if (ArgRanges) { + J.attributeBegin("argRanges"); + J.arrayBegin(); + + for (auto range : *ArgRanges) { + std::string ArgRangeStr = fullRangeToString(range); + if (!ArgRangeStr.empty()) { + J.value(ArgRangeStr); + } + } + + J.arrayEnd(); + J.attributeEnd(); + } + + // End the top-level object. + J.objectEnd(); + // we want a newline. + ros << '\n'; + F->Output.push_back(std::move(ros.str())); + } + + // Generate a single "source":1 for all the symbols. If we search from here, + // we want to union the results for every symbol in `symbols`. + std::string json_str; + llvm::raw_string_ostream ros(json_str); + llvm::json::OStream J(ros); + // Start the top-level object. + J.objectBegin(); + + J.attribute("loc", RangeStr); + J.attribute("source", 1); + + if (NestingRange.isValid()) { + std::string NestingRangeStr = fullRangeToString(NestingRange); + if (!NestingRangeStr.empty()) { + J.attribute("nestingRange", NestingRangeStr); + } + } + + std::string Syntax; + if (Flags & NoCrossref) { + J.attribute("syntax", ""); + } else { + Syntax = Kind; + Syntax.push_back(','); + Syntax.append(SyntaxKind); + J.attribute("syntax", Syntax); + } + + if (!MaybeType.isNull()) { + J.attribute("type", MaybeType.getAsString()); + QualType canonical = MaybeType.getCanonicalType(); + const TagDecl *decl = canonical->getAsTagDecl(); + if (!decl) { + // Try again piercing any pointers/references involved. Note that our + // typesym semantics are dubious-ish and right now crossref just does + // some parsing of "type" itself until we improve this rep. + canonical = canonical->getPointeeType(); + if (!canonical.isNull()) { + decl = canonical->getAsTagDecl(); + } + } + if (decl) { + std::string Mangled = getMangledName(CurMangleContext, decl); + J.attribute("typesym", Mangled); + } + } + + std::string Pretty(SyntaxKind); + Pretty.push_back(' '); + Pretty.append(QualName.data()); + J.attribute("pretty", Pretty); + + J.attribute("sym", Symbol); + + if (Flags & NoCrossref) { + J.attribute("no_crossref", 1); + } + + if (ArgRanges) { + J.attributeBegin("argRanges"); + J.arrayBegin(); + + for (auto range : *ArgRanges) { + std::string ArgRangeStr = fullRangeToString(range); + if (!ArgRangeStr.empty()) { + J.value(ArgRangeStr); + } + } + + J.arrayEnd(); + J.attributeEnd(); + } + + // End the top-level object. + J.objectEnd(); + + // we want a newline. + ros << '\n'; + F->Output.push_back(std::move(ros.str())); + } + + void normalizeLocation(SourceLocation *Loc) { + *Loc = SM.getSpellingLoc(*Loc); + } + + // For cases where the left-brace is not directly accessible from the AST, + // helper to use the lexer to find the brace. Make sure you're picking the + // start location appropriately! + SourceLocation findLeftBraceFromLoc(SourceLocation Loc) { + return Lexer::findLocationAfterToken(Loc, tok::l_brace, SM, LO, false); + } + + // If the provided statement is compound, return its range. + SourceRange getCompoundStmtRange(Stmt* D) { + if (!D) { + return SourceRange(); + } + + CompoundStmt *D2 = dyn_cast<CompoundStmt>(D); + if (D2) { + return D2->getSourceRange(); + } + + return SourceRange(); + } + + SourceRange getFunctionPeekRange(FunctionDecl* D) { + // We always start at the start of the function decl, which may include the + // return type on a separate line. + SourceLocation Start = D->getBeginLoc(); + + // By default, we end at the line containing the function's name. + SourceLocation End = D->getLocation(); + + std::pair<FileID, unsigned> FuncLoc = SM.getDecomposedLoc(End); + + // But if there are parameters, we want to include those as well. + for (ParmVarDecl* Param : D->parameters()) { + std::pair<FileID, unsigned> ParamLoc = SM.getDecomposedLoc(Param->getLocation()); + + // It's possible there are macros involved or something. We don't include + // the parameters in that case. + if (ParamLoc.first == FuncLoc.first) { + // Assume parameters are in order, so we always take the last one. + End = Param->getEndLoc(); + } + } + + return SourceRange(Start, End); + } + + SourceRange getTagPeekRange(TagDecl* D) { + SourceLocation Start = D->getBeginLoc(); + + // By default, we end at the line containing the name. + SourceLocation End = D->getLocation(); + + std::pair<FileID, unsigned> FuncLoc = SM.getDecomposedLoc(End); + + if (CXXRecordDecl* D2 = dyn_cast<CXXRecordDecl>(D)) { + // But if there are parameters, we want to include those as well. + for (CXXBaseSpecifier& Base : D2->bases()) { + std::pair<FileID, unsigned> Loc = SM.getDecomposedLoc(Base.getEndLoc()); + + // It's possible there are macros involved or something. We don't include + // the parameters in that case. + if (Loc.first == FuncLoc.first) { + // Assume parameters are in order, so we always take the last one. + End = Base.getEndLoc(); + } + } + } + + return SourceRange(Start, End); + } + + SourceRange getCommentRange(NamedDecl* D) { + const RawComment* RC = + AstContext->getRawCommentForDeclNoCache(D); + if (!RC) { + return SourceRange(); + } + + return RC->getSourceRange(); + } + + // Sanity checks that all ranges are in the same file, returning the first if + // they're in different files. Unions the ranges based on which is first. + SourceRange combineRanges(SourceRange Range1, SourceRange Range2) { + if (Range1.isInvalid()) { + return Range2; + } + if (Range2.isInvalid()) { + return Range1; + } + + std::pair<FileID, unsigned> Begin1 = SM.getDecomposedLoc(Range1.getBegin()); + std::pair<FileID, unsigned> End1 = SM.getDecomposedLoc(Range1.getEnd()); + std::pair<FileID, unsigned> Begin2 = SM.getDecomposedLoc(Range2.getBegin()); + std::pair<FileID, unsigned> End2 = SM.getDecomposedLoc(Range2.getEnd()); + + if (End1.first != Begin2.first) { + // Something weird is probably happening with the preprocessor. Just + // return the first range. + return Range1; + } + + // See which range comes first. + if (Begin1.second <= End2.second) { + return SourceRange(Range1.getBegin(), Range2.getEnd()); + } else { + return SourceRange(Range2.getBegin(), Range1.getEnd()); + } + } + + // Given a location and a range, returns the range if: + // - The location and the range live in the same file. + // - The range is well ordered (end is not before begin). + // Returns an empty range otherwise. + SourceRange validateRange(SourceLocation Loc, SourceRange Range) { + std::pair<FileID, unsigned> Decomposed = SM.getDecomposedLoc(Loc); + std::pair<FileID, unsigned> Begin = SM.getDecomposedLoc(Range.getBegin()); + std::pair<FileID, unsigned> End = SM.getDecomposedLoc(Range.getEnd()); + + if (Begin.first != Decomposed.first || End.first != Decomposed.first) { + return SourceRange(); + } + + if (Begin.second >= End.second) { + return SourceRange(); + } + + return Range; + } + + bool VisitNamedDecl(NamedDecl *D) { + SourceLocation Loc = D->getLocation(); + + // If the token is from a macro expansion and the expansion location + // is interesting, use that instead as it tends to be more useful. + SourceLocation expandedLoc = Loc; + if (SM.isMacroBodyExpansion(Loc)) { + Loc = SM.getFileLoc(Loc); + } + + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + if (isa<ParmVarDecl>(D) && !D->getDeclName().getAsIdentifierInfo()) { + // Unnamed parameter in function proto. + return true; + } + + int Flags = 0; + const char *Kind = "def"; + const char *PrettyKind = "?"; + bool wasTemplate = false; + SourceRange PeekRange(D->getBeginLoc(), D->getEndLoc()); + // The nesting range identifies the left brace and right brace, which + // heavily depends on the AST node type. + SourceRange NestingRange; + QualType qtype = QualType(); + if (FunctionDecl *D2 = dyn_cast<FunctionDecl>(D)) { + if (D2->isTemplateInstantiation()) { + wasTemplate = true; + D = D2->getTemplateInstantiationPattern(); + } + // We treat pure virtual declarations as definitions. + Kind = (D2->isThisDeclarationADefinition() || D2->isPure()) ? "def" : "decl"; + PrettyKind = "function"; + PeekRange = getFunctionPeekRange(D2); + + // Only emit the nesting range if: + // - This is a definition AND + // - This isn't a template instantiation. Function templates' + // instantiations can end up as a definition with a Loc at their point + // of declaration but with the CompoundStmt of the template's + // point of definition. This really messes up the nesting range logic. + // At the time of writing this, the test repo's `big_header.h`'s + // `WhatsYourVector_impl::forwardDeclaredTemplateThingInlinedBelow` as + // instantiated by `big_cpp.cpp` triggers this phenomenon. + // + // Note: As covered elsewhere, template processing is tricky and it's + // conceivable that we may change traversal patterns in the future, + // mooting this guard. + if (D2->isThisDeclarationADefinition() && + !D2->isTemplateInstantiation()) { + // The CompoundStmt range is the brace range. + NestingRange = getCompoundStmtRange(D2->getBody()); + } + } else if (TagDecl *D2 = dyn_cast<TagDecl>(D)) { + Kind = D2->isThisDeclarationADefinition() ? "def" : "forward"; + PrettyKind = "type"; + + if (D2->isThisDeclarationADefinition() && D2->getDefinition() == D2) { + PeekRange = getTagPeekRange(D2); + NestingRange = D2->getBraceRange(); + } else { + PeekRange = SourceRange(); + } + } else if (TypedefNameDecl *D2 = dyn_cast<TypedefNameDecl>(D)) { + Kind = "alias"; + PrettyKind = "type"; + PeekRange = SourceRange(Loc, Loc); + qtype = D2->getUnderlyingType(); + } else if (VarDecl *D2 = dyn_cast<VarDecl>(D)) { + if (D2->isLocalVarDeclOrParm()) { + Flags = NoCrossref; + } + + Kind = D2->isThisDeclarationADefinition() == VarDecl::DeclarationOnly + ? "decl" + : "def"; + PrettyKind = "variable"; + } else if (isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D)) { + Kind = "def"; + PrettyKind = "namespace"; + PeekRange = SourceRange(Loc, Loc); + NamespaceDecl *D2 = dyn_cast<NamespaceDecl>(D); + if (D2) { + // There's no exposure of the left brace so we have to find it. + NestingRange = SourceRange( + findLeftBraceFromLoc(D2->isAnonymousNamespace() ? D2->getBeginLoc() : Loc), + D2->getRBraceLoc()); + } + } else if (isa<FieldDecl>(D)) { + Kind = "def"; + PrettyKind = "field"; + } else if (isa<EnumConstantDecl>(D)) { + Kind = "def"; + PrettyKind = "enum constant"; + } else { + return true; + } + + if (ValueDecl *D2 = dyn_cast<ValueDecl>(D)) { + qtype = D2->getType(); + } + + SourceRange CommentRange = getCommentRange(D); + PeekRange = combineRanges(PeekRange, CommentRange); + PeekRange = validateRange(Loc, PeekRange); + NestingRange = validateRange(Loc, NestingRange); + + std::string Symbol = getMangledName(CurMangleContext, D); + + // In the case of destructors, Loc might point to the ~ character. In that + // case we want to skip to the name of the class. However, Loc might also + // point to other places that generate destructors, such as the use site of + // a macro that expands to generate a destructor, or a lambda (apparently + // clang 8 creates a destructor declaration for at least some lambdas). In + // the former case we'll use the macro use site as the location, and in the + // latter we'll just drop the declaration. + if (isa<CXXDestructorDecl>(D)) { + PrettyKind = "destructor"; + const char *P = SM.getCharacterData(Loc); + if (*P == '~') { + // Advance Loc to the class name + P++; + + unsigned Skipped = 1; + while (*P == ' ' || *P == '\t' || *P == '\r' || *P == '\n') { + P++; + Skipped++; + } + + Loc = Loc.getLocWithOffset(Skipped); + } else { + // See if the destructor is coming from a macro expansion + P = SM.getCharacterData(expandedLoc); + if (*P != '~') { + // It's not + return true; + } + // It is, so just use Loc as-is + } + } + + visitIdentifier(Kind, PrettyKind, getQualifiedName(D), SourceRange(Loc), Symbol, + qtype, + getContext(D), Flags, PeekRange, NestingRange); + + // In-progress structured info emission. + if (RecordDecl *D2 = dyn_cast<RecordDecl>(D)) { + if (D2->isThisDeclarationADefinition() && + // XXX getASTRecordLayout doesn't work for dependent types, so we + // avoid calling into emitStructuredInfo for now if there's a + // dependent type or if we're in any kind of template context. This + // should be re-evaluated once this is working for normal classes and + // we can better evaluate what is useful. + !D2->isDependentType() && + !TemplateStack) { + if (auto *D3 = dyn_cast<CXXRecordDecl>(D2)) { + findBindingToJavaClass(*AstContext, *D3); + findBoundAsJavaClasses(*AstContext, *D3); + } + emitStructuredInfo(Loc, D2); + } + } + if (FunctionDecl *D2 = dyn_cast<FunctionDecl>(D)) { + if ((D2->isThisDeclarationADefinition() || D2->isPure()) && + // a clause at the top should have generalized and set wasTemplate so + // it shouldn't be the case that isTemplateInstantiation() is true. + !D2->isTemplateInstantiation() && + !wasTemplate && + !D2->isFunctionTemplateSpecialization() && + !TemplateStack) { + if (auto *D3 = dyn_cast<CXXMethodDecl>(D2)) { + findBindingToJavaMember(*AstContext, *D3); + } else { + findBindingToJavaFunction(*AstContext, *D2); + } + emitStructuredInfo(Loc, D2); + } + } + if (FieldDecl *D2 = dyn_cast<FieldDecl>(D)) { + if (!D2->isTemplated() && + !TemplateStack) { + emitStructuredInfo(Loc, D2); + } + } + if (VarDecl *D2 = dyn_cast<VarDecl>(D)) { + if (!D2->isTemplated() && + !TemplateStack && + isa<CXXRecordDecl>(D2->getDeclContext())) { + findBindingToJavaConstant(*AstContext, *D2); + emitStructuredInfo(Loc, D2); + } + } + + return true; + } + + bool VisitCXXConstructExpr(CXXConstructExpr *E) { + SourceLocation Loc = E->getBeginLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + FunctionDecl *Ctor = E->getConstructor(); + if (Ctor->isTemplateInstantiation()) { + Ctor = Ctor->getTemplateInstantiationPattern(); + } + std::string Mangled = getMangledName(CurMangleContext, Ctor); + + // FIXME: Need to do something different for list initialization. + + visitIdentifier("use", "constructor", getQualifiedName(Ctor), Loc, Mangled, + QualType(), getContext(Loc)); + + return true; + } + + bool VisitCallExpr(CallExpr *E) { + Decl *Callee = E->getCalleeDecl(); + if (!Callee || !FunctionDecl::classof(Callee)) { + return true; + } + + const NamedDecl *NamedCallee = dyn_cast<NamedDecl>(Callee); + + SourceLocation Loc; + + const FunctionDecl *F = dyn_cast<FunctionDecl>(NamedCallee); + if (F->isTemplateInstantiation()) { + NamedCallee = F->getTemplateInstantiationPattern(); + } + + std::string Mangled = getMangledName(CurMangleContext, NamedCallee); + int Flags = 0; + + Expr *CalleeExpr = E->getCallee()->IgnoreParenImpCasts(); + + if (CXXOperatorCallExpr::classof(E)) { + // Just take the first token. + CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E); + Loc = Op->getOperatorLoc(); + Flags |= NotIdentifierToken; + } else if (MemberExpr::classof(CalleeExpr)) { + MemberExpr *Member = dyn_cast<MemberExpr>(CalleeExpr); + Loc = Member->getMemberLoc(); + } else if (DeclRefExpr::classof(CalleeExpr)) { + // We handle this in VisitDeclRefExpr. + return true; + } else { + return true; + } + + normalizeLocation(&Loc); + + if (!isInterestingLocation(Loc)) { + return true; + } + + std::vector<SourceRange> argRanges; + for (auto argExpr : E->arguments()) { + argRanges.push_back(argExpr->getSourceRange()); + } + + visitIdentifier("use", "function", getQualifiedName(NamedCallee), Loc, Mangled, + E->getCallReturnType(*AstContext), getContext(Loc), Flags, + SourceRange(), SourceRange(), &argRanges); + + return true; + } + + bool VisitTagTypeLoc(TagTypeLoc L) { + SourceLocation Loc = L.getBeginLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + TagDecl *Decl = L.getDecl(); + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "type", getQualifiedName(Decl), Loc, Mangled, + L.getType(), getContext(Loc)); + return true; + } + + bool VisitTypedefTypeLoc(TypedefTypeLoc L) { + SourceLocation Loc = L.getBeginLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + NamedDecl *Decl = L.getTypedefNameDecl(); + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "type", getQualifiedName(Decl), Loc, Mangled, + L.getType(), getContext(Loc)); + return true; + } + + bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc L) { + SourceLocation Loc = L.getBeginLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + NamedDecl *Decl = L.getDecl(); + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "type", getQualifiedName(Decl), Loc, Mangled, + L.getType(), getContext(Loc)); + return true; + } + + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) { + SourceLocation Loc = L.getBeginLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + TemplateDecl *Td = L.getTypePtr()->getTemplateName().getAsTemplateDecl(); + if (ClassTemplateDecl *D = dyn_cast<ClassTemplateDecl>(Td)) { + NamedDecl *Decl = D->getTemplatedDecl(); + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "type", getQualifiedName(Decl), Loc, Mangled, + QualType(), getContext(Loc)); + } else if (TypeAliasTemplateDecl *D = dyn_cast<TypeAliasTemplateDecl>(Td)) { + NamedDecl *Decl = D->getTemplatedDecl(); + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "type", getQualifiedName(Decl), Loc, Mangled, + QualType(), getContext(Loc)); + } + + return true; + } + + bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) { + SourceLocation Loc = L.getNameLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + for (const NamedDecl *D : + Resolver->resolveDependentNameType(L.getTypePtr())) { + visitHeuristicResult(Loc, D); + } + return true; + } + + bool VisitDeclRefExpr(DeclRefExpr *E) { + SourceLocation Loc = E->getExprLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + if (E->hasQualifier()) { + Loc = E->getNameInfo().getLoc(); + normalizeLocation(&Loc); + } + + NamedDecl *Decl = E->getDecl(); + if (const VarDecl *D2 = dyn_cast<VarDecl>(Decl)) { + int Flags = 0; + if (D2->isLocalVarDeclOrParm()) { + Flags = NoCrossref; + } + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "variable", getQualifiedName(Decl), Loc, Mangled, + D2->getType(), getContext(Loc), Flags); + } else if (isa<FunctionDecl>(Decl)) { + const FunctionDecl *F = dyn_cast<FunctionDecl>(Decl); + if (F->isTemplateInstantiation()) { + Decl = F->getTemplateInstantiationPattern(); + } + + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "function", getQualifiedName(Decl), Loc, Mangled, + E->getType(), getContext(Loc)); + } else if (isa<EnumConstantDecl>(Decl)) { + std::string Mangled = getMangledName(CurMangleContext, Decl); + visitIdentifier("use", "enum", getQualifiedName(Decl), Loc, Mangled, + E->getType(), getContext(Loc)); + } + + return true; + } + + bool VisitCXXConstructorDecl(CXXConstructorDecl *D) { + if (!isInterestingLocation(D->getLocation())) { + return true; + } + + for (CXXConstructorDecl::init_const_iterator It = D->init_begin(); + It != D->init_end(); ++It) { + const CXXCtorInitializer *Ci = *It; + if (!Ci->getMember() || !Ci->isWritten()) { + continue; + } + + SourceLocation Loc = Ci->getMemberLocation(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + continue; + } + + FieldDecl *Member = Ci->getMember(); + std::string Mangled = getMangledName(CurMangleContext, Member); + visitIdentifier("use", "field", getQualifiedName(Member), Loc, Mangled, + Member->getType(), getContext(D)); + } + + return true; + } + + bool VisitMemberExpr(MemberExpr *E) { + SourceLocation Loc = E->getExprLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + ValueDecl *Decl = E->getMemberDecl(); + if (FieldDecl *Field = dyn_cast<FieldDecl>(Decl)) { + std::string Mangled = getMangledName(CurMangleContext, Field); + visitIdentifier("use", "field", getQualifiedName(Field), Loc, Mangled, + Field->getType(), getContext(Loc)); + } + return true; + } + + // Helper function for producing heuristic results for usages in dependent + // code. These should be distinguished from concrete results (obtained for + // dependent code using the AutoTemplateContext machinery) once bug 1833552 is + // fixed. + // We don't expect this method to be intentionally called multiple times for + // a given (Loc, NamedDecl) pair because our callers should be mutually + // exclusive AST node types. However, it's fine if this method is called + // multiple time for a given pair because we explicitly de-duplicate records + // with an identical string representation (which is a good reason to have + // this helper, as it ensures identical representations). + void visitHeuristicResult(SourceLocation Loc, const NamedDecl *ND) { + if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(ND)) { + ND = TD->getTemplatedDecl(); + } + QualType MaybeType; + const char *SyntaxKind = nullptr; + if (const FunctionDecl *F = dyn_cast<FunctionDecl>(ND)) { + MaybeType = F->getType(); + SyntaxKind = "function"; + } else if (const FieldDecl *F = dyn_cast<FieldDecl>(ND)) { + MaybeType = F->getType(); + SyntaxKind = "field"; + } else if (const EnumConstantDecl *E = dyn_cast<EnumConstantDecl>(ND)) { + MaybeType = E->getType(); + SyntaxKind = "enum"; + } else if (const TypedefNameDecl *T = dyn_cast<TypedefNameDecl>(ND)) { + MaybeType = T->getUnderlyingType(); + SyntaxKind = "type"; + } + if (SyntaxKind) { + std::string Mangled = getMangledName(CurMangleContext, ND); + visitIdentifier("use", SyntaxKind, getQualifiedName(ND), Loc, Mangled, + MaybeType, getContext(Loc)); + } + } + + bool VisitOverloadExpr(OverloadExpr *E) { + SourceLocation Loc = E->getExprLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + for (auto *Candidate : E->decls()) { + visitHeuristicResult(Loc, Candidate); + } + return true; + } + + bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { + SourceLocation Loc = E->getMemberLoc(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + // If possible, provide a heuristic result without instantiation. + for (const NamedDecl *D : Resolver->resolveMemberExpr(E)) { + visitHeuristicResult(Loc, D); + } + + // Also record this location so that if we have instantiations, we can + // gather more accurate results from them. + if (TemplateStack) { + TemplateStack->visitDependent(Loc); + } + return true; + } + + bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + SourceLocation Loc = E->getLocation(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return true; + } + + for (const NamedDecl *D : Resolver->resolveDeclRefExpr(E)) { + visitHeuristicResult(Loc, D); + } + return true; + } + + void enterSourceFile(SourceLocation Loc) { + normalizeLocation(&Loc); + FileInfo* newFile = getFileInfo(Loc); + if (!newFile->Interesting) { + return; + } + FileType type = newFile->Generated ? FileType::Generated : FileType::Source; + std::string symbol = + std::string("FILE_") + mangleFile(newFile->Realname, type); + + // We use an explicit zero-length source range at the start of the file. If we + // don't set the LocRangeEndValid flag, the visitIdentifier code will use the + // entire first token, which could be e.g. a long multiline-comment. + visitIdentifier("def", "file", newFile->Realname, SourceRange(Loc), + symbol, QualType(), Context(), + NotIdentifierToken | LocRangeEndValid); + } + + void inclusionDirective(SourceRange FileNameRange, const FileEntry* File) { + std::string includedFile(File->tryGetRealPathName()); + FileType type = relativizePath(includedFile); + if (type == FileType::Unknown) { + return; + } + std::string symbol = + std::string("FILE_") + mangleFile(includedFile, type); + + visitIdentifier("use", "file", includedFile, FileNameRange, symbol, + QualType(), Context(), + NotIdentifierToken | LocRangeEndValid); + } + + void macroDefined(const Token &Tok, const MacroDirective *Macro) { + if (Macro->getMacroInfo()->isBuiltinMacro()) { + return; + } + SourceLocation Loc = Tok.getLocation(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return; + } + + IdentifierInfo *Ident = Tok.getIdentifierInfo(); + if (Ident) { + std::string Mangled = + std::string("M_") + mangleLocation(Loc, std::string(Ident->getName())); + visitIdentifier("def", "macro", Ident->getName(), Loc, Mangled); + } + } + + void macroUsed(const Token &Tok, const MacroInfo *Macro) { + if (!Macro) { + return; + } + if (Macro->isBuiltinMacro()) { + return; + } + SourceLocation Loc = Tok.getLocation(); + normalizeLocation(&Loc); + if (!isInterestingLocation(Loc)) { + return; + } + + IdentifierInfo *Ident = Tok.getIdentifierInfo(); + if (Ident) { + std::string Mangled = + std::string("M_") + + mangleLocation(Macro->getDefinitionLoc(), std::string(Ident->getName())); + visitIdentifier("use", "macro", Ident->getName(), Loc, Mangled); + } + } +}; + +void PreprocessorHook::FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID = FileID()) { + switch (Reason) { + case PPCallbacks::RenameFile: + case PPCallbacks::SystemHeaderPragma: + // Don't care about these, since we want the actual on-disk filenames + break; + case PPCallbacks::EnterFile: + Indexer->enterSourceFile(Loc); + break; + case PPCallbacks::ExitFile: + // Don't care about exiting files + break; + } +} + +void PreprocessorHook::InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + StringRef FileName, + bool IsAngled, + CharSourceRange FileNameRange, +#if CLANG_VERSION_MAJOR >= 16 + OptionalFileEntryRef File, +#elif CLANG_VERSION_MAJOR >= 15 + Optional<FileEntryRef> File, +#else + const FileEntry *File, +#endif + StringRef SearchPath, + StringRef RelativePath, + const Module *Imported, + SrcMgr::CharacteristicKind FileType) { +#if CLANG_VERSION_MAJOR >= 15 + if (!File) { + return; + } + Indexer->inclusionDirective(FileNameRange.getAsRange(), &File->getFileEntry()); +#else + Indexer->inclusionDirective(FileNameRange.getAsRange(), File); +#endif +} + +void PreprocessorHook::MacroDefined(const Token &Tok, + const MacroDirective *Md) { + Indexer->macroDefined(Tok, Md); +} + +void PreprocessorHook::MacroExpands(const Token &Tok, const MacroDefinition &Md, + SourceRange Range, const MacroArgs *Ma) { + Indexer->macroUsed(Tok, Md.getMacroInfo()); +} + +void PreprocessorHook::MacroUndefined(const Token &Tok, + const MacroDefinition &Md, + const MacroDirective *Undef) +{ + Indexer->macroUsed(Tok, Md.getMacroInfo()); +} + +void PreprocessorHook::Defined(const Token &Tok, const MacroDefinition &Md, + SourceRange Range) { + Indexer->macroUsed(Tok, Md.getMacroInfo()); +} + +void PreprocessorHook::Ifdef(SourceLocation Loc, const Token &Tok, + const MacroDefinition &Md) { + Indexer->macroUsed(Tok, Md.getMacroInfo()); +} + +void PreprocessorHook::Ifndef(SourceLocation Loc, const Token &Tok, + const MacroDefinition &Md) { + Indexer->macroUsed(Tok, Md.getMacroInfo()); +} + +class IndexAction : public PluginASTAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef F) { + return make_unique<IndexConsumer>(CI); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector<std::string> &Args) { + if (Args.size() != 3) { + DiagnosticsEngine &D = CI.getDiagnostics(); + unsigned DiagID = D.getCustomDiagID( + DiagnosticsEngine::Error, + "Need arguments for the source, output, and object directories"); + D.Report(DiagID); + return false; + } + + // Load our directories + Srcdir = getAbsolutePath(Args[0]); + if (Srcdir.empty()) { + DiagnosticsEngine &D = CI.getDiagnostics(); + unsigned DiagID = D.getCustomDiagID( + DiagnosticsEngine::Error, "Source directory '%0' does not exist"); + D.Report(DiagID) << Args[0]; + return false; + } + + ensurePath(Args[1] + PATHSEP_STRING); + Outdir = getAbsolutePath(Args[1]); + Outdir += PATHSEP_STRING; + + Objdir = getAbsolutePath(Args[2]); + if (Objdir.empty()) { + DiagnosticsEngine &D = CI.getDiagnostics(); + unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error, + "Objdir '%0' does not exist"); + D.Report(DiagID) << Args[2]; + return false; + } + Objdir += PATHSEP_STRING; + + printf("MOZSEARCH: %s %s %s\n", Srcdir.c_str(), Outdir.c_str(), + Objdir.c_str()); + + return true; + } + + void printHelp(llvm::raw_ostream &Ros) { + Ros << "Help for mozsearch plugin goes here\n"; + } +}; + +static FrontendPluginRegistry::Add<IndexAction> + Y("mozsearch-index", "create the mozsearch index database"); diff --git a/build/clang-plugin/mozsearch-plugin/README b/build/clang-plugin/mozsearch-plugin/README new file mode 100644 index 0000000000..d948e9aca3 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/README @@ -0,0 +1,12 @@ +This clang plugin code generates a JSON file for each compiler input +file. The JSON file contains information about the C++ symbols that +are referenced by the input file. The data is eventually consumed by +Searchfox. See https://github.com/mozsearch/mozsearch for more +information. + +This plugin is enabled with the --enable-clang-plugin and +--enable-mozsearch-plugin mozconfig options. The output of the plugin +is stored in $OBJDIR/mozsearch_index. + +This code is not a checker, unlike other parts of the Mozilla clang +plugin. It cannot be used with clang-tidy. diff --git a/build/clang-plugin/mozsearch-plugin/StringOperations.cpp b/build/clang-plugin/mozsearch-plugin/StringOperations.cpp new file mode 100644 index 0000000000..a2e60e42c6 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/StringOperations.cpp @@ -0,0 +1,42 @@ +/* -*- 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 "StringOperations.h" + +static unsigned long djbHash(const char *Str) { + unsigned long Hash = 5381; + + for (const char *P = Str; *P; P++) { + // Hash * 33 + c + Hash = ((Hash << 5) + Hash) + *P; + } + + return Hash; +} + +// This doesn't actually return a hex string of |hash|, but it +// does... something. It doesn't really matter what. +static void hashToString(unsigned long Hash, char *Buffer) { + const char Table[] = {"0123456789abcdef"}; + char *P = Buffer; + while (Hash) { + *P = Table[Hash & 0xf]; + Hash >>= 4; + P++; + } + + *P = 0; +} + +std::string hash(const std::string &Str) { + static char HashStr[41]; + unsigned long H = djbHash(Str.c_str()); + hashToString(H, HashStr); + return std::string(HashStr); +} + +std::string toString(int N) { + return stringFormat("%d", N); +} diff --git a/build/clang-plugin/mozsearch-plugin/StringOperations.h b/build/clang-plugin/mozsearch-plugin/StringOperations.h new file mode 100644 index 0000000000..4aa5b31962 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/StringOperations.h @@ -0,0 +1,25 @@ +/* -*- 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/. */ + +#ifndef StringOperations_h +#define StringOperations_h + +#include <memory> +#include <string> +#include <string.h> + +std::string hash(const std::string &Str); + +template <typename... Args> +inline std::string stringFormat(const std::string &Format, Args... ArgList) { + size_t Len = snprintf(nullptr, 0, Format.c_str(), ArgList...); + std::unique_ptr<char[]> Buf(new char[Len + 1]); + snprintf(Buf.get(), Len + 1, Format.c_str(), ArgList...); + return std::string(Buf.get(), Buf.get() + Len); +} + +std::string toString(int N); + +#endif diff --git a/build/clang-plugin/mozsearch-plugin/from-clangd/HeuristicResolver.cpp b/build/clang-plugin/mozsearch-plugin/from-clangd/HeuristicResolver.cpp new file mode 100644 index 0000000000..719094dbf2 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/from-clangd/HeuristicResolver.cpp @@ -0,0 +1,349 @@ +//===--- HeuristicResolver.cpp ---------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HeuristicResolver.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Type.h" + +namespace clang { +namespace clangd { + +// Convenience lambdas for use as the 'Filter' parameter of +// HeuristicResolver::resolveDependentMember(). +const auto NoFilter = [](const NamedDecl *D) { return true; }; +const auto NonStaticFilter = [](const NamedDecl *D) { + return D->isCXXInstanceMember(); +}; +const auto StaticFilter = [](const NamedDecl *D) { + return !D->isCXXInstanceMember(); +}; +const auto ValueFilter = [](const NamedDecl *D) { return isa<ValueDecl>(D); }; +const auto TypeFilter = [](const NamedDecl *D) { return isa<TypeDecl>(D); }; +const auto TemplateFilter = [](const NamedDecl *D) { + return isa<TemplateDecl>(D); +}; + +namespace { + +const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls, + ASTContext &Ctx) { + if (Decls.size() != 1) // Names an overload set -- just bail. + return nullptr; + if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) { + return Ctx.getTypeDeclType(TD).getTypePtr(); + } + if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) { + return VD->getType().getTypePtrOrNull(); + } + return nullptr; +} + +} // namespace + +// Helper function for HeuristicResolver::resolveDependentMember() +// which takes a possibly-dependent type `T` and heuristically +// resolves it to a CXXRecordDecl in which we can try name lookup. +CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(const Type *T) const { + assert(T); + + // Unwrap type sugar such as type aliases. + T = T->getCanonicalTypeInternal().getTypePtr(); + + if (const auto *DNT = T->getAs<DependentNameType>()) { + T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx); + if (!T) + return nullptr; + T = T->getCanonicalTypeInternal().getTypePtr(); + } + + if (const auto *RT = T->getAs<RecordType>()) + return dyn_cast<CXXRecordDecl>(RT->getDecl()); + + if (const auto *ICNT = T->getAs<InjectedClassNameType>()) + T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + if (!T) + return nullptr; + + const auto *TST = T->getAs<TemplateSpecializationType>(); + if (!TST) + return nullptr; + + const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>( + TST->getTemplateName().getAsTemplateDecl()); + if (!TD) + return nullptr; + + return TD->getTemplatedDecl(); +} + +const Type *HeuristicResolver::getPointeeType(const Type *T) const { + if (!T) + return nullptr; + + if (T->isPointerType()) + return T->castAs<PointerType>()->getPointeeType().getTypePtrOrNull(); + + // Try to handle smart pointer types. + + // Look up operator-> in the primary template. If we find one, it's probably a + // smart pointer type. + auto ArrowOps = resolveDependentMember( + T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter); + if (ArrowOps.empty()) + return nullptr; + + // Getting the return type of the found operator-> method decl isn't useful, + // because we discarded template arguments to perform lookup in the primary + // template scope, so the return type would just have the form U* where U is a + // template parameter type. + // Instead, just handle the common case where the smart pointer type has the + // form of SmartPtr<X, ...>, and assume X is the pointee type. + auto *TST = T->getAs<TemplateSpecializationType>(); + if (!TST) + return nullptr; + if (TST->template_arguments().size() == 0) + return nullptr; + const TemplateArgument &FirstArg = TST->template_arguments()[0]; + if (FirstArg.getKind() != TemplateArgument::Type) + return nullptr; + return FirstArg.getAsType().getTypePtrOrNull(); +} + +std::vector<const NamedDecl *> HeuristicResolver::resolveMemberExpr( + const CXXDependentScopeMemberExpr *ME) const { + // If the expression has a qualifier, first try resolving the member + // inside the qualifier's type. + // Note that we cannot use a NonStaticFilter in either case, for a couple + // of reasons: + // 1. It's valid to access a static member using instance member syntax, + // e.g. `instance.static_member`. + // 2. We can sometimes get a CXXDependentScopeMemberExpr for static + // member syntax too, e.g. if `X::static_member` occurs inside + // an instance method, it's represented as a CXXDependentScopeMemberExpr + // with `this` as the base expression as `X` as the qualifier + // (which could be valid if `X` names a base class after instantiation). + if (NestedNameSpecifier *NNS = ME->getQualifier()) { + if (const Type *QualifierType = resolveNestedNameSpecifierToType(NNS)) { + auto Decls = + resolveDependentMember(QualifierType, ME->getMember(), NoFilter); + if (!Decls.empty()) + return Decls; + } + } + + // If that didn't yield any results, try resolving the member inside + // the expression's base type. + const Type *BaseType = ME->getBaseType().getTypePtrOrNull(); + if (ME->isArrow()) { + BaseType = getPointeeType(BaseType); + } + if (!BaseType) + return {}; + if (const auto *BT = BaseType->getAs<BuiltinType>()) { + // If BaseType is the type of a dependent expression, it's just + // represented as BuiltinType::Dependent which gives us no information. We + // can get further by analyzing the dependent expression. + Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase(); + if (Base && BT->getKind() == BuiltinType::Dependent) { + BaseType = resolveExprToType(Base); + } + } + return resolveDependentMember(BaseType, ME->getMember(), NoFilter); +} + +std::vector<const NamedDecl *> HeuristicResolver::resolveDeclRefExpr( + const DependentScopeDeclRefExpr *RE) const { + return resolveDependentMember(RE->getQualifier()->getAsType(), + RE->getDeclName(), StaticFilter); +} + +std::vector<const NamedDecl *> +HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const { + const auto *CalleeType = resolveExprToType(CE->getCallee()); + if (!CalleeType) + return {}; + if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) + CalleeType = FnTypePtr->getPointeeType().getTypePtr(); + if (const FunctionType *FnType = CalleeType->getAs<FunctionType>()) { + if (const auto *D = + resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) { + return {D}; + } + } + return {}; +} + +std::vector<const NamedDecl *> +HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const { + if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) { + return {ND}; + } + + return resolveExprToDecls(CE->getCallee()); +} + +std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl( + const UnresolvedUsingValueDecl *UUVD) const { + return resolveDependentMember(UUVD->getQualifier()->getAsType(), + UUVD->getNameInfo().getName(), ValueFilter); +} + +std::vector<const NamedDecl *> HeuristicResolver::resolveDependentNameType( + const DependentNameType *DNT) const { + return resolveDependentMember( + resolveNestedNameSpecifierToType(DNT->getQualifier()), + DNT->getIdentifier(), TypeFilter); +} + +std::vector<const NamedDecl *> +HeuristicResolver::resolveTemplateSpecializationType( + const DependentTemplateSpecializationType *DTST) const { + return resolveDependentMember( + resolveNestedNameSpecifierToType(DTST->getQualifier()), + DTST->getIdentifier(), TemplateFilter); +} + +std::vector<const NamedDecl *> +HeuristicResolver::resolveExprToDecls(const Expr *E) const { + if (const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) { + return resolveMemberExpr(ME); + } + if (const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) { + return resolveDeclRefExpr(RE); + } + if (const auto *OE = dyn_cast<OverloadExpr>(E)) { + return {OE->decls_begin(), OE->decls_end()}; + } + if (const auto *CE = dyn_cast<CallExpr>(E)) { + return resolveTypeOfCallExpr(CE); + } + if (const auto *ME = dyn_cast<MemberExpr>(E)) + return {ME->getMemberDecl()}; + + return {}; +} + +const Type *HeuristicResolver::resolveExprToType(const Expr *E) const { + std::vector<const NamedDecl *> Decls = resolveExprToDecls(E); + if (!Decls.empty()) + return resolveDeclsToType(Decls, Ctx); + + return E->getType().getTypePtr(); +} + +const Type *HeuristicResolver::resolveNestedNameSpecifierToType( + const NestedNameSpecifier *NNS) const { + if (!NNS) + return nullptr; + + // The purpose of this function is to handle the dependent (Kind == + // Identifier) case, but we need to recurse on the prefix because + // that may be dependent as well, so for convenience handle + // the TypeSpec cases too. + switch (NNS->getKind()) { + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + return NNS->getAsType(); + case NestedNameSpecifier::Identifier: { + return resolveDeclsToType( + resolveDependentMember( + resolveNestedNameSpecifierToType(NNS->getPrefix()), + NNS->getAsIdentifier(), TypeFilter), + Ctx); + } + default: + break; + } + return nullptr; +} + +namespace { + +bool isOrdinaryMember(const NamedDecl *ND) { + return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag | + Decl::IDNS_Member); +} + +bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, + DeclarationName Name) { + Path.Decls = RD->lookup(Name).begin(); + for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I) + if (isOrdinaryMember(*I)) + return true; + + return false; +} + +} // namespace + +bool HeuristicResolver::findOrdinaryMemberInDependentClasses( + const CXXBaseSpecifier *Specifier, CXXBasePath &Path, + DeclarationName Name) const { + CXXRecordDecl *RD = + resolveTypeToRecordDecl(Specifier->getType().getTypePtr()); + if (!RD) + return false; + return findOrdinaryMember(RD, Path, Name); +} + +std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName( + CXXRecordDecl *RD, DeclarationName Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) const { + std::vector<const NamedDecl *> Results; + + // Lookup in the class. + bool AnyOrdinaryMembers = false; + for (const NamedDecl *ND : RD->lookup(Name)) { + if (isOrdinaryMember(ND)) + AnyOrdinaryMembers = true; + if (Filter(ND)) + Results.push_back(ND); + } + if (AnyOrdinaryMembers) + return Results; + + // Perform lookup into our base classes. + CXXBasePaths Paths; + Paths.setOrigin(RD); + if (!RD->lookupInBases( + [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return findOrdinaryMemberInDependentClasses(Specifier, Path, Name); + }, + Paths, /*LookupInDependent=*/true)) + return Results; + for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end(); + I != E; ++I) { + if (isOrdinaryMember(*I) && Filter(*I)) + Results.push_back(*I); + } + return Results; +} + +std::vector<const NamedDecl *> HeuristicResolver::resolveDependentMember( + const Type *T, DeclarationName Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) const { + if (!T) + return {}; + if (auto *ET = T->getAs<EnumType>()) { + auto Result = ET->getDecl()->lookup(Name); + return {Result.begin(), Result.end()}; + } + if (auto *RD = resolveTypeToRecordDecl(T)) { + if (!RD->hasDefinition()) + return {}; + RD = RD->getDefinition(); + return lookupDependentName(RD, Name, Filter); + } + return {}; +} + +} // namespace clangd +} // namespace clang diff --git a/build/clang-plugin/mozsearch-plugin/from-clangd/HeuristicResolver.h b/build/clang-plugin/mozsearch-plugin/from-clangd/HeuristicResolver.h new file mode 100644 index 0000000000..dc04123d37 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/from-clangd/HeuristicResolver.h @@ -0,0 +1,122 @@ +//===--- HeuristicResolver.h - Resolution of dependent names -----*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEURISTICRESOLVER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEURISTICRESOLVER_H + +#include "clang/AST/Decl.h" +#include <vector> + +namespace clang { + +class ASTContext; +class CallExpr; +class CXXBasePath; +class CXXDependentScopeMemberExpr; +class DeclarationName; +class DependentScopeDeclRefExpr; +class NamedDecl; +class Type; +class UnresolvedUsingValueDecl; + +namespace clangd { + +// This class heuristic resolution of declarations and types in template code. +// +// As a compiler, clang only needs to perform certain types of processing on +// template code (such as resolving dependent names to declarations, or +// resolving the type of a dependent expression) after instantiation. Indeed, +// C++ language features such as template specialization mean such resolution +// cannot be done accurately before instantiation +// +// However, template code is written and read in uninstantiated form, and clangd +// would like to provide editor features like go-to-definition in template code +// where possible. To this end, clangd attempts to resolve declarations and +// types in uninstantiated code by using heuristics, understanding that the +// results may not be fully accurate but that this is better than nothing. +// +// At this time, the heuristic used is a simple but effective one: assume that +// template instantiations are based on the primary template definition and not +// not a specialization. More advanced heuristics may be added in the future. +class HeuristicResolver { +public: + HeuristicResolver(ASTContext &Ctx) : Ctx(Ctx) {} + + // Try to heuristically resolve certain types of expressions, declarations, or + // types to one or more likely-referenced declarations. + std::vector<const NamedDecl *> + resolveMemberExpr(const CXXDependentScopeMemberExpr *ME) const; + std::vector<const NamedDecl *> + resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) const; + std::vector<const NamedDecl *> + resolveTypeOfCallExpr(const CallExpr *CE) const; + std::vector<const NamedDecl *> + resolveCalleeOfCallExpr(const CallExpr *CE) const; + std::vector<const NamedDecl *> + resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const; + std::vector<const NamedDecl *> + resolveDependentNameType(const DependentNameType *DNT) const; + std::vector<const NamedDecl *> resolveTemplateSpecializationType( + const DependentTemplateSpecializationType *DTST) const; + + // Try to heuristically resolve a dependent nested name specifier + // to the type it likely denotes. Note that *dependent* name specifiers always + // denote types, not namespaces. + const Type * + resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const; + + // Given the type T of a dependent expression that appears of the LHS of a + // "->", heuristically find a corresponding pointee type in whose scope we + // could look up the name appearing on the RHS. + const Type *getPointeeType(const Type *T) const; + +private: + ASTContext &Ctx; + + // Given a tag-decl type and a member name, heuristically resolve the + // name to one or more declarations. + // The current heuristic is simply to look up the name in the primary + // template. This is a heuristic because the template could potentially + // have specializations that declare different members. + // Multiple declarations could be returned if the name is overloaded + // (e.g. an overloaded method in the primary template). + // This heuristic will give the desired answer in many cases, e.g. + // for a call to vector<T>::size(). + std::vector<const NamedDecl *> resolveDependentMember( + const Type *T, DeclarationName Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) const; + + // Try to heuristically resolve the type of a possibly-dependent expression + // `E`. + const Type *resolveExprToType(const Expr *E) const; + std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E) const; + + // Helper function for HeuristicResolver::resolveDependentMember() + // which takes a possibly-dependent type `T` and heuristically + // resolves it to a CXXRecordDecl in which we can try name lookup. + CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) const; + + // This is a reimplementation of CXXRecordDecl::lookupDependentName() + // so that the implementation can call into other HeuristicResolver helpers. + // FIXME: Once HeuristicResolver is upstreamed to the clang libraries + // (https://github.com/clangd/clangd/discussions/1662), + // CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites + // can be modified to benefit from the more comprehensive heuristics offered + // by HeuristicResolver instead. + std::vector<const NamedDecl *> lookupDependentName( + CXXRecordDecl *RD, DeclarationName Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) const; + bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + DeclarationName Name) const; +}; + +} // namespace clangd +} // namespace clang + +#endif diff --git a/build/clang-plugin/mozsearch-plugin/from-clangd/README.md b/build/clang-plugin/mozsearch-plugin/from-clangd/README.md new file mode 100644 index 0000000000..9f39dab231 --- /dev/null +++ b/build/clang-plugin/mozsearch-plugin/from-clangd/README.md @@ -0,0 +1,10 @@ +The facilities in this subdirectory are copied over from clangd +(https://clangd.llvm.org/). + +The files here are currently copies of the following upstream files: +https://github.com/llvm/llvm-project/blob/2bcbcbefcd0f7432f99cc07bb47d1e1ecb579a3f/clang-tools-extra/clangd/HeuristicResolver.h +https://github.com/llvm/llvm-project/blob/2bcbcbefcd0f7432f99cc07bb47d1e1ecb579a3f/clang-tools-extra/clangd/HeuristicResolver.cpp + +If, in the future, these facilities are moved from clangd to +to libclangTooling and exposed in the clang API headers, we can +switch to consuming them from there directly. diff --git a/build/clang-plugin/plugin.h b/build/clang-plugin/plugin.h new file mode 100644 index 0000000000..15e7560455 --- /dev/null +++ b/build/clang-plugin/plugin.h @@ -0,0 +1,57 @@ +/* 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/. */ + +#ifndef plugin_h__ +#define plugin_h__ + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Analysis/CFG.h" +#include "clang/Basic/Version.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Sema/Sema.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include <iterator> +#include <memory> + +#define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR) + +using namespace llvm; +using namespace clang; +using namespace clang::ast_matchers; + +#if CLANG_VERSION_FULL >= 306 +typedef std::unique_ptr<ASTConsumer> ASTConsumerPtr; +#else +typedef ASTConsumer *ASTConsumerPtr; +#endif + +#if CLANG_VERSION_FULL < 800 +// Starting with Clang 8.0 some basic functions have been renamed +#define getBeginLoc getLocStart +#define getEndLoc getLocEnd +#endif + +// In order to support running our checks using clang-tidy, we implement a +// source compatible base check class called BaseCheck, and we use the +// preprocessor to decide which base class to pick. +#ifdef CLANG_TIDY +#if CLANG_VERSION_FULL >= 900 +#include "../ClangTidyCheck.h" +#else +#include "../ClangTidy.h" +#endif +typedef clang::tidy::ClangTidyCheck BaseCheck; +typedef clang::tidy::ClangTidyContext ContextType; +#else +#include "BaseCheck.h" +#endif + +#endif // plugin_h__ diff --git a/build/clang-plugin/tests/Makefile.in b/build/clang-plugin/tests/Makefile.in new file mode 100644 index 0000000000..318c9a0261 --- /dev/null +++ b/build/clang-plugin/tests/Makefile.in @@ -0,0 +1,19 @@ +# 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/rules.mk + +$(OBJS): $(CLANG_PLUGIN) + +# Because building the objects doesn't actually build anything, create +# a stamp file to avoid re-running the tests unless the test files or +# the plugin changed. And since no objects are created, and not having +# the files around makes the rule always, we create dummy files here too. +tests-ok: $(OBJS) $(CSRCS) $(CPPSRCS) $(CLANG_PLUGIN) + touch $@ $(OBJS) + +target-objects: tests-ok + +# Don't actually build a library, since we don't actually build objects. +$(LIBRARY): EXPAND_LIBS_GEN=true diff --git a/build/clang-plugin/tests/NonParameterTestCases.h b/build/clang-plugin/tests/NonParameterTestCases.h new file mode 100644 index 0000000000..d38a14d944 --- /dev/null +++ b/build/clang-plugin/tests/NonParameterTestCases.h @@ -0,0 +1,61 @@ +MAYBE_STATIC void raw(Param x) {} + +MAYBE_STATIC void raw(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(NonParamUnion x) {} //expected-error {{Type 'NonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(NonParamClass x) {} //expected-error {{Type 'NonParamClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(NonParamEnum x) {} //expected-error {{Type 'NonParamEnum' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(NonParamEnumClass x) {} //expected-error {{Type 'NonParamEnumClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void raw(HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + +MAYBE_STATIC void const_(const NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const NonParamUnion x) {} //expected-error {{Type 'NonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const NonParamClass x) {} //expected-error {{Type 'NonParamClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const NonParamEnum x) {} //expected-error {{Type 'NonParamEnum' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const NonParamEnumClass x) {} //expected-error {{Type 'NonParamEnumClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC void const_(const HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + +MAYBE_STATIC void array(NonParam x[]) {} +MAYBE_STATIC void array(NonParamUnion x[]) {} +MAYBE_STATIC void array(NonParamClass x[]) {} +MAYBE_STATIC void array(NonParamEnum x[]) {} +MAYBE_STATIC void array(NonParamEnumClass x[]) {} +MAYBE_STATIC void array(HasNonParamStruct x[]) {} +MAYBE_STATIC void array(HasNonParamUnion x[]) {} +MAYBE_STATIC void array(HasNonParamStructUnion x[]) {} + +MAYBE_STATIC void ptr(NonParam* x) {} +MAYBE_STATIC void ptr(NonParamUnion* x) {} +MAYBE_STATIC void ptr(NonParamClass* x) {} +MAYBE_STATIC void ptr(NonParamEnum* x) {} +MAYBE_STATIC void ptr(NonParamEnumClass* x) {} +MAYBE_STATIC void ptr(HasNonParamStruct* x) {} +MAYBE_STATIC void ptr(HasNonParamUnion* x) {} +MAYBE_STATIC void ptr(HasNonParamStructUnion* x) {} + +MAYBE_STATIC void ref(NonParam& x) {} +MAYBE_STATIC void ref(NonParamUnion& x) {} +MAYBE_STATIC void ref(NonParamClass& x) {} +MAYBE_STATIC void ref(NonParamEnum& x) {} +MAYBE_STATIC void ref(NonParamEnumClass& x) {} +MAYBE_STATIC void ref(HasNonParamStruct& x) {} +MAYBE_STATIC void ref(HasNonParamUnion& x) {} +MAYBE_STATIC void ref(HasNonParamStructUnion& x) {} + +MAYBE_STATIC void constRef(const NonParam& x) {} +MAYBE_STATIC void constRef(const NonParamUnion& x) {} +MAYBE_STATIC void constRef(const NonParamClass& x) {} +MAYBE_STATIC void constRef(const NonParamEnum& x) {} +MAYBE_STATIC void constRef(const NonParamEnumClass& x) {} +MAYBE_STATIC void constRef(const HasNonParamStruct& x) {} +MAYBE_STATIC void constRef(const HasNonParamUnion& x) {} +MAYBE_STATIC void constRef(const HasNonParamStructUnion& x) {} + +MAYBE_STATIC inline void inlineRaw(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC inline void inlineRaw(NonParamUnion x) {} //expected-error {{Type 'NonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC inline void inlineRaw(NonParamClass x) {} //expected-error {{Type 'NonParamClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC inline void inlineRaw(NonParamEnum x) {} //expected-error {{Type 'NonParamEnum' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +MAYBE_STATIC inline void inlineRaw(NonParamEnumClass x) {} //expected-error {{Type 'NonParamEnumClass' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} diff --git a/build/clang-plugin/tests/TestAssertWithAssignment.cpp b/build/clang-plugin/tests/TestAssertWithAssignment.cpp new file mode 100644 index 0000000000..f0f049e4a3 --- /dev/null +++ b/build/clang-plugin/tests/TestAssertWithAssignment.cpp @@ -0,0 +1,68 @@ +#include "mozilla/MacroArgs.h" + +static __attribute__((always_inline)) bool MOZ_AssertAssignmentTest(bool expr) { + return expr; +} + +#define MOZ_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#define MOZ_CRASH() do { } while(0) +#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) MOZ_AssertAssignmentTest(!!(expr)) + +#define MOZ_ASSERT_HELPER1(expr) \ + do { \ + if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \ + MOZ_CRASH();\ + } \ + } while(0) \ + +/* Now the two-argument form. */ +#define MOZ_ASSERT_HELPER2(expr, explain) \ + do { \ + if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \ + MOZ_CRASH();\ + } \ + } while(0) \ + +#define MOZ_RELEASE_ASSERT_GLUE(a, b) a b +#define MOZ_RELEASE_ASSERT(...) \ + MOZ_RELEASE_ASSERT_GLUE( \ + MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \ + (__VA_ARGS__)) + +#define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__) + +void FunctionTest(int p) { + MOZ_ASSERT(p = 1); // expected-error {{Forbidden assignment in assert expression}} +} + +void FunctionTest2(int p) { + MOZ_ASSERT(((p = 1))); // expected-error {{Forbidden assignment in assert expression}} +} + +void FunctionTest3(int p) { + MOZ_ASSERT(p != 3); +} + +class TestOverloading { + int value; +public: + explicit TestOverloading(int _val) : value(_val) {} + // different operators + explicit operator bool() const { return true; } + TestOverloading& operator=(const int _val) { value = _val; return *this; } + + int& GetInt() {return value;} +}; + +void TestOverloadingFunc() { + TestOverloading p(2); + int f; + + MOZ_ASSERT(p); + MOZ_ASSERT(p = 3); // expected-error {{Forbidden assignment in assert expression}} + MOZ_ASSERT(p, "p is not valid"); + MOZ_ASSERT(p = 3, "p different than 3"); // expected-error {{Forbidden assignment in assert expression}} + MOZ_ASSERT(p.GetInt() = 2); // expected-error {{Forbidden assignment in assert expression}} + MOZ_ASSERT(p.GetInt() == 2); + MOZ_ASSERT(p.GetInt() == 2, f = 3); +} diff --git a/build/clang-plugin/tests/TestBadImplicitConversionCtor.cpp b/build/clang-plugin/tests/TestBadImplicitConversionCtor.cpp new file mode 100644 index 0000000000..ca2472582e --- /dev/null +++ b/build/clang-plugin/tests/TestBadImplicitConversionCtor.cpp @@ -0,0 +1,50 @@ +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +struct Foo { + Foo(int); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}} + Foo(int, char=0); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}} + Foo(...); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}} + template<class T> + Foo(float); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}} + Foo(int, unsigned); + Foo(Foo&); + Foo(const Foo&); + Foo(volatile Foo&); + Foo(const volatile Foo&); + Foo(Foo&&); + Foo(const Foo&&); + Foo(volatile Foo&&); + Foo(const volatile Foo&&); +}; + +struct Bar { + explicit Bar(int); + explicit Bar(int, char=0); + explicit Bar(...); +}; + +struct Baz { + MOZ_IMPLICIT Baz(int); + MOZ_IMPLICIT Baz(int, char=0); + MOZ_IMPLICIT Baz(...); +}; + +struct Barn { + Barn(int) = delete; + Barn(int, char=0) = delete; + Barn(...) = delete; +}; + +struct Abstract { + Abstract(int); + Abstract(int, char=0); + Abstract(...); + virtual void f() = 0; +}; + +template<class T> +struct Template { + Template(int); // expected-error {{bad implicit conversion constructor for 'Template'}} expected-note {{consider adding the explicit keyword to the constructor}} + template<class U> + Template(float); // expected-error {{bad implicit conversion constructor for 'Template'}} expected-note {{consider adding the explicit keyword to the constructor}} +}; diff --git a/build/clang-plugin/tests/TestCanRunScript.cpp b/build/clang-plugin/tests/TestCanRunScript.cpp new file mode 100644 index 0000000000..28795a31bf --- /dev/null +++ b/build/clang-plugin/tests/TestCanRunScript.cpp @@ -0,0 +1,881 @@ +#include <mozilla/RefPtr.h> +#include <mozilla/Maybe.h> + +#define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script"))) +#define MOZ_CAN_RUN_SCRIPT_BOUNDARY __attribute__((annotate("moz_can_run_script_boundary"))) + +MOZ_CAN_RUN_SCRIPT void test() { + +} + +void test_parent() { // expected-note {{caller function declared here}} + test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} +} + +MOZ_CAN_RUN_SCRIPT void test_parent2() { + test(); +} + +struct RefCountedBase; +MOZ_CAN_RUN_SCRIPT void test2(RefCountedBase* param) { + +} + +struct RefCountedBase { + void AddRef(); + void Release(); + + MOZ_CAN_RUN_SCRIPT void method_test() { + test(); + } + + MOZ_CAN_RUN_SCRIPT void method_test2() { + test2(this); + } + + virtual void method_test3() { // expected-note {{caller function declared here}} + test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} + } + + MOZ_CAN_RUN_SCRIPT void method_test4() { + method_test(); + } + + MOZ_CAN_RUN_SCRIPT void method_test5() { + this->method_test(); + } +}; + +MOZ_CAN_RUN_SCRIPT void testLambda() { + auto doIt = []() MOZ_CAN_RUN_SCRIPT { + test(); + }; + + auto doItWrong = []() { // expected-note {{caller function declared here}} + test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} + }; + + doIt(); + doItWrong(); +} + +void test2_parent() { // expected-note {{caller function declared here}} + test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'new RefCountedBase' is neither.}} \ + // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} +} + +MOZ_CAN_RUN_SCRIPT void test2_parent2() { + test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'new RefCountedBase' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test2_parent3(RefCountedBase* param) { + test2(param); + + RefCountedBase*& paramRef = param; + test2(paramRef); +} + +MOZ_CAN_RUN_SCRIPT void test2_parent4() { + RefPtr<RefCountedBase> refptr = new RefCountedBase; + test2(refptr); + RefPtr<RefCountedBase>& refptrRef = refptr; + test2(refptrRef); + const RefPtr<RefCountedBase>& refptrConstRef = refptr; + test2(refptrConstRef); + + RefPtr<RefCountedBase> refptrOther = refptr; + RefPtr<RefCountedBase>& refptrRef2 = refptr ? refptr : refptrOther; + test2(refptrRef2); + + RefPtr<RefCountedBase>* refPtrInHeap = new RefPtr<RefCountedBase>; + RefPtr<RefCountedBase>& refptrRefUnsafe1 = *refPtrInHeap; + test2(refptrRefUnsafe1); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe1' is neither.}} + + RefPtr<RefCountedBase>& refptrRefUnsafe2 = refPtrInHeap ? *refPtrInHeap : refptr; + test2(refptrRefUnsafe2); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe2' is neither.}} + + RefPtr<RefCountedBase>& refptrRefUnsafe3 = refPtrInHeap ? refptr : *refPtrInHeap; + test2(refptrRefUnsafe3); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe3' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test2_parent5() { + test2(MOZ_KnownLive(new RefCountedBase)); +} + +MOZ_CAN_RUN_SCRIPT void test2_parent6() { + RefPtr<RefCountedBase> refptr = new RefCountedBase; + refptr->method_test(); + refptr->method_test2(); + RefPtr<RefCountedBase>& refptrRef = refptr; + refptrRef->method_test(); + refptrRef->method_test2(); + + RefPtr<RefCountedBase> refptrOther = refptr; + RefPtr<RefCountedBase>& refptrRef2 = refptr ? refptr : refptrOther; + refptrRef2->method_test(); + refptrRef2->method_test2(); + + RefPtr<RefCountedBase>* refPtrInHeap = new RefPtr<RefCountedBase>; + RefPtr<RefCountedBase>& refptrRefUnsafe1 = *refPtrInHeap; + refptrRefUnsafe1->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe1->' is neither.}} + refptrRefUnsafe1->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe1->' is neither.}} + + RefPtr<RefCountedBase>& refptrRefUnsafe2 = refPtrInHeap ? *refPtrInHeap : refptr; + refptrRefUnsafe2->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe2->' is neither.}} + refptrRefUnsafe2->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe2->' is neither.}} + + RefPtr<RefCountedBase>& refptrRefUnsafe3 = refPtrInHeap ? refptr : *refPtrInHeap; + refptrRefUnsafe3->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe3->' is neither.}} + refptrRefUnsafe3->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe3->' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test2_parent7() { + RefCountedBase* t = new RefCountedBase; + t->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} + t->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} + + RefCountedBase*& tRef = t; + tRef->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'tRef' is neither.}} + tRef->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'tRef' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test2_parent8() { + test2(nullptr); +} + +MOZ_CAN_RUN_SCRIPT void test3(int* param) {} + +MOZ_CAN_RUN_SCRIPT void test3_parent() { + test3(new int); +} + +struct RefCountedChild : public RefCountedBase { + virtual void method_test3() override; // expected-note {{overridden function declared here}} expected-note {{overridden function declared here}} expected-note {{caller function declared here}} +}; + +void RefCountedChild::method_test3() { + test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} +} + +struct RefCountedSubChild : public RefCountedChild { + MOZ_CAN_RUN_SCRIPT void method_test3() override; // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT cannot override functions that are not marked MOZ_CAN_RUN_SCRIPT}} +}; + +void RefCountedSubChild::method_test3() { // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT cannot override functions that are not marked MOZ_CAN_RUN_SCRIPT}} + test(); +} + +MOZ_CAN_RUN_SCRIPT void test4() { + RefPtr<RefCountedBase> refptr1 = new RefCountedChild; + refptr1->method_test3(); + + RefPtr<RefCountedBase> refptr2 = new RefCountedSubChild; + refptr2->method_test3(); + + RefPtr<RefCountedChild> refptr3 = new RefCountedSubChild; + refptr3->method_test3(); + + RefPtr<RefCountedSubChild> refptr4 = new RefCountedSubChild; + refptr4->method_test3(); +} + +MOZ_CAN_RUN_SCRIPT_BOUNDARY void test5() { + RefPtr<RefCountedBase> refptr1 = new RefCountedChild; + refptr1->method_test3(); + + RefPtr<RefCountedBase> refptr2 = new RefCountedSubChild; + refptr2->method_test3(); + + RefPtr<RefCountedChild> refptr3 = new RefCountedSubChild; + refptr3->method_test3(); + + RefPtr<RefCountedSubChild> refptr4 = new RefCountedSubChild; + refptr4->method_test3(); +} + +// We should be able to call test5 from a non-can_run_script function. +void test5_b() { + test5(); +} + +MOZ_CAN_RUN_SCRIPT void test6() { + void* x = new RefCountedBase(); + test2((RefCountedBase*)x); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'x' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_ref(const RefCountedBase&) { + +} + +MOZ_CAN_RUN_SCRIPT void test_ref_1() { + RefCountedBase* t = new RefCountedBase; + test_ref(*t); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*t' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_ref_2() { + RefCountedBase* t = new RefCountedBase; + (*t).method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*t' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_ref_3() { + RefCountedBase* t = new RefCountedBase; + auto& ref = *t; + test_ref(ref); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'ref' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_ref_4() { + RefCountedBase* t = new RefCountedBase; + auto& ref = *t; + ref.method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'ref' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_ref_5() { + RefPtr<RefCountedBase> t = new RefCountedBase; + test_ref(*t); +} + +MOZ_CAN_RUN_SCRIPT void test_ref_6() { + RefPtr<RefCountedBase> t = new RefCountedBase; + (*t).method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ref_7() { + RefPtr<RefCountedBase> t = new RefCountedBase; + auto& ref = *t; + MOZ_KnownLive(ref).method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ref_8() { + RefPtr<RefCountedBase> t = new RefCountedBase; + auto& ref = *t; + test_ref(MOZ_KnownLive(ref)); +} + +MOZ_CAN_RUN_SCRIPT void test_ref_9() { + void* x = new RefCountedBase(); + test_ref(*(RefCountedBase*)x); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*(RefCountedBase*)x' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_maybe() { + mozilla::Maybe<RefCountedBase*> unsafe; + unsafe.emplace(new RefCountedBase); + (*unsafe)->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*unsafe' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_maybe_2() { + // FIXME(bz): This should not generate an error! + mozilla::Maybe<RefPtr<RefCountedBase>> safe; + safe.emplace(new RefCountedBase); + (*safe)->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '(*safe){{(->)?}}' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_helper_1(RefCountedBase* arg = nullptr) { +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_1() { + test_defaults_helper_1(); +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_2() { + RefCountedBase* t = new RefCountedBase; + test_defaults_helper_1(t); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_3() { + RefPtr<RefCountedBase> t = new RefCountedBase; + test_defaults_helper_1(t); +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_helper_2(RefCountedBase* arg = new RefCountedBase()) { // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'new RefCountedBase()' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_4() { + test_defaults_helper_2(); +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_5() { + RefCountedBase* t = new RefCountedBase; + test_defaults_helper_2(t); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_defaults_6() { + RefPtr<RefCountedBase> t = new RefCountedBase; + test_defaults_helper_2(t); +} + +MOZ_CAN_RUN_SCRIPT void test_arg_deref_helper(RefCountedBase&) { +} + +MOZ_CAN_RUN_SCRIPT void test_arg_deref(RefCountedBase* arg) { + test_arg_deref_helper(*arg); +} + +struct RefCountedDerefTester : public RefCountedBase { + MOZ_CAN_RUN_SCRIPT void foo() { + test_arg_deref_helper(*this); + } +}; + +struct DisallowMemberArgs { + RefPtr<RefCountedBase> mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + mRefCounted->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted{{(->)?}}' is neither.}} + + RefPtr<RefCountedBase>& unsafeMemberRef = mRefCounted; + unsafeMemberRef->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef{{(->)?}}' is neither.}} + + RefPtr<RefCountedBase> safeRefCounted = mRefCounted; + RefPtr<RefCountedBase>& maybeUnsafeMemberRef1 = mRefCounted ? mRefCounted : safeRefCounted; + maybeUnsafeMemberRef1->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1{{(->)?}}' is neither.}} + RefPtr<RefCountedBase>& maybeUnsafeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; + maybeUnsafeMemberRef2->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2{{(->)?}}' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted' is neither.}} + + RefPtr<RefCountedBase>& unsafeMemberRef = mRefCounted; + test2(unsafeMemberRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef' is neither.}} + + RefPtr<RefCountedBase> safeRefCounted = mRefCounted; + RefPtr<RefCountedBase>& maybeUnsafeMemberRef1 = mRefCounted ? mRefCounted : safeRefCounted; + test2(maybeUnsafeMemberRef1); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1' is neither.}} + RefPtr<RefCountedBase>& maybeUnsafeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; + test2(maybeUnsafeMemberRef2); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2' is neither.}} + } +}; + +struct DisallowMemberArgsWithGet { + RefPtr<RefCountedBase> mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + mRefCounted.get()->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted.get()' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mRefCounted.get()); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted.get()' is neither.}} + } +}; + +struct AllowKnownLiveMemberArgs { + RefPtr<RefCountedBase> mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + MOZ_KnownLive(mRefCounted)->method_test(); + + RefPtr<RefCountedBase>& unsafeMemberRef = mRefCounted; + MOZ_KnownLive(unsafeMemberRef)->method_test(); + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(MOZ_KnownLive(mRefCounted)); + + RefPtr<RefCountedBase>& unsafeMemberRef = mRefCounted; + test2(MOZ_KnownLive(unsafeMemberRef)); + } +}; + +struct WeakPtrReturner : public RefCountedBase { + RefCountedBase* getWeakPtr() { return new RefCountedBase(); } +}; + +struct DisallowMemberCallsOnRandomKnownLive { + RefPtr<WeakPtrReturner> mWeakPtrReturner1; + WeakPtrReturner* mWeakPtrReturner2; + + MOZ_CAN_RUN_SCRIPT void test_refptr_method() { + MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()' is neither.}} + } + + MOZ_CAN_RUN_SCRIPT void test_refptr_function() { + test2(MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()' is neither.}} + } + + MOZ_CAN_RUN_SCRIPT void test_raw_method() { + MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()' is neither.}} + } + + MOZ_CAN_RUN_SCRIPT void test_raw_function() { + test2(MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()' is neither.}} + } +}; + +struct AllowConstMemberArgs { + const RefPtr<RefCountedBase> mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + mRefCounted->method_test(); + + const RefPtr<RefCountedBase>& safeMemberRef1 = mRefCounted; + safeMemberRef1->method_test(); + + const RefPtr<RefCountedBase> safeRefCounted = new RefCountedBase; + const RefPtr<RefCountedBase>& safeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; + safeMemberRef2->method_test(); + const RefPtr<RefCountedBase>& safeMemberRef3 = mRefCounted ? mRefCounted : safeRefCounted; + safeMemberRef3->method_test(); + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mRefCounted); + + const RefPtr<RefCountedBase>& safeMemberRef1 = mRefCounted; + test2(safeMemberRef1); + + const RefPtr<RefCountedBase> safeRefCounted = new RefCountedBase; + const RefPtr<RefCountedBase>& safeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; + test2(safeMemberRef2); + const RefPtr<RefCountedBase>& safeMemberRef3 = mRefCounted ? mRefCounted : safeRefCounted; + test2(safeMemberRef3); + } +}; + +struct AllowConstMemberArgsWithExplicitThis { + const RefPtr<RefCountedBase> mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + this->mRefCounted->method_test(); + + const RefPtr<RefCountedBase>& safeMemberRef1 = this->mRefCounted; + safeMemberRef1->method_test(); + + const RefPtr<RefCountedBase> safeRefCounted = new RefCountedBase; + const RefPtr<RefCountedBase>& safeMemberRef2 = safeRefCounted ? safeRefCounted : this->mRefCounted; + safeMemberRef2->method_test(); + const RefPtr<RefCountedBase>& safeMemberRef3 = this->mRefCounted ? this->mRefCounted : safeRefCounted; + safeMemberRef3->method_test(); + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(this->mRefCounted); + + const RefPtr<RefCountedBase>& safeMemberRef1 = this->mRefCounted; + test2(safeMemberRef1); + + const RefPtr<RefCountedBase> safeRefCounted = new RefCountedBase; + const RefPtr<RefCountedBase>& safeMemberRef2 = safeRefCounted ? safeRefCounted : this->mRefCounted; + test2(safeMemberRef2); + const RefPtr<RefCountedBase>& safeMemberRef3 = this->mRefCounted ? this->mRefCounted : safeRefCounted; + test2(safeMemberRef3); + } +}; + +struct DisallowConstMemberArgsOfMembers { + RefPtr<AllowConstMemberArgs> mMember; + MOZ_CAN_RUN_SCRIPT void foo() { + mMember->mRefCounted->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mRefCounted{{(->)?}}' is neither.}} + + const RefPtr<RefCountedBase>& unsafeMemberRef = mMember->mRefCounted; + unsafeMemberRef->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef{{(->)?}}' is neither.}} + + const RefPtr<RefCountedBase> safeRefCounted = new RefCountedBase; + const RefPtr<RefCountedBase>& maybeUnsafeMemberRef1 = safeRefCounted ? safeRefCounted : mMember->mRefCounted; + maybeUnsafeMemberRef1->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1{{(->)?}}' is neither.}} + const RefPtr<RefCountedBase>& maybeUnsafeMemberRef2 = mMember->mRefCounted ? mMember->mRefCounted : safeRefCounted; + maybeUnsafeMemberRef2->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2{{(->)?}}' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mMember->mRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mRefCounted' is neither.}} + + const RefPtr<RefCountedBase>& unsafeMemberRef = mMember->mRefCounted; + test2(unsafeMemberRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef' is neither.}} + + const RefPtr<RefCountedBase> safeRefCounted = new RefCountedBase; + const RefPtr<RefCountedBase>& maybeUnsafeMemberRef1 = safeRefCounted ? safeRefCounted : mMember->mRefCounted; + test2(maybeUnsafeMemberRef1); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1' is neither.}} + const RefPtr<RefCountedBase>& maybeUnsafeMemberRef2 = mMember->mRefCounted ? mMember->mRefCounted : safeRefCounted; + test2(maybeUnsafeMemberRef2); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2' is neither.}} + } +}; + +struct DisallowConstNonRefPtrMemberArgs { + RefCountedBase* const mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + mRefCounted->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted' is neither.}} + + RefCountedBase* const& unsafeMemberRefCounted = mRefCounted; + unsafeMemberRefCounted->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRefCounted' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted' is neither.}} + + RefCountedBase* const& unsafeMemberRefCounted = mRefCounted; + test2(unsafeMemberRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRefCounted' is neither.}} + } +}; + +MOZ_CAN_RUN_SCRIPT void test_temporary_1() { +#ifdef MOZ_CLANG_PLUGIN_ALPHA + RefPtr<RefCountedBase>(new RefCountedBase())->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} +#else + RefPtr<RefCountedBase>(new RefCountedBase())->method_test(); +#endif +} + +MOZ_CAN_RUN_SCRIPT void test_temporary_2() { + test_ref(*RefPtr<RefCountedBase>(new RefCountedBase())); +} + +struct WeakSmartPtr { + RefCountedBase* member; + + explicit WeakSmartPtr(RefCountedBase* arg) : member(arg) {} + + RefCountedBase* operator->() const { + return member; + } + + RefCountedBase& operator*() const { + return *member; + } + + operator RefCountedBase*() const { + return member; + } +}; + +MOZ_CAN_RUN_SCRIPT void test_temporary_3() { + WeakSmartPtr(new RefCountedBase())->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'WeakSmartPtr(new RefCountedBase()){{(->)?}}' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_temporary_4() { + test_ref(*WeakSmartPtr(new RefCountedBase())); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*WeakSmartPtr(new RefCountedBase())' is neither.}} +} + +MOZ_CAN_RUN_SCRIPT void test_temporary_5() { + test2(WeakSmartPtr(new RefCountedBase())); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'WeakSmartPtr(new RefCountedBase())' is neither.}} +} + + +template<typename T> +struct TArray { + TArray() { + mArray[0] = new RefCountedBase(); + } + T& operator[](unsigned int index) { return mArray[index]; } + T mArray[1]; +}; + +struct DisallowRawTArrayElement { + TArray<RefCountedBase*> mArray; + MOZ_CAN_RUN_SCRIPT void foo() { + mArray[0]->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mArray[0]); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]' is neither.}} + } +}; + +struct DisallowRefPtrTArrayElement { + TArray<RefPtr<RefCountedBase>> mArray; + MOZ_CAN_RUN_SCRIPT void foo() { + mArray[0]->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]{{(->)?}}' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mArray[0]); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]' is neither.}} + } +}; + +struct AllowConstexprMembers { + static constexpr RefCountedBase* mRefCounted = nullptr; + static constexpr RefCountedBase* mRefCounted2 = nullptr; + MOZ_CAN_RUN_SCRIPT void foo() { + mRefCounted->method_test(); + } + MOZ_CAN_RUN_SCRIPT void bar() { + test2(mRefCounted); + } + MOZ_CAN_RUN_SCRIPT void baz() { + test_ref(*mRefCounted); + } +}; + +MOZ_CAN_RUN_SCRIPT void test_constexpr_1() { + AllowConstexprMembers::mRefCounted->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_constexpr_2() { + test2(AllowConstexprMembers::mRefCounted); +} + +MOZ_CAN_RUN_SCRIPT void test_constexpr_3() { + test_ref(*AllowConstexprMembers::mRefCounted); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_1(RefCountedBase* arg1, RefCountedBase* arg2) { + (arg1 ? arg1 : arg2)->method_test(); + RefCountedBase*& safeArg = arg1 ? arg1 : arg2; + safeArg->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_2(RefCountedBase* arg1, RefCountedBase* arg2) { + test2(arg1 ? arg1 : arg2); + RefCountedBase*& safeArg = arg1 ? arg1 : arg2; + test2(safeArg); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_3(RefCountedBase* arg1, RefCountedBase& arg2) { + (arg1 ? *arg1 : arg2).method_test(); + RefCountedBase& safeArg = arg1 ? *arg1 : arg2; + safeArg.method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_4(RefCountedBase* arg1, RefCountedBase& arg2) { + test_ref(arg1 ? *arg1 : arg2); + RefCountedBase& safeArg = arg1 ? *arg1 : arg2; + test_ref(safeArg); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_5(RefCountedBase* arg) { + RefPtr<RefCountedBase> local = new RefCountedBase(); + (arg ? arg : local.get())->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_6(RefCountedBase* arg) { + RefPtr<RefCountedBase> local = new RefCountedBase(); + test2(arg ? arg : local.get()); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_7(RefCountedBase* arg) { + RefPtr<RefCountedBase> local = new RefCountedBase(); + (arg ? *arg : *local).method_test(); + RefCountedBase& safeArgOrLocal = arg ? *arg : *local; + safeArgOrLocal.method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_8(RefCountedBase* arg) { + RefPtr<RefCountedBase> local = new RefCountedBase(); + test_ref(arg ? *arg : *local); + RefCountedBase& safeArgOrLocal = arg ? *arg : *local; + test_ref(safeArgOrLocal); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_9(RefCountedBase* arg) { + (arg ? arg : AllowConstexprMembers::mRefCounted)->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_10(RefCountedBase* arg) { + test2(arg ? arg : AllowConstexprMembers::mRefCounted); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_11(RefCountedBase* arg) { + (arg ? *arg : *AllowConstexprMembers::mRefCounted).method_test(); + RefCountedBase& safeArgOrMember = arg ? *arg : *AllowConstexprMembers::mRefCounted; + safeArgOrMember.method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_12(RefCountedBase* arg) { + test_ref(arg ? *arg : *AllowConstexprMembers::mRefCounted); + RefCountedBase& safeArgOrMember = arg ? *arg : *AllowConstexprMembers::mRefCounted; + test_ref(safeArgOrMember); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_13(RefCountedBase* arg1, RefCountedBase& arg2) { + (arg1 ? arg1 : &arg2)->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_44(RefCountedBase* arg1, RefCountedBase& arg2) { + test2(arg1 ? arg1 : &arg2); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_13(bool arg) { + (arg ? + AllowConstexprMembers::mRefCounted : + AllowConstexprMembers::mRefCounted2)->method_test(); + RefCountedBase* const& safeConstexprMember = arg ? AllowConstexprMembers::mRefCounted : AllowConstexprMembers::mRefCounted2; + safeConstexprMember->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_14(bool arg) { + test2(arg ? + AllowConstexprMembers::mRefCounted : + AllowConstexprMembers::mRefCounted2); + RefCountedBase* const& safeConstexprMember = arg ? AllowConstexprMembers::mRefCounted : AllowConstexprMembers::mRefCounted2; + test2(safeConstexprMember); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_15(bool arg) { + (arg ? + *AllowConstexprMembers::mRefCounted : + *AllowConstexprMembers::mRefCounted2).method_test(); + RefCountedBase& safeConstexprMember = arg ? *AllowConstexprMembers::mRefCounted : *AllowConstexprMembers::mRefCounted2; + safeConstexprMember.method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_ternary_16(bool arg) { + test_ref(arg ? + *AllowConstexprMembers::mRefCounted : + *AllowConstexprMembers::mRefCounted2); + RefCountedBase& safeConstexprMember = arg ? *AllowConstexprMembers::mRefCounted : *AllowConstexprMembers::mRefCounted2; + test_ref(safeConstexprMember); +} + +MOZ_CAN_RUN_SCRIPT void test_pointer_to_ref_1(RefCountedBase& arg) { + (&arg)->method_test(); +} + +MOZ_CAN_RUN_SCRIPT void test_pointer_to_ref_2(RefCountedBase& arg) { + test2(&arg); +} + +struct DisallowMemberArgsViaReferenceAlias { + RefPtr<RefCountedBase> mRefCounted; + MOZ_CAN_RUN_SCRIPT void foo() { + RefPtr<RefCountedBase>& bogus = mRefCounted; + bogus->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'bogus{{(->)?}}' is neither.}} + } + MOZ_CAN_RUN_SCRIPT void bar() { + RefPtr<RefCountedBase>& bogus = mRefCounted; + test2(bogus); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'bogus' is neither.}} + } +}; + +struct DisallowMemberArgsViaReferenceAlias2 { + RefPtr<RefCountedBase> mRefCountedArr[2]; + MOZ_CAN_RUN_SCRIPT void foo1() { + for (RefPtr<RefCountedBase>& item : mRefCountedArr) { + item->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item{{(->)?}}' is neither.}} + } + } + MOZ_CAN_RUN_SCRIPT void foo2() { + for (auto& item : mRefCountedArr) { + item->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item{{(->)?}}' is neither.}} + } + } + MOZ_CAN_RUN_SCRIPT void foo3() { + for (RefPtr<RefCountedBase> item : mRefCountedArr) { + item->method_test(); + } + } + MOZ_CAN_RUN_SCRIPT void foo4() { + for (auto item : mRefCountedArr) { + item->method_test(); + } + } + MOZ_CAN_RUN_SCRIPT void bar1() { + for (RefPtr<RefCountedBase>& item : mRefCountedArr) { + test2(item); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item' is neither.}} + } + } + MOZ_CAN_RUN_SCRIPT void bar2() { + for (auto& item : mRefCountedArr) { + test2(item); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item' is neither.}} + } + } + MOZ_CAN_RUN_SCRIPT void bar3() { + for (RefPtr<RefCountedBase> item : mRefCountedArr) { + test2(item); + } + } + MOZ_CAN_RUN_SCRIPT void bar4() { + for (auto item : mRefCountedArr) { + test2(item); + } + } +}; + +struct AllowMozKnownLiveMember { +public: + MOZ_KNOWN_LIVE RefCountedBase* mWhatever; + MOZ_KNOWN_LIVE RefPtr<RefCountedBase> mRefCountedWhatever; + MOZ_CAN_RUN_SCRIPT void fooPtr(RefCountedBase* aWhatever) {} + MOZ_CAN_RUN_SCRIPT void fooRef(RefCountedBase& aWhatever) {} + MOZ_CAN_RUN_SCRIPT void bar() { + fooPtr(mWhatever); + fooRef(*mWhatever); + fooPtr(mRefCountedWhatever); + fooRef(*mRefCountedWhatever); + + RefCountedBase*& whateverRef = mWhatever; + fooPtr(whateverRef); + fooRef(*whateverRef); + RefPtr<RefCountedBase>& refCountedWhateverRef = mRefCountedWhatever; + fooPtr(refCountedWhateverRef); + fooRef(*refCountedWhateverRef); + } +}; + +struct AllowMozKnownLiveMemberParent : AllowMozKnownLiveMember { + MOZ_CAN_RUN_SCRIPT void baz() { + fooPtr(mWhatever); + fooRef(*mWhatever); + fooPtr(mRefCountedWhatever); + fooRef(*mRefCountedWhatever); + + RefCountedBase*& whateverRef = mWhatever; + fooPtr(whateverRef); + fooRef(*whateverRef); + RefPtr<RefCountedBase>& refCountedWhateverRef = mRefCountedWhatever; + fooPtr(refCountedWhateverRef); + fooRef(*refCountedWhateverRef); + } +}; + +struct AllowMozKnownLiveParamMember { +public: + MOZ_CAN_RUN_SCRIPT void foo(AllowMozKnownLiveMember& aAllow) { + aAllow.fooPtr(aAllow.mWhatever); + aAllow.fooRef(*aAllow.mWhatever); + aAllow.fooPtr(aAllow.mRefCountedWhatever); + aAllow.fooRef(*aAllow.mRefCountedWhatever); + + RefCountedBase*& whateverRef = aAllow.mWhatever; + aAllow.fooPtr(whateverRef); + aAllow.fooRef(*whateverRef); + RefPtr<RefCountedBase>& refCountedWhateverRef = aAllow.mRefCountedWhatever; + aAllow.fooPtr(refCountedWhateverRef); + aAllow.fooRef(*refCountedWhateverRef); + } + MOZ_CAN_RUN_SCRIPT void bar(AllowMozKnownLiveMemberParent& aAllowParent) { + aAllowParent.fooPtr(aAllowParent.mWhatever); + aAllowParent.fooRef(*aAllowParent.mWhatever); + aAllowParent.fooPtr(aAllowParent.mRefCountedWhatever); + aAllowParent.fooRef(*aAllowParent.mRefCountedWhatever); + + RefCountedBase*& whateverRef = aAllowParent.mWhatever; + aAllowParent.fooPtr(whateverRef); + aAllowParent.fooRef(*whateverRef); + RefPtr<RefCountedBase>& refCountedWhateverRef = aAllowParent.mRefCountedWhatever; + aAllowParent.fooPtr(refCountedWhateverRef); + aAllowParent.fooRef(*refCountedWhateverRef); + } +}; + +MOZ_CAN_RUN_SCRIPT void AllowMozKnownLiveMemberInAutoStorage() { + AllowMozKnownLiveMember inStack; + AllowMozKnownLiveMember* inHeap = new AllowMozKnownLiveMember(); + inStack.fooPtr(inStack.mWhatever); + inStack.fooRef(*inStack.mWhatever); + inStack.fooPtr(inStack.mRefCountedWhatever); + inStack.fooRef(*inStack.mRefCountedWhatever); + RefCountedBase*& whateverRefInStack = inStack.mWhatever; + inStack.fooPtr(whateverRefInStack); + inStack.fooRef(*whateverRefInStack); + RefPtr<RefCountedBase>& refCountedWhateverRefInStack = inStack.mRefCountedWhatever; + inStack.fooPtr(refCountedWhateverRefInStack); + inStack.fooRef(*refCountedWhateverRefInStack); + + inStack.fooPtr(inHeap->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'inHeap->mWhatever' is neither.}} + inStack.fooRef(*inHeap->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*inHeap->mWhatever' is neither.}} + inStack.fooPtr(inHeap->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'inHeap->mRefCountedWhatever' is neither.}} + inStack.fooRef(*inHeap->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*inHeap->mRefCountedWhatever' is neither.}} + RefCountedBase*& whateverRefInHeap = inHeap->mWhatever; + inStack.fooPtr(whateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'whateverRefInHeap' is neither.}} + inStack.fooRef(*whateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*whateverRefInHeap' is neither.}} + RefPtr<RefCountedBase>& refCountedWhateverRefInHeap = inHeap->mRefCountedWhatever; + inStack.fooPtr(refCountedWhateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refCountedWhateverRefInHeap' is neither.}} + inStack.fooRef(*refCountedWhateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*refCountedWhateverRefInHeap' is neither.}} +} + +struct DisallowMozKnownLiveMemberNotFromKnownLive { + AllowMozKnownLiveMember* mMember; + MOZ_CAN_RUN_SCRIPT void fooPtr(RefCountedBase* aWhatever) {} + MOZ_CAN_RUN_SCRIPT void fooRef(RefCountedBase& aWhatever) {} + MOZ_CAN_RUN_SCRIPT void bar() { + fooPtr(mMember->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mWhatever' is neither.}} + fooRef(*mMember->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*mMember->mWhatever' is neither.}} + fooPtr(mMember->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mRefCountedWhatever' is neither.}} + fooRef(*mMember->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*mMember->mRefCountedWhatever' is neither.}} + RefCountedBase*& whateverRef = mMember->mWhatever; + fooPtr(whateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'whateverRef' is neither.}} + fooRef(*whateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*whateverRef' is neither.}} + RefPtr<RefCountedBase>& refCountedWhateverRef = mMember->mRefCountedWhatever; + fooPtr(refCountedWhateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refCountedWhateverRef' is neither.}} + fooRef(*refCountedWhateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*refCountedWhateverRef' is neither.}} + } +}; + +void IncorrectlyUnmarkedEarlyDeclaration(); // expected-note {{The first declaration exists here}} + +MOZ_CAN_RUN_SCRIPT void IncorrectlyUnmarkedEarlyDeclaration() {}; // expected-error {{MOZ_CAN_RUN_SCRIPT must be put in front of the declaration, not the definition}} diff --git a/build/clang-plugin/tests/TestCustomHeap.cpp b/build/clang-plugin/tests/TestCustomHeap.cpp new file mode 100644 index 0000000000..c1e82f2fa7 --- /dev/null +++ b/build/clang-plugin/tests/TestCustomHeap.cpp @@ -0,0 +1,29 @@ +#define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class"))) +#ifndef MOZ_HEAP_ALLOCATOR +#define MOZ_HEAP_ALLOCATOR \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((annotate("moz_heap_allocator"))) \ + _Pragma("GCC diagnostic pop") +#endif + +#include <stdlib.h> +#include <memory> + +struct MOZ_NONHEAP_CLASS X { +}; + +void *operator new(size_t x, int qual) MOZ_HEAP_ALLOCATOR { + return ::operator new(x); +} + +template <typename T> +T *customAlloc() MOZ_HEAP_ALLOCATOR { + T *arg = static_cast<T*>(malloc(sizeof(T))); + return new (arg) T(); +} + +void misuseX() { + X *foo = customAlloc<X>(); // expected-error {{variable of type 'X' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} + X *foo2 = new (100) X(); // expected-error {{variable of type 'X' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} +} diff --git a/build/clang-plugin/tests/TestDanglingOnTemporary.cpp b/build/clang-plugin/tests/TestDanglingOnTemporary.cpp new file mode 100644 index 0000000000..62a7755ece --- /dev/null +++ b/build/clang-plugin/tests/TestDanglingOnTemporary.cpp @@ -0,0 +1,45 @@ +#define MOZ_NO_DANGLING_ON_TEMPORARIES \ + __attribute__((annotate("moz_no_dangling_on_temporaries"))) + +class AnnotateConflict { + MOZ_NO_DANGLING_ON_TEMPORARIES int *get() && { return nullptr; } // expected-error {{methods annotated with MOZ_NO_DANGLING_ON_TEMPORARIES cannot be && ref-qualified}} + MOZ_NO_DANGLING_ON_TEMPORARIES int test() { return 0; } // expected-error {{methods annotated with MOZ_NO_DANGLING_ON_TEMPORARIES must return a pointer}} +}; + +class NS_ConvertUTF8toUTF16 { +public: + MOZ_NO_DANGLING_ON_TEMPORARIES int *get() { return nullptr; } + operator int*() + { + return get(); // This should be ignored because the call is implcitly on this + } +}; + +NS_ConvertUTF8toUTF16 TemporaryFunction() { return NS_ConvertUTF8toUTF16(); } + +void UndefinedFunction(int* test); + +void NoEscapeFunction(int *test) {} + +int *glob; // expected-note {{through the variable declared here}} +void EscapeFunction1(int *test) { glob = test; } // expected-note {{the raw pointer escapes the function scope here}} + +void EscapeFunction2(int *test, int *&escape) { escape = test; } // expected-note {{the raw pointer escapes the function scope here}} \ + expected-note {{through the parameter declared here}} + +int *EscapeFunction3(int *test) { return test; } // expected-note {{the raw pointer escapes the function scope here}} \ + expected-note {{through the return value of the function declared here}} + +int main() { + int *test = TemporaryFunction().get(); // expected-error {{calling `get` on a temporary, potentially allowing use after free of the raw pointer}} + int *test2 = NS_ConvertUTF8toUTF16().get(); // expected-error {{calling `get` on a temporary, potentially allowing use after free of the raw pointer}} + + UndefinedFunction(NS_ConvertUTF8toUTF16().get()); + + NoEscapeFunction(TemporaryFunction().get()); + EscapeFunction1(TemporaryFunction().get()); // expected-error {{calling `get` on a temporary, potentially allowing use after free of the raw pointer}} + + int *escape; + EscapeFunction2(TemporaryFunction().get(), escape); // expected-error {{calling `get` on a temporary, potentially allowing use after free of the raw pointer}} + int *escape2 = EscapeFunction3(TemporaryFunction().get()); // expected-error {{calling `get` on a temporary, potentially allowing use after free of the raw pointer}} +} diff --git a/build/clang-plugin/tests/TestExplicitOperatorBool.cpp b/build/clang-plugin/tests/TestExplicitOperatorBool.cpp new file mode 100644 index 0000000000..bc4b43a7d0 --- /dev/null +++ b/build/clang-plugin/tests/TestExplicitOperatorBool.cpp @@ -0,0 +1,11 @@ +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +struct Bad { + operator bool(); // expected-error {{bad implicit conversion operator for 'Bad'}} expected-note {{consider adding the explicit keyword to 'operator bool'}} +}; +struct Good { + explicit operator bool(); +}; +struct Okay { + MOZ_IMPLICIT operator bool(); +}; diff --git a/build/clang-plugin/tests/TestFopenUsage.cpp b/build/clang-plugin/tests/TestFopenUsage.cpp new file mode 100644 index 0000000000..19a89f88c9 --- /dev/null +++ b/build/clang-plugin/tests/TestFopenUsage.cpp @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <io.h> +#include <fcntl.h> +#include <fstream> +#include <windows.h> + +void func_fopen() { + FILE *f1 = fopen("dummy.txt", "rt"); // expected-warning {{Usage of ASCII file functions (here fopen) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + FILE *f2; + fopen_s(&f2, "dummy.txt", "rt"); // expected-warning {{Usage of ASCII file functions (here fopen_s) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + + int fh1 = _open("dummy.txt", _O_RDONLY); // expected-warning {{Usage of ASCII file functions (here _open) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + int fh2 = open("dummy.txt", _O_RDONLY); // expected-warning {{Usage of ASCII file functions (here open) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + int fh3 = _sopen("dummy.txt", _O_RDONLY, _SH_DENYRW); // expected-warning {{Usage of ASCII file functions (here _sopen) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + int fd4; + errno_t err = _sopen_s(&fd4, "dummy.txt", _O_RDONLY, _SH_DENYRW, 0); // expected-warning {{Usage of ASCII file functions (here _sopen_s) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + + std::fstream fs1; + fs1.open("dummy.txt"); // expected-warning {{Usage of ASCII file functions (here open) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + std::ifstream ifs1; + ifs1.open("dummy.txt"); // expected-warning {{Usage of ASCII file functions (here open) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + std::ofstream ofs1; + ofs1.open("dummy.txt"); // expected-warning {{Usage of ASCII file functions (here open) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} +#ifdef _MSC_VER + std::fstream fs2; + fs2.open(L"dummy.txt"); + std::ifstream ifs2; + ifs2.open(L"dummy.txt"); + std::ofstream ofs2; + ofs2.open(L"dummy.txt"); +#endif + + LPOFSTRUCT buffer; + HFILE hFile1 = OpenFile("dummy.txt", buffer, OF_READ); // expected-warning {{Usage of ASCII file functions (here OpenFile) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + +#ifndef UNICODE + // CreateFile is just an alias of CreateFileA + LPCSTR buffer2; + HANDLE hFile2 = CreateFile(buffer2, GENERIC_WRITE, 0, NULL, CREATE_NEW, // expected-warning {{Usage of ASCII file functions (here CreateFileA) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + FILE_ATTRIBUTE_NORMAL, NULL); +#else + // CreateFile is just an alias of CreateFileW and should not be matched + LPCWSTR buffer2; + HANDLE hFile2 = CreateFile(buffer2, GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, NULL); +#endif + LPCSTR buffer3; + HANDLE hFile3 = CreateFileA(buffer3, GENERIC_WRITE, 0, NULL, CREATE_NEW, // expected-warning {{Usage of ASCII file functions (here CreateFileA) is forbidden on Windows.}} expected-note {{On Windows executed functions: fopen, fopen_s, open, _open, _sopen, _sopen_s, OpenFile, CreateFileA should never be used due to lossy conversion from UTF8 to ANSI.}} + FILE_ATTRIBUTE_NORMAL, NULL); +} diff --git a/build/clang-plugin/tests/TestGlobalClass.cpp b/build/clang-plugin/tests/TestGlobalClass.cpp new file mode 100644 index 0000000000..7ce9c8d463 --- /dev/null +++ b/build/clang-plugin/tests/TestGlobalClass.cpp @@ -0,0 +1,52 @@ +#define MOZ_GLOBAL_CLASS __attribute__((annotate("moz_global_class"))) +#include <stddef.h> + +struct MOZ_GLOBAL_CLASS Global { + int i; + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_GLOBAL_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void misuseGlobalClass(int len) { + Global notValid; // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated in an automatic variable}} + Global alsoNotValid[2]; // expected-error-re {{variable of type 'Global{{ ?}}[2]' only valid as global}} expected-note-re {{'Global{{ ?}}[2]' is a global type because it is an array of global type 'Global'}} expected-note {{value incorrectly allocated in an automatic variable}} + static Global valid; + static Global alsoValid[2]; + + gobble(¬Valid); + gobble(&valid); + gobble(&alsoValid[0]); + + gobble(new Global); // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated on the heap}} + gobble(new Global[10]); // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated on the heap}} + gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' only valid as global}} expected-note {{value incorrectly allocated on the heap}} + gobble(len <= 5 ? &valid : new Global); // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated on the heap}} + + char buffer[sizeof(Global)]; + gobble(new (buffer) Global); +} + +Global valid; +struct RandomClass { + Global nonstaticMember; // expected-note {{'RandomClass' is a global type because member 'nonstaticMember' is a global type 'Global'}} + static Global staticMember; +}; +struct MOZ_GLOBAL_CLASS RandomGlobalClass { + Global nonstaticMember; + static Global staticMember; +}; + +struct BadInherit : Global {}; // expected-note {{'BadInherit' is a global type because it inherits from a global type 'Global'}} +struct MOZ_GLOBAL_CLASS GoodInherit : Global {}; + +void misuseGlobalClassEvenMore(int len) { + BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' only valid as global}} expected-note {{value incorrectly allocated in an automatic variable}} + RandomClass evenMoreInvalid; // expected-error {{variable of type 'RandomClass' only valid as global}} expected-note {{value incorrectly allocated in an automatic variable}} +} diff --git a/build/clang-plugin/tests/TestHeapClass.cpp b/build/clang-plugin/tests/TestHeapClass.cpp new file mode 100644 index 0000000000..0cdd939250 --- /dev/null +++ b/build/clang-plugin/tests/TestHeapClass.cpp @@ -0,0 +1,64 @@ +#define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class"))) +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +#include <stddef.h> + +struct MOZ_HEAP_CLASS Heap { + int i; + Heap() {} + MOZ_IMPLICIT Heap(int a) {} + Heap(int a, int b) {} + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_HEAP_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void gobbleref(const Heap&) { } + +void misuseHeapClass(int len) { + Heap invalid; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} + Heap alsoInvalid[2]; // expected-error-re {{variable of type 'Heap{{ ?}}[2]' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} expected-note-re {{'Heap{{ ?}}[2]' is a heap type because it is an array of heap type 'Heap'}} + static Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} + static Heap alsoInvalidStatic[2]; // expected-error-re {{variable of type 'Heap{{ ?}}[2]' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} expected-note-re {{'Heap{{ ?}}[2]' is a heap type because it is an array of heap type 'Heap'}} + + gobble(&invalid); + gobble(&invalidStatic); + gobble(&alsoInvalid[0]); + + gobbleref(Heap()); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}} + gobbleref(Heap(10, 20)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}} + gobbleref(Heap(10)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}} + gobbleref(10); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}} + + gobble(new Heap); + gobble(new Heap[10]); + gobble(new TemplateClass<int>); + gobble(len <= 5 ? &invalid : new Heap); + + char buffer[sizeof(Heap)]; + gobble(new (buffer) Heap); +} + +Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} +struct RandomClass { + Heap nonstaticMember; // expected-note {{'RandomClass' is a heap type because member 'nonstaticMember' is a heap type 'Heap'}} + static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} +}; +struct MOZ_HEAP_CLASS RandomHeapClass { + Heap nonstaticMember; + static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} +}; + +struct BadInherit : Heap {}; // expected-note {{'BadInherit' is a heap type because it inherits from a heap type 'Heap'}} +struct MOZ_HEAP_CLASS GoodInherit : Heap {}; + +void useStuffWrongly() { + BadInherit i; // expected-error {{variable of type 'BadInherit' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} + RandomClass r; // expected-error {{variable of type 'RandomClass' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} +} diff --git a/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp b/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp new file mode 100644 index 0000000000..0c04c3b2bd --- /dev/null +++ b/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp @@ -0,0 +1,46 @@ +#define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \ + __attribute__((annotate("moz_inherit_type_annotations_from_template_args"))) +#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) +#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable"))) +#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type"))) + +class Normal {}; +class MOZ_STACK_CLASS Stack {}; +class IndirectStack : Stack {}; // expected-note {{'IndirectStack' is a stack type because it inherits from a stack type 'Stack'}} +class ContainsStack { Stack m; }; // expected-note {{'ContainsStack' is a stack type because member 'm' is a stack type 'Stack'}} +class MOZ_NON_MEMMOVABLE Pointery {}; +class IndirectPointery : Pointery {}; // expected-note {{'IndirectPointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Pointery'}} +class ContainsPointery { Pointery m; }; // expected-note {{'ContainsPointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Pointery'}} + +template<class T> +class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Template {}; // expected-note-re 5 {{'Template<{{.*}}>' is a stack type because it has a template argument stack type '{{.*}}'}} expected-note-re 5 {{'Template<{{.*}}>' is a non-memmove()able type because it has a template argument non-memmove()able type '{{.*}}'}} +class IndirectTemplate : Template<Stack> {}; // expected-note {{'IndirectTemplate' is a stack type because it inherits from a stack type 'Template<Stack>'}} +class ContainsTemplate { Template<Stack> m; }; // expected-note {{'ContainsTemplate' is a stack type because member 'm' is a stack type 'Template<Stack>'}} + +static Template<Stack> a; // expected-error {{variable of type 'Template<Stack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +static Template<IndirectStack> b; // expected-error {{variable of type 'Template<IndirectStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +static Template<ContainsStack> c; // expected-error {{variable of type 'Template<ContainsStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +static IndirectTemplate d; // expected-error {{variable of type 'IndirectTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +static ContainsTemplate e; // expected-error {{variable of type 'ContainsTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +static Template<Normal> f; + +template<class T> +class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { // expected-error-re 8 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}} + char mForceInstantiation[sizeof(T)]; +}; +class IndirectTemplatePointery : Template<Pointery> {}; // expected-note {{'IndirectTemplatePointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Template<Pointery>'}} +class ContainsTemplatePointery { Template<Pointery> m; }; // expected-note {{'ContainsTemplatePointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Template<Pointery>'}} + +static Mover<Template<Pointery>> n; // expected-note-re {{instantiation of 'Mover<Template<Pointery>{{ ?}}>' requested here}} +static Mover<Template<IndirectPointery>> o; // expected-note-re {{instantiation of 'Mover<Template<IndirectPointery>{{ ?}}>' requested here}} +static Mover<Template<ContainsPointery>> p; // expected-note-re {{instantiation of 'Mover<Template<ContainsPointery>{{ ?}}>' requested here}} +static Mover<IndirectTemplatePointery> q; // expected-note {{instantiation of 'Mover<IndirectTemplatePointery>' requested here}} +static Mover<ContainsTemplatePointery> r; // expected-note {{instantiation of 'Mover<ContainsTemplatePointery>' requested here}} +static Mover<Template<Normal>> s; + +template<class T, class... Ts> +class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS ManyTs {}; // expected-note-re 3 {{'ManyTs<{{.*}}>' is a non-memmove()able type because it has a template argument non-memmove()able type '{{.*}}'}} + +static Mover<ManyTs<Pointery>> t; // expected-note-re {{instantiation of 'Mover<ManyTs<Pointery>{{ ?}}>' requested here}} +static Mover<ManyTs<Normal, Pointery>> u; // expected-note-re {{instantiation of 'Mover<ManyTs<Normal, Pointery>{{ ?}}>' requested here}} +static Mover<ManyTs<Normal, Normal, Pointery>> v; // expected-note-re {{instantiation of 'Mover<ManyTs<Normal, Normal, Pointery>{{ ?}}>' requested here}} diff --git a/build/clang-plugin/tests/TestJSHandleRootedTypedef.cpp b/build/clang-plugin/tests/TestJSHandleRootedTypedef.cpp new file mode 100644 index 0000000000..a0489e09ef --- /dev/null +++ b/build/clang-plugin/tests/TestJSHandleRootedTypedef.cpp @@ -0,0 +1,168 @@ +#include "js/TypeDecls.h" +#include "js/Value.h" +#include "js/GCVector.h" +#include "js/Id.h" + +class Foo { + void HandleFunction(JS::HandleFunction){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleId(JS::HandleId){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleObject(JS::HandleObject){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleScript(JS::HandleScript){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleString(JS::HandleString){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleSymbol(JS::HandleSymbol){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleBigInt(JS::HandleBigInt){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleValue(JS::HandleValue){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleValueVector(JS::HandleValueVector){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleObjectVector(JS::HandleObjectVector){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void HandleIdVector(JS::HandleIdVector){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + void MutableHandleFunction(JS::MutableHandleFunction){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleId(JS::MutableHandleId){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleObject(JS::MutableHandleObject){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleScript(JS::MutableHandleScript){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleString(JS::MutableHandleString){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleSymbol(JS::MutableHandleSymbol){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleBigInt(JS::MutableHandleBigInt){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleValue(JS::MutableHandleValue){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleValueVector(JS::MutableHandleValueVector){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleObjectVector(JS::MutableHandleObjectVector){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + void MutableHandleIdVector(JS::MutableHandleIdVector){}; // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + // Examples of preferred forms + void FullHandleFunction(JS::Handle<JSFunction*>){}; + void FullHandleId(JS::Handle<JS::PropertyKey>){}; + void FullHandleObject(JS::Handle<JSObject*>){}; + void FullHandleScript(JS::Handle<JSScript*>){}; + void FullHandleString(JS::Handle<JSString*>){}; + void FullHandleSymbol(JS::Handle<JS::Symbol*>){}; + void FullHandleBigInt(JS::Handle<JS::BigInt*>){}; + void FullHandleValue(JS::Handle<JS::Value>){}; + void FullHandleValueVector(JS::Handle<JS::StackGCVector<JS::Value>>){}; + void FullHandleObjectVector(JS::Handle<JS::StackGCVector<JSObject*>>){}; + void FullHandleIdVector(JS::HandleVector<JS::PropertyKey>){}; + void FullHandleValueVectorShorter(JS::HandleVector<JS::Value>){}; + void FullHandleObjectVectorShorter(JS::HandleVector<JSObject*>){}; + void FullHandleIdVectorShorter(JS::HandleVector<JS::PropertyKey>){}; + + void FullMutableHandleFunction(JS::MutableHandle<JSFunction*>){}; + void FullMutableHandleId(JS::MutableHandle<JS::PropertyKey>){}; + void FullMutableHandleObject(JS::MutableHandle<JSObject*>){}; + void FullMutableHandleScript(JS::MutableHandle<JSScript*>){}; + void FullMutableHandleString(JS::MutableHandle<JSString*>){}; + void FullMutableHandleSymbol(JS::MutableHandle<JS::Symbol*>){}; + void FullMutableHandleBigInt(JS::MutableHandle<JS::BigInt*>){}; + void FullMutableHandleValue(JS::MutableHandle<JS::Value*>){}; + void FullMutableHandleValueVector(JS::MutableHandle<JS::StackGCVector<JS::Value>>){}; + void FullMutableHandleObjectVector(JS::MutableHandle<JS::StackGCVector<JSObject*>>){}; + void FullMutableHandleIdVector(JS::MutableHandle<JS::StackGCVector<JS::PropertyKey>>){}; + void FullMutableHandleValueVectorShorter(JS::MutableHandleVector<JS::Value>){}; + void FullMutableHandleObjectVectorShorter(JS::MutableHandleVector<JSObject*>){}; + void FullMutableHandleIdVectorShorter(JS::MutableHandleVector<JS::PropertyKey>){}; +}; + +static void Bar(JSContext *aCx) { + JS::RootedObject RootedObject(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedFunction RootedFunction(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedScript RootedScript(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedString RootedString(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedSymbol RootedSymbol(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedBigInt RootedBigInt(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedId RootedId(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedValue RootedValue(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + JS::RootedValueVector RootedValueVector(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedObjectVector RootedObjectVector(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::RootedIdVector RootedIdVector(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + JS::PersistentRootedFunction PersistentRootedFunction(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedId PersistentRootedId(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedObject PersistentRootedObject(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedScript PersistentRootedScript(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedString PersistentRootedString(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedSymbol PersistentRootedSymbol(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedBigInt PersistentRootedBigInt(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedValue PersistentRootedValue(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + JS::PersistentRootedIdVector PersistentRootedIdVector(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::PersistentRootedObjectVector PersistentRootedObjectVector(aCx); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + JS::HandleFunction HandleFunction(RootedFunction); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleId HandleId(RootedId); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleObject HandleObject(RootedObject); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleScript HandleScript(RootedScript); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleString HandleString(RootedString); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleSymbol HandleSymbol(RootedSymbol); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleBigInt HandleBigInt(RootedBigInt); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleValue HandleValue(RootedValue); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleValueVector HandleValueVector(RootedValueVector); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleObjectVector HandleObjectVector(RootedObjectVector); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::HandleIdVector HandleIdVector(RootedIdVector); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + JS::MutableHandleFunction MutableHandleFunction(&RootedFunction); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleId MutableHandleId(&RootedId); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleObject MutableHandleObject(&RootedObject); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleScript MutableHandleScript(&RootedScript); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleString MutableHandleString(&RootedString); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleSymbol MutableHandleSymbol(&RootedSymbol); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleBigInt MutableHandleBigInt(&RootedBigInt); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleValue MutableHandleValue(&RootedValue); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleValueVector MutableHandleValueVector(&RootedValueVector); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleObjectVector MutableHandleObjectVector(&RootedObjectVector); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + JS::MutableHandleIdVector MutableHandleIdVector(&RootedIdVector); // expected-error {{The fully qualified types are preferred over the shorthand typedefs for JS::Handle/JS::Rooted types outside SpiderMonkey.}} + + // Examples of preferred forms + JS::Rooted<JSObject*> FullRootedObject(aCx); + JS::Rooted<JSFunction*> FullRootedFunction(aCx); + JS::Rooted<JSScript*> FullRootedScript(aCx); + JS::Rooted<JSString*> FullRootedString(aCx); + JS::Rooted<JS::Symbol*> FullRootedSymbol(aCx); + JS::Rooted<JS::BigInt*> FullRootedBigInt(aCx); + JS::Rooted<JS::PropertyKey> FullRootedId(aCx); + JS::Rooted<JS::Value> FullRootedValue(aCx); + + JS::RootedVector<JS::Value> FullRootedValueVector(aCx); + JS::RootedVector<JSObject*> FullRootedObjectVector(aCx); + JS::RootedVector<JS::PropertyKey> FullRootedIdVector(aCx); + + JS::PersistentRooted<JSFunction*> FullPersistentRootedFunction(aCx); + JS::PersistentRooted<JS::PropertyKey> FullPersistentRootedId(aCx); + JS::PersistentRooted<JSObject*> FullPersistentRootedObject(aCx); + JS::PersistentRooted<JSScript*> FullPersistentRootedScript(aCx); + JS::PersistentRooted<JSString*> FullPersistentRootedString(aCx); + JS::PersistentRooted<JS::Symbol*> FullPersistentRootedSymbol(aCx); + JS::PersistentRooted<JS::BigInt*> FullPersistentRootedBigInt(aCx); + JS::PersistentRooted<JS::Value> FullPersistentRootedValue(aCx); + + JS::PersistentRootedVector<JS::PropertyKey> FullPersistentRootedIdVector(aCx); + JS::PersistentRootedVector<JSObject*> FullPersistentRootedObjectVector(aCx); + + JS::Handle<JSFunction*> FullHandleFunction(FullRootedFunction); + JS::Handle<JS::PropertyKey> FullHandleId(FullRootedId); + JS::Handle<JSObject*> FullHandleObject(FullRootedObject); + JS::Handle<JSScript*> FullHandleScript(FullRootedScript); + JS::Handle<JSString*> FullHandleString(FullRootedString); + JS::Handle<JS::Symbol*> FullHandleSymbol(FullRootedSymbol); + JS::Handle<JS::BigInt*> FullHandleBigInt(FullRootedBigInt); + JS::Handle<JS::Value> FullHandleValue(FullRootedValue); + JS::Handle<JS::StackGCVector<JS::Value>> FullHandleValueVector(FullRootedValueVector); + JS::Handle<JS::StackGCVector<JSObject*>> FullHandleObjectVector(FullRootedObjectVector); + JS::Handle<JS::StackGCVector<JS::PropertyKey>> FullHandleIdVector(FullRootedIdVector); + JS::HandleVector<JS::Value> FullHandleValueVectorShorter(FullRootedValueVector); + JS::HandleVector<JSObject*> FullHandleObjectVectorShorter(FullRootedObjectVector); + JS::HandleVector<JS::PropertyKey> FullHandleIdVectorShorter(FullRootedIdVector); + + JS::MutableHandle<JSFunction*> FullMutableHandleFunction(&FullRootedFunction); + JS::MutableHandle<JS::PropertyKey> FullMutableHandleId(&FullRootedId); + JS::MutableHandle<JSObject*> FullMutableHandleObject(&FullRootedObject); + JS::MutableHandle<JSScript*> FullMutableHandleScript(&FullRootedScript); + JS::MutableHandle<JSString*> FullMutableHandleString(&FullRootedString); + JS::MutableHandle<JS::Symbol*> FullMutableHandleSymbol(&FullRootedSymbol); + JS::MutableHandle<JS::BigInt*> FullMutableHandleBigInt(&FullRootedBigInt); + JS::MutableHandle<JS::Value> FullMutableHandleValue(&FullRootedValue); + JS::MutableHandle<JS::StackGCVector<JS::Value>> FullMutableHandleValueVector(&FullRootedValueVector); + JS::MutableHandle<JS::StackGCVector<JSObject*>> FullMutableHandleObjectVector(&FullRootedObjectVector); + JS::MutableHandle<JS::StackGCVector<JS::PropertyKey>> FullMutableHandleIdVector(&FullRootedIdVector); + JS::MutableHandleVector<JS::Value> FullMutableHandleValueVectorShorter(&FullRootedValueVector); + JS::MutableHandleVector<JSObject*> FullMutableHandleObjectVectorShorter(&FullRootedObjectVector); + JS::MutableHandleVector<JS::PropertyKey> FullMutableHandleIdVectorShorter(&FullRootedIdVector); +} diff --git a/build/clang-plugin/tests/TestKnownLive.cpp b/build/clang-plugin/tests/TestKnownLive.cpp new file mode 100644 index 0000000000..8d01160d1d --- /dev/null +++ b/build/clang-plugin/tests/TestKnownLive.cpp @@ -0,0 +1,33 @@ +#include <mozilla/RefPtr.h> + +#define MOZ_KNOWN_LIVE __attribute__((annotate("moz_known_live"))) + +class Foo { + // dummy refcounting +public: + uint32_t AddRef() { return 0; } + uint32_t Release() { return 0; } + +private: + ~Foo() = default; +}; + +class Bar { + MOZ_KNOWN_LIVE RefPtr<Foo> mFoo; + Bar() : mFoo(new Foo()) {} + ~Bar() { mFoo = nullptr; } + + void Baz() { + mFoo = nullptr; // expected-error {{MOZ_KNOWN_LIVE members can only be modified by constructors and destructors}} + } +}; + +class Bar2 { + MOZ_KNOWN_LIVE Foo *mFoo; + Bar2() : mFoo(new Foo()) {} + ~Bar2() { mFoo = nullptr; } + + void Baz() { + mFoo = nullptr; // expected-error {{MOZ_KNOWN_LIVE members can only be modified by constructors and destructors}} + } +}; diff --git a/build/clang-plugin/tests/TestKungFuDeathGrip.cpp b/build/clang-plugin/tests/TestKungFuDeathGrip.cpp new file mode 100644 index 0000000000..0218015807 --- /dev/null +++ b/build/clang-plugin/tests/TestKungFuDeathGrip.cpp @@ -0,0 +1,142 @@ +#include <utility> + +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +template <typename T> +class already_AddRefed { +public: + already_AddRefed(); + T* mPtr; +}; + +template <typename T> +class RefPtr { +public: + RefPtr(); + MOZ_IMPLICIT RefPtr(T* aIn); + MOZ_IMPLICIT RefPtr(already_AddRefed<T> aIn); + + RefPtr(const RefPtr<T>& aOther) = default; + RefPtr& operator=(const RefPtr<T>&) = default; + + // We must define non-defaulted move operations as in the real RefPtr to make + // the type non-trivially-copyable. + RefPtr(RefPtr<T>&&); + RefPtr& operator=(RefPtr<T>&&); + + void swap(RefPtr<T>& aOther); + + ~RefPtr(); + T* mPtr; +}; + +template <typename T> +class nsCOMPtr { +public: + nsCOMPtr(); + MOZ_IMPLICIT nsCOMPtr(T* aIn); + MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T> aIn); + ~nsCOMPtr(); + T* mPtr; +}; + +class Type { +public: + static nsCOMPtr<Type> someStaticCOMPtr; + + void f(nsCOMPtr<Type> ignoredArgument, Type *param) { + nsCOMPtr<Type> never_referenced; + nsCOMPtr<Type> kfdg_t1(this); + nsCOMPtr<Type> kfdg_t2 = this; + nsCOMPtr<Type> kfdg_t3 = (this); + + nsCOMPtr<Type> kfdg_m1(p); // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m1', or explicitly pass 'kfdg_m1' to `mozilla::Unused`}} + nsCOMPtr<Type> kfdg_m2 = p; // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m2', or explicitly pass 'kfdg_m2' to `mozilla::Unused`}} + nsCOMPtr<Type> kfdg_m3(p); + kfdg_m3.mPtr->f(nullptr, nullptr); + nsCOMPtr<Type> kfdg_m4 = p; + kfdg_m4.mPtr->f(nullptr, nullptr); + + nsCOMPtr<Type> kfdg_a1((already_AddRefed<Type>())); + nsCOMPtr<Type> kfdg_a2 = already_AddRefed<Type>(); + + nsCOMPtr<Type> kfdg_p1(param); + nsCOMPtr<Type> kfdg_p2 = param; + + + RefPtr<Type> never_referenced2; + RefPtr<Type> kfdg_t4(this); + RefPtr<Type> kfdg_t5 = this; + RefPtr<Type> kfdg_t6 = (this); + + RefPtr<Type> kfdg_m5(p); // expected-error {{Unused "kungFuDeathGrip" 'RefPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m5', or explicitly pass 'kfdg_m5' to `mozilla::Unused`}} + RefPtr<Type> kfdg_m6 = p; // expected-error {{Unused "kungFuDeathGrip" 'RefPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m6', or explicitly pass 'kfdg_m6' to `mozilla::Unused`}} + RefPtr<Type> kfdg_m7(p); + kfdg_m7.mPtr->f(nullptr, nullptr); + RefPtr<Type> kfdg_m8 = p; + kfdg_m8.mPtr->f(nullptr, nullptr); + + RefPtr<Type> kfdg_a3((already_AddRefed<Type>())); + RefPtr<Type> kfdg_a4 = already_AddRefed<Type>(); + + RefPtr<Type> kfdg_p3(param); + RefPtr<Type> kfdg_p4 = param; + } + + Type *p; +}; + +struct Type2 { + void f() { + mWeakRef->f(nullptr, nullptr); + } + + void g() { + RefPtr<Type> kfdg; + kfdg.swap(mStrongRef); + f(); + } + + void h() { + RefPtr<Type> kfdg = std::move(mStrongRef); + f(); + } + + RefPtr<Type> mStrongRef; + Type* mWeakRef; +}; + +void f(nsCOMPtr<Type> ignoredArgument, Type *param) { + nsCOMPtr<Type> never_referenced; + Type t; + // Type *p = nullptr; + nsCOMPtr<Type> kfdg_m1(t.p); // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m1', or explicitly pass 'kfdg_m1' to `mozilla::Unused`}} + nsCOMPtr<Type> kfdg_m2 = t.p; // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m2', or explicitly pass 'kfdg_m2' to `mozilla::Unused`}} + nsCOMPtr<Type> kfdg_m3(t.p); + kfdg_m3.mPtr->f(nullptr, nullptr); + nsCOMPtr<Type> kfdg_m4 = t.p; + kfdg_m4.mPtr->f(nullptr, nullptr); + + nsCOMPtr<Type> kfdg_a1((already_AddRefed<Type>())); + nsCOMPtr<Type> kfdg_a2 = already_AddRefed<Type>(); + + nsCOMPtr<Type> kfdg_p1(param); + nsCOMPtr<Type> kfdg_p2 = param; + + + RefPtr<Type> never_referenced2; + RefPtr<Type> kfdg_m5(t.p); // expected-error {{Unused "kungFuDeathGrip" 'RefPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m5', or explicitly pass 'kfdg_m5' to `mozilla::Unused`}} + RefPtr<Type> kfdg_m6 = t.p; // expected-error {{Unused "kungFuDeathGrip" 'RefPtr<Type>' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m6', or explicitly pass 'kfdg_m6' to `mozilla::Unused`}} + RefPtr<Type> kfdg_m7(t.p); + kfdg_m7.mPtr->f(nullptr, nullptr); + RefPtr<Type> kfdg_m8 = t.p; + kfdg_m8.mPtr->f(nullptr, nullptr); + + RefPtr<Type> kfdg_a3((already_AddRefed<Type>())); + RefPtr<Type> kfdg_a4 = already_AddRefed<Type>(); + + RefPtr<Type> kfdg_p3(param); + RefPtr<Type> kfdg_p4 = param; +} + +nsCOMPtr<Type> Type::someStaticCOMPtr(nullptr); diff --git a/build/clang-plugin/tests/TestLoadLibraryUsage.cpp b/build/clang-plugin/tests/TestLoadLibraryUsage.cpp new file mode 100644 index 0000000000..319c9d6b2a --- /dev/null +++ b/build/clang-plugin/tests/TestLoadLibraryUsage.cpp @@ -0,0 +1,20 @@ +#include <windows.h> +#include "prlink.h" + +void Func() { + auto h1 = PR_LoadLibrary(nullptr); // expected-error {{Usage of ASCII file functions (such as PR_LoadLibrary) is forbidden.}} + auto h2 = PR_LoadLibrary("C:\\Some\\Path"); + auto h3 = LoadLibraryA(nullptr); // expected-error {{Usage of ASCII file functions (such as LoadLibraryA) is forbidden.}} + auto h4 = LoadLibraryA("C:\\Some\\Path"); + auto h5 = LoadLibraryExA(nullptr, nullptr, 0); // expected-error {{Usage of ASCII file functions (such as LoadLibraryExA) is forbidden.}} + auto h6 = LoadLibraryExA("C:\\Some\\Path", nullptr, 0); + +#ifndef UNICODE + // LoadLibrary is a defnine for LoadLibraryA + auto h7 = LoadLibrary(nullptr); // expected-error {{Usage of ASCII file functions (such as LoadLibraryA) is forbidden.}} + auto h8 = LoadLibrary("C:\\Some\\Path"); + // LoadLibraryEx is a define for LoadLibraryExA + auto h9 = LoadLibraryEx(nullptr, nullptr, 0); // expected-error {{Usage of ASCII file functions (such as LoadLibraryExA) is forbidden.}} + auto h10 = LoadLibraryEx("C:\\Some\\Path", nullptr, 0); +#endif +} diff --git a/build/clang-plugin/tests/TestMultipleAnnotations.cpp b/build/clang-plugin/tests/TestMultipleAnnotations.cpp new file mode 100644 index 0000000000..034367a58e --- /dev/null +++ b/build/clang-plugin/tests/TestMultipleAnnotations.cpp @@ -0,0 +1,19 @@ +#define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class"))) +#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) + +class MOZ_NON_TEMPORARY_CLASS MOZ_STACK_CLASS TestClass {}; + +TestClass foo; // expected-error {{variable of type 'TestClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} + +TestClass f() +{ + TestClass bar; + return bar; +} + +void gobbleref(const TestClass&) { } + +void g() +{ + gobbleref(f()); // expected-error {{variable of type 'TestClass' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} +} diff --git a/build/clang-plugin/tests/TestMustOverride.cpp b/build/clang-plugin/tests/TestMustOverride.cpp new file mode 100644 index 0000000000..8e053f6c23 --- /dev/null +++ b/build/clang-plugin/tests/TestMustOverride.cpp @@ -0,0 +1,63 @@ +#define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override"))) +// Ignore warnings not related to static analysis here +#pragma GCC diagnostic ignored "-Woverloaded-virtual" + +struct S { + virtual void f() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + virtual void g() MOZ_MUST_OVERRIDE; + virtual void h() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} +}; +struct C : S { // expected-error {{'C' must override 'f'}} expected-error {{'C' must override 'h'}} + virtual void g() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + virtual void h(int); + void q() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} +}; +struct D : C { // expected-error {{'D' must override 'g'}} expected-error {{'D' must override 'q'}} + virtual void f(); +}; + +struct Base { + virtual void VirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + void NonVirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + static void StaticMethod() MOZ_MUST_OVERRIDE; +}; + +struct DoesNotPropagate : Base { + virtual void VirtMethod(); + void NonVirtMethod(); + static void StaticMethod(); +}; + +struct Final : DoesNotPropagate { }; + +struct Propagates : Base { + virtual void VirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + void NonVirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + static void StaticMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} +}; + +struct FailsFinal : Propagates { }; // expected-error {{'FailsFinal' must override 'VirtMethod'}} expected-error {{'FailsFinal' must override 'NonVirtMethod'}} expected-error {{'FailsFinal' must override 'StaticMethod'}} + +struct WrongOverload : Base { // expected-error {{'WrongOverload' must override 'VirtMethod'}} expected-error {{'WrongOverload' must override 'NonVirtMethod'}} + virtual void VirtMethod() const; + void NonVirtMethod(int param); + static void StaticMethod(); +}; + +namespace A { namespace B { namespace C { + struct Param {}; + struct Base { + void f(Param p) MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}} + }; +}}} + +struct Param {}; + +struct Derived : A::B::C::Base { + typedef A::B::C::Param Typedef; + void f(Typedef t); +}; + +struct BadDerived : A::B::C::Base { // expected-error {{'BadDerived' must override 'f'}} + void f(Param p); +}; diff --git a/build/clang-plugin/tests/TestMustReturnFromCaller.cpp b/build/clang-plugin/tests/TestMustReturnFromCaller.cpp new file mode 100644 index 0000000000..c935be3cf8 --- /dev/null +++ b/build/clang-plugin/tests/TestMustReturnFromCaller.cpp @@ -0,0 +1,270 @@ +#include <cstddef> +#include <utility> + +#define MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG __attribute__((annotate("moz_must_return_from_caller_if_this_is_arg"))) +#define MOZ_MAY_CALL_AFTER_MUST_RETURN __attribute__((annotate("moz_may_call_after_must_return"))) + +struct Thrower { + void MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG Throw() {} +}; + +void DoAnythingElse(); +int MakeAnInt(); +int MOZ_MAY_CALL_AFTER_MUST_RETURN SafeMakeInt(); +bool Condition(); + +// It might be nicer to #include "mozilla/ScopeExit.h" and use that here -- but +// doing so also will #define the two attribute-macros defined above, running a +// risk of redefinition errors. Just stick to the normal clang-plugin test +// style and use as little external code as possible. + +template<typename Func> +class ScopeExit { + Func exitFunction; + bool callOnDestruction; +public: + explicit ScopeExit(Func&& func) + : exitFunction(std::move(func)) + , callOnDestruction(true) + {} + + ~ScopeExit() { + if (callOnDestruction) { + exitFunction(); + } + } + + void release() { callOnDestruction = false; } +}; + +template<typename ExitFunction> +ScopeExit<ExitFunction> +MakeScopeExit(ExitFunction&& func) +{ + return ScopeExit<ExitFunction>(std::move(func)); +} + +class Foo { +public: + __attribute__((annotate("moz_implicit"))) Foo(std::nullptr_t); + Foo(); +}; + +void a1(Thrower& thrower) { + thrower.Throw(); +} + +int a2(Thrower& thrower) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + return MakeAnInt(); +} + +int a3(Thrower& thrower) { + // RAII operations happening after a must-immediately-return are fine. + auto atExit = MakeScopeExit([] { DoAnythingElse(); }); + thrower.Throw(); + return 5; +} + +int a4(Thrower& thrower) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + return Condition() ? MakeAnInt() : MakeAnInt(); +} + +void a5(Thrower& thrower) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + DoAnythingElse(); +} + +int a6(Thrower& thrower) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + DoAnythingElse(); + return MakeAnInt(); +} + +int a7(Thrower& thrower) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + DoAnythingElse(); + return Condition() ? MakeAnInt() : MakeAnInt(); +} + +int a8(Thrower& thrower) { + thrower.Throw(); + return SafeMakeInt(); +} + +int a9(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return SafeMakeInt(); +} + +int a10(Thrower& thrower) { + auto atExit = MakeScopeExit([] { DoAnythingElse(); }); + + if (Condition()) { + thrower.Throw(); + return SafeMakeInt(); + } + + atExit.release(); + DoAnythingElse(); + return 5; +} + +void b1(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } +} + +int b2(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + } + return MakeAnInt(); +} + +int b3(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return 5; +} + +// Explicit test in orer to also verify the `UnaryOperator` node in the `CFG` +int b3a(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return -1; +} + +float b3b(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return 1.0f; +} + +bool b3c(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return false; +} + +int b4(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + } + return Condition() ? MakeAnInt() : MakeAnInt(); +} + +void b5(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + } + DoAnythingElse(); +} + +void b6(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + DoAnythingElse(); + } +} + +void b7(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + return; + } + DoAnythingElse(); +} + +void b8(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + DoAnythingElse(); + return; + } + DoAnythingElse(); +} + +void b9(Thrower& thrower) { + while (Condition()) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + } +} + +void b10(Thrower& thrower) { + while (Condition()) { + thrower.Throw(); + return; + } +} + +void b11(Thrower& thrower) { + thrower.Throw(); // expected-error {{You must immediately return after calling this function}} + if (Condition()) { + return; + } else { + return; + } +} + +void b12(Thrower& thrower) { + switch (MakeAnInt()) { + case 1: + break; + default: + thrower.Throw(); + return; + } +} + +void b13(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return; +} + +Foo b14(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + return nullptr; + } + return nullptr; +} + +Foo b15(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return nullptr; +} + +Foo b16(Thrower& thrower) { + if (Condition()) { + thrower.Throw(); + } + return Foo(); +} + +void c1() { + Thrower thrower; + thrower.Throw(); + DoAnythingElse(); // Should be allowed, since our thrower is not an arg +} + +class TestRet { + TestRet *b13(Thrower &thrower) { + if (Condition()) { + thrower.Throw(); + } + return this; + } +}; diff --git a/build/clang-plugin/tests/TestNANTestingExpr.cpp b/build/clang-plugin/tests/TestNANTestingExpr.cpp new file mode 100644 index 0000000000..9aac46d036 --- /dev/null +++ b/build/clang-plugin/tests/TestNANTestingExpr.cpp @@ -0,0 +1,24 @@ +#line 1 "tests/SkScalar.h" +// This checks that the whitelist accounts for #line directives and such. If you +// remove SkScalar from the whitelist, please change the filename here instead +// of adding expected diagnostics. +inline int headerSays(double x) { + return x != x; +} +#line 9 "TestNANTestingExpr.cpp" +void test(bool x); +void foo() { + float f, f2; + typedef double mydouble; + mydouble d; + double d2; + test(f == f); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using std::isnan instead}} + test(d == d); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using std::isnan instead}} + test(f != f); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using std::isnan instead}} + test(d != d); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using std::isnan instead}} + test(f != d); + test(d == (d - f)); + test(f == f2); + test(d == d2); + test(d + 1 == d); +} diff --git a/build/clang-plugin/tests/TestNANTestingExprC.c b/build/clang-plugin/tests/TestNANTestingExprC.c new file mode 100644 index 0000000000..ab2fead22a --- /dev/null +++ b/build/clang-plugin/tests/TestNANTestingExprC.c @@ -0,0 +1,17 @@ +/* expected-no-diagnostics */ +void test(int x); +void foo() { + float f, f2; + typedef double mydouble; + mydouble d; + double d2; + test(f == f); + test(d == d); + test(f != f); + test(d != d); + test(f != d); + test(d == (d - f)); + test(f == f2); + test(d == d2); + test(d + 1 == d); +} diff --git a/build/clang-plugin/tests/TestNeedsNoVTableType.cpp b/build/clang-plugin/tests/TestNeedsNoVTableType.cpp new file mode 100644 index 0000000000..9b7c405d80 --- /dev/null +++ b/build/clang-plugin/tests/TestNeedsNoVTableType.cpp @@ -0,0 +1,94 @@ +#define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type"))) + +template <class T> +struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer { // expected-error {{'PickyConsumer<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer<G>' cannot be instantiated because 'G' has a VTable}} + T *m; +}; + +template <class T> +struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_A { // expected-error {{'PickyConsumer_A<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_A<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_A<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_A<G>' cannot be instantiated because 'G' has a VTable}} + T *m; +}; +template <class T> +struct PickyConsumerWrapper { + PickyConsumer_A<T> m; // expected-note {{bad instantiation of 'PickyConsumer_A<B>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<E>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<F>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<G>' requested here}} +}; + +template <class T> +struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_B { // expected-error {{'PickyConsumer_B<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_B<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_B<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_B<G>' cannot be instantiated because 'G' has a VTable}} + T *m; +}; +template <class T> +struct PickyConsumerSubclass : PickyConsumer_B<T> {}; // expected-note {{bad instantiation of 'PickyConsumer_B<B>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<E>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<F>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<G>' requested here}} + +template <class T> +struct NonPickyConsumer { + T *m; +}; + +struct A {}; +struct B : virtual A {}; +struct C : A {}; +struct D { + void d(); +}; +struct E { + virtual void e(); +}; +struct F : E { + void e() final; +}; +struct G { + virtual void e() = 0; +}; + +void f() { + { + PickyConsumer<A> a1; + PickyConsumerWrapper<A> a2; + PickyConsumerSubclass<A> a3; + NonPickyConsumer<A> a4; + } + + { + PickyConsumer<B> a1; // expected-note {{bad instantiation of 'PickyConsumer<B>' requested here}} + PickyConsumerWrapper<B> a2; + PickyConsumerSubclass<B> a3; + NonPickyConsumer<B> a4; + } + + { + PickyConsumer<C> a1; + PickyConsumerWrapper<C> a2; + PickyConsumerSubclass<C> a3; + NonPickyConsumer<C> a4; + } + + { + PickyConsumer<D> a1; + PickyConsumerWrapper<D> a2; + PickyConsumerSubclass<D> a3; + NonPickyConsumer<D> a4; + } + + { + PickyConsumer<E> a1; // expected-note {{bad instantiation of 'PickyConsumer<E>' requested here}} + PickyConsumerWrapper<E> a2; + PickyConsumerSubclass<E> a3; + NonPickyConsumer<E> a4; + } + + { + PickyConsumer<F> a1; // expected-note {{bad instantiation of 'PickyConsumer<F>' requested here}} + PickyConsumerWrapper<F> a2; + PickyConsumerSubclass<F> a3; + NonPickyConsumer<F> a4; + } + + { + PickyConsumer<G> a1; // expected-note {{bad instantiation of 'PickyConsumer<G>' requested here}} + PickyConsumerWrapper<G> a2; + PickyConsumerSubclass<G> a3; + NonPickyConsumer<G> a4; + } +} diff --git a/build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp b/build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp new file mode 100644 index 0000000000..5db514f7ab --- /dev/null +++ b/build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp @@ -0,0 +1,110 @@ +#define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return"))) + +struct Test { + void AddRef(); + void Release(); + void foo(); +}; + +struct TestD : Test {}; + +struct S { + Test* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + Test& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + Test h() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +}; + +struct SD { + TestD* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + TestD& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + TestD h() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +}; + +template<class T> +struct X { + T* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + T& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + T h() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +}; + +template<class T> +struct SP { + T* operator->() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +}; + +Test* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +Test& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +Test h() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + +TestD* fd() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +TestD& gd() MOZ_NO_ADDREF_RELEASE_ON_RETURN; +TestD hd() MOZ_NO_ADDREF_RELEASE_ON_RETURN; + +void test() { + S s; + s.f()->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'S::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + s.f()->Release(); // expected-error{{'Release' must not be called on the return value of 'S::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + s.f()->foo(); + s.g().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'S::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + s.g().Release(); // expected-error{{'Release' must not be called on the return value of 'S::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + s.g().foo(); + s.h().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'S::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + s.h().Release(); // expected-error{{'Release' must not be called on the return value of 'S::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + s.h().foo(); + SD sd; + sd.f()->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'SD::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sd.f()->Release(); // expected-error{{'Release' must not be called on the return value of 'SD::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sd.f()->foo(); + sd.g().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'SD::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sd.g().Release(); // expected-error{{'Release' must not be called on the return value of 'SD::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sd.g().foo(); + sd.h().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'SD::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sd.h().Release(); // expected-error{{'Release' must not be called on the return value of 'SD::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sd.h().foo(); + X<Test> x; + x.f()->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'X<Test>::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + x.f()->Release(); // expected-error{{'Release' must not be called on the return value of 'X<Test>::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + x.f()->foo(); + x.g().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'X<Test>::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + x.g().Release(); // expected-error{{'Release' must not be called on the return value of 'X<Test>::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + x.g().foo(); + x.h().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'X<Test>::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + x.h().Release(); // expected-error{{'Release' must not be called on the return value of 'X<Test>::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + x.h().foo(); + X<TestD> xd; + xd.f()->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'X<TestD>::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + xd.f()->Release(); // expected-error{{'Release' must not be called on the return value of 'X<TestD>::f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + xd.f()->foo(); + xd.g().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'X<TestD>::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + xd.g().Release(); // expected-error{{'Release' must not be called on the return value of 'X<TestD>::g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + xd.g().foo(); + xd.h().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'X<TestD>::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + xd.h().Release(); // expected-error{{'Release' must not be called on the return value of 'X<TestD>::h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + xd.h().foo(); + SP<Test> sp; + sp->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'SP<Test>::operator->' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sp->Release(); // expected-error{{'Release' must not be called on the return value of 'SP<Test>::operator->' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + sp->foo(); + SP<TestD> spd; + spd->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'SP<TestD>::operator->' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + spd->Release(); // expected-error{{'Release' must not be called on the return value of 'SP<TestD>::operator->' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + spd->foo(); + f()->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + f()->Release(); // expected-error{{'Release' must not be called on the return value of 'f' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + f()->foo(); + g().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + g().Release(); // expected-error{{'Release' must not be called on the return value of 'g' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + g().foo(); + h().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + h().Release(); // expected-error{{'Release' must not be called on the return value of 'h' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + h().foo(); + fd()->AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'fd' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + fd()->Release(); // expected-error{{'Release' must not be called on the return value of 'fd' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + fd()->foo(); + gd().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'gd' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + gd().Release(); // expected-error{{'Release' must not be called on the return value of 'gd' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + gd().foo(); + hd().AddRef(); // expected-error{{'AddRef' must not be called on the return value of 'hd' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + hd().Release(); // expected-error{{'Release' must not be called on the return value of 'hd' which is marked with MOZ_NO_ADDREF_RELEASE_ON_RETURN}} + hd().foo(); +} diff --git a/build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp b/build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp new file mode 100644 index 0000000000..d147b17012 --- /dev/null +++ b/build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp @@ -0,0 +1,32 @@ +#define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg"))) + +struct X { + explicit X(int) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT; + void baz(int) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT; +}; + +int operator+(int, X); +int operator+(X, int); +int operator++(X); + +void badArithmeticsInArgs() { + int a = 1; + typedef int myint; + myint b = 2; + X goodObj1(a); + goodObj1.baz(b); + X badObj1(a + b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}} + X badObj2 = X(a ? 0 : ++a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}} + X badObj3(~a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}} + badObj1.baz(a - 1 - b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}} + badObj1.baz(++a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}} + badObj1.baz(a++); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}} + badObj1.baz(a || b); + badObj1.baz(a + goodObj1); + badObj1.baz(goodObj1 + a); + badObj1.baz(++goodObj1); + badObj1.baz(-1); + badObj1.baz(-1.0); + badObj1.baz(1 + 2); + badObj1.baz(1 << (sizeof(int)/2)); +} diff --git a/build/clang-plugin/tests/TestNoAutoType.cpp b/build/clang-plugin/tests/TestNoAutoType.cpp new file mode 100644 index 0000000000..6c6e65f243 --- /dev/null +++ b/build/clang-plugin/tests/TestNoAutoType.cpp @@ -0,0 +1,41 @@ +#define MOZ_NON_AUTOABLE __attribute__((annotate("moz_non_autoable"))) + +template<class T> +struct MOZ_NON_AUTOABLE ExplicitTypeTemplate {}; +struct MOZ_NON_AUTOABLE ExplicitType {}; +struct NonExplicitType {}; + +void f() { + { + ExplicitType a; + auto b = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType'}} expected-note {{Please write out this type explicitly}} + auto &br = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType &'}} expected-note {{Please write out this type explicitly}} + const auto &brc = a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitType &'}} expected-note {{Please write out this type explicitly}} + auto *bp = &a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType *'}} expected-note {{Please write out this type explicitly}} + const auto *bpc = &a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitType *'}} expected-note {{Please write out this type explicitly}} + } + + { + ExplicitTypeTemplate<int> a; + auto b = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitTypeTemplate<int>'}} expected-note {{Please write out this type explicitly}} + auto &br = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitTypeTemplate<int> &'}} expected-note {{Please write out this type explicitly}} + const auto &brc = a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitTypeTemplate<int> &'}} expected-note {{Please write out this type explicitly}} + auto *bp = &a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitTypeTemplate<int> *'}} expected-note {{Please write out this type explicitly}} + const auto *bpc = &a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitTypeTemplate<int> *'}} expected-note {{Please write out this type explicitly}} + } + + { + NonExplicitType c; + auto d = c; + auto &dr = c; + const auto &drc = c; + auto *dp = &c; + const auto *dpc = &c; + } +} + +ExplicitType A; +auto B = A; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType'}} expected-note {{Please write out this type explicitly}} + +NonExplicitType C; +auto D = C; diff --git a/build/clang-plugin/tests/TestNoDuplicateRefCntMember.cpp b/build/clang-plugin/tests/TestNoDuplicateRefCntMember.cpp new file mode 100644 index 0000000000..ff68e4fc7c --- /dev/null +++ b/build/clang-plugin/tests/TestNoDuplicateRefCntMember.cpp @@ -0,0 +1,49 @@ +class C1 {}; + +class RC1 { +public: + virtual void AddRef(); + virtual void Release(); + +private: + int mRefCnt; // expected-note 2 {{Superclass 'RC1' also has an mRefCnt member}} expected-note 3 {{Superclass 'RC1' has an mRefCnt member}} +}; + +class RC2 : public RC1 { // expected-error {{Refcounted record 'RC2' has multiple mRefCnt members}} +public: + virtual void AddRef(); + virtual void Release(); + +private: + int mRefCnt; // expected-note {{Consider using the _INHERITED macros for AddRef and Release here}} +}; + +class C2 : public RC1 {}; + +class RC3 : public RC1 {}; + +class RC4 : public RC3, public C2 {}; // expected-error {{Refcounted record 'RC4' has multiple superclasses with mRefCnt members}} + +class RC5 : public RC1 {}; + +class RC6 : public C1, public RC5 { // expected-error {{Refcounted record 'RC6' has multiple mRefCnt members}} +public: + virtual void AddRef(); + virtual void Release(); + +private: + int mRefCnt; // expected-note {{Consider using the _INHERITED macros for AddRef and Release here}} +}; + +class Predecl; + +class OtherRC { +public: + virtual void AddRef(); + virtual void Release(); + +private: + int mRefCnt; // expected-note {{Superclass 'OtherRC' has an mRefCnt member}} +}; + +class MultRCSuper : public RC1, public OtherRC {}; // expected-error {{Refcounted record 'MultRCSuper' has multiple superclasses with mRefCnt members}} diff --git a/build/clang-plugin/tests/TestNoExplicitMoveConstructor.cpp b/build/clang-plugin/tests/TestNoExplicitMoveConstructor.cpp new file mode 100644 index 0000000000..5aea6b1a7f --- /dev/null +++ b/build/clang-plugin/tests/TestNoExplicitMoveConstructor.cpp @@ -0,0 +1,25 @@ +class Foo { + Foo(Foo&& f); +}; + +class Bar { + explicit Bar(Bar&& f); // expected-error {{Move constructors may not be marked explicit}} +}; + +class Baz { + template<typename T> + explicit Baz(T&& f) {}; +}; + +class Quxx { + Quxx(); + Quxx(Quxx& q) = delete; + template<typename T> + explicit Quxx(T&& f) {}; +}; + +void f() { + // Move a quxx into a quxx! (This speciailizes Quxx's constructor to look like + // a move constructor - to make sure it doesn't trigger) + Quxx(Quxx()); +} diff --git a/build/clang-plugin/tests/TestNoNewThreadsChecker.cpp b/build/clang-plugin/tests/TestNoNewThreadsChecker.cpp new file mode 100644 index 0000000000..c10277c1c4 --- /dev/null +++ b/build/clang-plugin/tests/TestNoNewThreadsChecker.cpp @@ -0,0 +1,9 @@ +// Dummy NS_NewNamedThread. +void NS_NewNamedThread(const char *aName) {} + +void func_threads() { + // Test to see if the checker recognizes a bad name, and if it recognizes a + // name from the ThreadAllows.txt. + NS_NewNamedThread("A bad name"); // expected-error {{Thread name not recognized. Please use the background thread pool.}} expected-note {{NS_NewNamedThread has been deprecated in favor of background task dispatch via NS_DispatchBackgroundTask and NS_CreateBackgroundTaskQueue. If you must create a new ad-hoc thread, have your thread name added to ThreadAllows.txt.}} + NS_NewNamedThread("Checker Test"); +} diff --git a/build/clang-plugin/tests/TestNoPrincipalGetUri.cpp b/build/clang-plugin/tests/TestNoPrincipalGetUri.cpp new file mode 100644 index 0000000000..c94a2add8a --- /dev/null +++ b/build/clang-plugin/tests/TestNoPrincipalGetUri.cpp @@ -0,0 +1,31 @@ +class nsIPrincipal { +public: + void GetURI(int foo){}; +}; + +class SomePrincipal : public nsIPrincipal { +public: + void GetURI(int foo) {} +}; + +class NullPrincipal : public SomePrincipal {}; + +class SomeURI { +public: + void GetURI(int foo) {} +}; + +void f() { + nsIPrincipal *a = new SomePrincipal(); + a->GetURI(0); // expected-error {{Principal->GetURI is deprecated and will be removed soon. Please consider using the new helper functions of nsIPrincipal}} + + ::nsIPrincipal *b = new NullPrincipal(); + b->GetURI(0); // expected-error {{Principal->GetURI is deprecated and will be removed soon. Please consider using the new helper functions of nsIPrincipal}} + + SomeURI *c = new SomeURI(); + c->GetURI(0); + + SomePrincipal *d = new SomePrincipal(); + d->GetURI(0); + +} diff --git a/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp b/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp new file mode 100644 index 0000000000..aedc5af096 --- /dev/null +++ b/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp @@ -0,0 +1,682 @@ +#include <mozilla/StaticAnalysisFunctions.h> + +#include <functional> +#define MOZ_STRONG_REF +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +// Ensure that warnings about returning stack addresses of local variables are +// errors, so our `expected-error` annotations below work correctly. +#pragma GCC diagnostic error "-Wreturn-stack-address" + +struct RefCountedBase { + void AddRef(); + void Release(); +}; + +template <class T> +struct SmartPtr { + SmartPtr(); + MOZ_IMPLICIT SmartPtr(T*); + T* MOZ_STRONG_REF t; + T* operator->() const; +}; + +struct R : RefCountedBase { + void method(); +private: + void privateMethod(); +}; + +void take(...); +void foo() { + R* ptr; + SmartPtr<R> sp; + take([&](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + take([&](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + take([&](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + take([&](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + take([=](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + take([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + take([=](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + take([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + take([ptr](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + take([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + take([ptr](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + take([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + take([&ptr](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + take([&sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + take([&ptr](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + take([&sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +} + +void b() { + R* ptr; + SmartPtr<R> sp; + std::function<void(R*)>([&](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + std::function<void(R*)>([&](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + std::function<void(R*)>([=](R* argptr) { + R* localptr; + ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + argptr->method(); + localptr->method(); + }); + std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + std::function<void(R*)>([=](R* argptr) { + R* localptr; + take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + take(argptr); + take(localptr); + }); + std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + std::function<void(R*)>([&ptr](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + std::function<void(R*)>([&ptr](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +} + +// These tests would check c++14 deduced return types, if they were supported in +// our codebase. They are being kept here for convenience in the future if we do +// add support for c++14 deduced return types +#if 0 +auto d1() { + R* ptr; + SmartPtr<R> sp; + return ([&](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); +} +auto d2() { + R* ptr; + SmartPtr<R> sp; + return ([&](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); +} +auto d3() { + R* ptr; + SmartPtr<R> sp; + return ([&](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); +} +auto d4() { + R* ptr; + SmartPtr<R> sp; + return ([&](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +} +auto d5() { + R* ptr; + SmartPtr<R> sp; + return ([=](R* argptr) { + R* localptr; + ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + argptr->method(); + localptr->method(); + }); +} +auto d6() { + R* ptr; + SmartPtr<R> sp; + return ([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); +} +auto d8() { + R* ptr; + SmartPtr<R> sp; + return ([=](R* argptr) { + R* localptr; + take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + take(argptr); + take(localptr); + }); +} +auto d9() { + R* ptr; + SmartPtr<R> sp; + return ([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +} +auto d10() { + R* ptr; + SmartPtr<R> sp; + return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); +} +auto d11() { + R* ptr; + SmartPtr<R> sp; + return ([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); +} +auto d12() { + R* ptr; + SmartPtr<R> sp; + return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); +} +auto d13() { + R* ptr; + SmartPtr<R> sp; + return ([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +} +auto d14() { + R* ptr; + SmartPtr<R> sp; + return ([&ptr](R* argptr) { + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); +} +auto d15() { + R* ptr; + SmartPtr<R> sp; + return ([&sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); +} +auto d16() { + R* ptr; + SmartPtr<R> sp; + return ([&ptr](R* argptr) { + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); +} +auto d17() { + R* ptr; + SmartPtr<R> sp; + return ([&sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +} +#endif + +void e() { + auto e1 = []() { + R* ptr; + SmartPtr<R> sp; + return ([&](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} + R* localptr; +#if __clang_major__ >= 12 + ptr->method(); // expected-note{{implicitly captured by reference due to use here}} +#else + ptr->method(); +#endif + argptr->method(); + localptr->method(); + }); + }; + auto e2 = []() { + R* ptr; + SmartPtr<R> sp; + return ([&](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} + SmartPtr<R> localsp; +#if __clang_major__ >= 12 + sp->method(); // expected-note{{implicitly captured by reference due to use here}} +#else + sp->method(); +#endif + argsp->method(); + localsp->method(); + }); + }; + auto e3 = []() { + R* ptr; + SmartPtr<R> sp; + return ([&](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} + R* localptr; +#if __clang_major__ >= 12 + take(ptr); // expected-note{{implicitly captured by reference due to use here}} +#else + take(ptr); +#endif + take(argptr); + take(localptr); + }); + }; + auto e4 = []() { + R* ptr; + SmartPtr<R> sp; + return ([&](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} + SmartPtr<R> localsp; +#if __clang_major__ >= 12 + take(sp); // expected-note{{implicitly captured by reference due to use here}} +#else + take(sp); +#endif + take(argsp); + take(localsp); + }); + }; + auto e5 = []() { + R* ptr; + SmartPtr<R> sp; + return ([=](R* argptr) { + R* localptr; + ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + argptr->method(); + localptr->method(); + }); + }; + auto e6 = []() { + R* ptr; + SmartPtr<R> sp; + return ([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + }; + auto e8 = []() { + R* ptr; + SmartPtr<R> sp; + return ([=](R* argptr) { + R* localptr; + take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + take(argptr); + take(localptr); + }); + }; + auto e9 = []() { + R* ptr; + SmartPtr<R> sp; + return ([=](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + }; + auto e10 = []() { + R* ptr; + SmartPtr<R> sp; + return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); + }; + auto e11 = []() { + R* ptr; + SmartPtr<R> sp; + return ([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); + }; + auto e12 = []() { + R* ptr; + SmartPtr<R> sp; + return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); + }; + auto e13 = []() { + R* ptr; + SmartPtr<R> sp; + return ([sp](SmartPtr<R> argsp) { + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); + }; + auto e14 = []() { + R* ptr; + SmartPtr<R> sp; +#if __clang_major__ >= 12 + return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} expected-note{{captured by reference here}} + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); +#else + return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} + R* localptr; + ptr->method(); + argptr->method(); + localptr->method(); + }); +#endif + }; + auto e15 = []() { + R* ptr; + SmartPtr<R> sp; +#if __clang_major__ >= 12 + return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} expected-note{{captured by reference here}} + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); +#else + return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} + SmartPtr<R> localsp; + sp->method(); + argsp->method(); + localsp->method(); + }); +#endif + }; + auto e16 = []() { + R* ptr; + SmartPtr<R> sp; +#if __clang_major__ >= 12 + return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} expected-note{{captured by reference here}} + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); +#else + return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} + R* localptr; + take(ptr); + take(argptr); + take(localptr); + }); +#endif + }; + auto e17 = []() { + R* ptr; + SmartPtr<R> sp; +#if __clang_major__ >= 12 + return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} expected-note{{captured by reference here}} + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +#else + return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} + SmartPtr<R> localsp; + take(sp); + take(argsp); + take(localsp); + }); +#endif + }; +} + +void +R::privateMethod() { + SmartPtr<R> self = this; + std::function<void()>([&]() { + self->method(); + }); + std::function<void()>([&]() { + self->privateMethod(); + }); + std::function<void()>([&]() { + this->method(); + }); + std::function<void()>([&]() { + this->privateMethod(); + }); + std::function<void()>([=]() { + self->method(); + }); + std::function<void()>([=]() { + self->privateMethod(); + }); + std::function<void()>([=]() { + this->method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([=]() { + this->privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([self]() { + self->method(); + }); + std::function<void()>([self]() { + self->privateMethod(); + }); + std::function<void()>([this]() { + this->method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([this]() { + this->privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([this]() { + method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([this]() { + privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([=]() { + method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([=]() { + privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}} + }); + std::function<void()>([&]() { + method(); + }); + std::function<void()>([&]() { + privateMethod(); + }); + + std::function<void()>( + [instance = MOZ_KnownLive(this)]() { instance->privateMethod(); }); + + // It should be OK to go through `this` if we have captured a reference to it. + std::function<void()>([this, self]() { + this->method(); + this->privateMethod(); + method(); + privateMethod(); + }); +} diff --git a/build/clang-plugin/tests/TestNoUsingNamespaceMozillaJava.cpp b/build/clang-plugin/tests/TestNoUsingNamespaceMozillaJava.cpp new file mode 100644 index 0000000000..70cfbe1827 --- /dev/null +++ b/build/clang-plugin/tests/TestNoUsingNamespaceMozillaJava.cpp @@ -0,0 +1,29 @@ +namespace mozilla { +namespace java { +namespace sdk { +} // namespace sdk + +namespace future { +} // namespace future +} // namespace java +} // namespace mozilla + +namespace mozilla { + using namespace java; // expected-error{{using namespace mozilla::java is forbidden}} + using namespace java::future; // expected-error{{using namespace mozilla::java::future is forbidden}} +} + +using namespace mozilla::java::sdk; // expected-error{{using namespace mozilla::java::sdk is forbidden}} + +namespace shouldPass { + namespace java { + } + + using namespace java; +} + +using namespace shouldPass::java; + + +void test() { +} diff --git a/build/clang-plugin/tests/TestNonHeapClass.cpp b/build/clang-plugin/tests/TestNonHeapClass.cpp new file mode 100644 index 0000000000..26fe6404e0 --- /dev/null +++ b/build/clang-plugin/tests/TestNonHeapClass.cpp @@ -0,0 +1,62 @@ +#define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class"))) +#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) +#include <stddef.h> + +struct MOZ_NONHEAP_CLASS NonHeap { + int i; + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_NONHEAP_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void misuseNonHeapClass(int len) { + NonHeap valid; + NonHeap alsoValid[2]; + static NonHeap validStatic; + static NonHeap alsoValidStatic[2]; + + gobble(&valid); + gobble(&validStatic); + gobble(&alsoValid[0]); + + gobble(new NonHeap); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} + gobble(new NonHeap[10]); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} + gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} + gobble(len <= 5 ? &valid : new NonHeap); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} + + char buffer[sizeof(NonHeap)]; + gobble(new (buffer) NonHeap); +} + +NonHeap validStatic; +struct RandomClass { + NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap type because member 'nonstaticMember' is a non-heap type 'NonHeap'}} + static NonHeap staticMember; +}; +struct MOZ_NONHEAP_CLASS RandomNonHeapClass { + NonHeap nonstaticMember; + static NonHeap staticMember; +}; + +struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap type because it inherits from a non-heap type 'NonHeap'}} +struct MOZ_NONHEAP_CLASS GoodInherit : NonHeap {}; + +void useStuffWrongly() { + gobble(new BadInherit); // expected-error {{variable of type 'BadInherit' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} + gobble(new RandomClass); // expected-error {{variable of type 'RandomClass' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}} +} + +// Stack class overrides non-heap typees. +struct MOZ_STACK_CLASS StackClass {}; +struct MOZ_NONHEAP_CLASS InferredStackClass : GoodInherit { + NonHeap nonstaticMember; + StackClass stackClass; // expected-note {{'InferredStackClass' is a stack type because member 'stackClass' is a stack type 'StackClass'}} +}; + +InferredStackClass global; // expected-error {{variable of type 'InferredStackClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} diff --git a/build/clang-plugin/tests/TestNonMemMovable.cpp b/build/clang-plugin/tests/TestNonMemMovable.cpp new file mode 100644 index 0000000000..dfbb5a6c65 --- /dev/null +++ b/build/clang-plugin/tests/TestNonMemMovable.cpp @@ -0,0 +1,830 @@ +#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable"))) +#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type"))) +#define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members"))) + +/* + These are a bunch of structs with variable levels of memmovability. + They will be used as template parameters to the various NeedyTemplates +*/ +struct MOZ_NON_MEMMOVABLE NonMovable {}; +struct Movable {}; + +// Subclasses +struct S_NonMovable : NonMovable {}; // expected-note 51 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}} +struct S_Movable : Movable {}; + +// Members +struct W_NonMovable { + NonMovable m; // expected-note 34 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}} +}; +struct W_Movable { + Movable m; +}; + +// Wrapped Subclasses +struct WS_NonMovable { + S_NonMovable m; // expected-note 34 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}} +}; +struct WS_Movable { + S_Movable m; +}; + +// Combinations of the above +struct SW_NonMovable : W_NonMovable {}; // expected-note 17 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}} +struct SW_Movable : W_Movable {}; + +struct SWS_NonMovable : WS_NonMovable {}; // expected-note 17 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}} +struct SWS_Movable : WS_Movable {}; + +// Basic templated wrapper +template <class T> +struct Template_Inline { + T m; // expected-note-re 56 {{'Template_Inline<{{.*}}>' is a non-memmove()able type because member 'm' is a non-memmove()able type '{{.*}}'}} +}; + +template <class T> +struct Template_Ref { + T* m; +}; + +template <class T> +struct Template_Unused {}; + +template <class T> +struct MOZ_NON_MEMMOVABLE Template_NonMovable {}; + +/* + These tests take the following form: + DECLARATIONS => Declarations of the templates which are either marked with MOZ_NEEDS_MEMMOVABLE_TYPE + or which instantiate a MOZ_NEEDS_MEMMOVABLE_TYPE through some mechanism. + BAD N => Instantiations of the wrapper template with each of the non-memmovable types. + The prefix S_ means subclass, W_ means wrapped. Each of these rows should produce an error + on the NeedyTemplate in question, and a note at the instantiation location of that template. + Unfortunately, on every case more complicated than bad1, the instantiation location is + within another template. Thus, the notes are expected on the template in question which + actually instantiates the MOZ_NEEDS_MEMMOVABLE_TYPE template. + GOOD N => Instantiations of the wrapper template with each of the memmovable types. + This is meant as a sanity check to ensure that we don't reject valid instantiations of + templates. + + + Note 1: Each set uses it's own types to ensure that they don't re-use each-other's template specializations. + If they did, then some of the error messages would not be emitted (as error messages are emitted for template + specializations, rather than for variable declarations) + + Note 2: Every instance of NeedyTemplate contains a member of type T. This is to ensure that T is actually + instantiated (if T is a template) by clang. If T isn't instantiated, then we can't actually tell if it is + NON_MEMMOVABLE. (This is OK in practice, as you cannot memmove a type which you don't know the size of). + + Note 3: There are a set of tests for specializations of NeedyTemplate at the bottom. For each set of tests, + these tests contribute two expected errors to the templates. +*/ + +// +// 1 - Unwrapped MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate1 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate1<{{.*}}>' with non-memmovable template argument '{{.*}}'}} + +void bad1() { + NeedyTemplate1<NonMovable> a1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<S_NonMovable> a2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<W_NonMovable> a3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<WS_NonMovable> a4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<SW_NonMovable> a5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<SWS_NonMovable> a6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + + NeedyTemplate1<Template_Inline<NonMovable> > b1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_Inline<S_NonMovable> > b2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_Inline<W_NonMovable> > b3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_Inline<WS_NonMovable> > b4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_Inline<SW_NonMovable> > b5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_Inline<SWS_NonMovable> > b6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + + NeedyTemplate1<Template_NonMovable<NonMovable> > c1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<S_NonMovable> > c2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<W_NonMovable> > c3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<WS_NonMovable> > c4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<SW_NonMovable> > c5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<SWS_NonMovable> > c6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<Movable> > c7; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<S_Movable> > c8; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<W_Movable> > c9; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<WS_Movable> > c10; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<SW_Movable> > c11; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1<Template_NonMovable<SWS_Movable> > c12; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} +} + +void good1() { + NeedyTemplate1<Movable> a1; + NeedyTemplate1<S_Movable> a2; + NeedyTemplate1<W_Movable> a3; + NeedyTemplate1<WS_Movable> a4; + NeedyTemplate1<SW_Movable> a5; + NeedyTemplate1<SWS_Movable> a6; + + NeedyTemplate1<Template_Inline<Movable> > b1; + NeedyTemplate1<Template_Inline<S_Movable> > b2; + NeedyTemplate1<Template_Inline<W_Movable> > b3; + NeedyTemplate1<Template_Inline<WS_Movable> > b4; + NeedyTemplate1<Template_Inline<SW_Movable> > b5; + NeedyTemplate1<Template_Inline<SWS_Movable> > b6; + + NeedyTemplate1<Template_Unused<Movable> > c1; + NeedyTemplate1<Template_Unused<S_Movable> > c2; + NeedyTemplate1<Template_Unused<W_Movable> > c3; + NeedyTemplate1<Template_Unused<WS_Movable> > c4; + NeedyTemplate1<Template_Unused<SW_Movable> > c5; + NeedyTemplate1<Template_Unused<SWS_Movable> > c6; + NeedyTemplate1<Template_Unused<NonMovable> > c7; + NeedyTemplate1<Template_Unused<S_NonMovable> > c8; + NeedyTemplate1<Template_Unused<W_NonMovable> > c9; + NeedyTemplate1<Template_Unused<WS_NonMovable> > c10; + NeedyTemplate1<Template_Unused<SW_NonMovable> > c11; + NeedyTemplate1<Template_Unused<SWS_NonMovable> > c12; + + NeedyTemplate1<Template_Ref<Movable> > d1; + NeedyTemplate1<Template_Ref<S_Movable> > d2; + NeedyTemplate1<Template_Ref<W_Movable> > d3; + NeedyTemplate1<Template_Ref<WS_Movable> > d4; + NeedyTemplate1<Template_Ref<SW_Movable> > d5; + NeedyTemplate1<Template_Ref<SWS_Movable> > d6; + NeedyTemplate1<Template_Ref<NonMovable> > d7; + NeedyTemplate1<Template_Ref<S_NonMovable> > d8; + NeedyTemplate1<Template_Ref<W_NonMovable> > d9; + NeedyTemplate1<Template_Ref<WS_NonMovable> > d10; + NeedyTemplate1<Template_Ref<SW_NonMovable> > d11; + NeedyTemplate1<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 2 - Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate2 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate2<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T> +struct S_NeedyTemplate2 : NeedyTemplate2<T> {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate2<{{.*}}>' requested here}} + +void bad2() { + S_NeedyTemplate2<NonMovable> a1; + S_NeedyTemplate2<S_NonMovable> a2; + S_NeedyTemplate2<W_NonMovable> a3; + S_NeedyTemplate2<WS_NonMovable> a4; + S_NeedyTemplate2<SW_NonMovable> a5; + S_NeedyTemplate2<SWS_NonMovable> a6; + + S_NeedyTemplate2<Template_Inline<NonMovable> > b1; + S_NeedyTemplate2<Template_Inline<S_NonMovable> > b2; + S_NeedyTemplate2<Template_Inline<W_NonMovable> > b3; + S_NeedyTemplate2<Template_Inline<WS_NonMovable> > b4; + S_NeedyTemplate2<Template_Inline<SW_NonMovable> > b5; + S_NeedyTemplate2<Template_Inline<SWS_NonMovable> > b6; + + S_NeedyTemplate2<Template_NonMovable<NonMovable> > c1; + S_NeedyTemplate2<Template_NonMovable<S_NonMovable> > c2; + S_NeedyTemplate2<Template_NonMovable<W_NonMovable> > c3; + S_NeedyTemplate2<Template_NonMovable<WS_NonMovable> > c4; + S_NeedyTemplate2<Template_NonMovable<SW_NonMovable> > c5; + S_NeedyTemplate2<Template_NonMovable<SWS_NonMovable> > c6; + S_NeedyTemplate2<Template_NonMovable<Movable> > c7; + S_NeedyTemplate2<Template_NonMovable<S_Movable> > c8; + S_NeedyTemplate2<Template_NonMovable<W_Movable> > c9; + S_NeedyTemplate2<Template_NonMovable<WS_Movable> > c10; + S_NeedyTemplate2<Template_NonMovable<SW_Movable> > c11; + S_NeedyTemplate2<Template_NonMovable<SWS_Movable> > c12; +} + +void good2() { + S_NeedyTemplate2<Movable> a1; + S_NeedyTemplate2<S_Movable> a2; + S_NeedyTemplate2<W_Movable> a3; + S_NeedyTemplate2<WS_Movable> a4; + S_NeedyTemplate2<SW_Movable> a5; + S_NeedyTemplate2<SWS_Movable> a6; + + S_NeedyTemplate2<Template_Inline<Movable> > b1; + S_NeedyTemplate2<Template_Inline<S_Movable> > b2; + S_NeedyTemplate2<Template_Inline<W_Movable> > b3; + S_NeedyTemplate2<Template_Inline<WS_Movable> > b4; + S_NeedyTemplate2<Template_Inline<SW_Movable> > b5; + S_NeedyTemplate2<Template_Inline<SWS_Movable> > b6; + + S_NeedyTemplate2<Template_Unused<Movable> > c1; + S_NeedyTemplate2<Template_Unused<S_Movable> > c2; + S_NeedyTemplate2<Template_Unused<W_Movable> > c3; + S_NeedyTemplate2<Template_Unused<WS_Movable> > c4; + S_NeedyTemplate2<Template_Unused<SW_Movable> > c5; + S_NeedyTemplate2<Template_Unused<SWS_Movable> > c6; + S_NeedyTemplate2<Template_Unused<NonMovable> > c7; + S_NeedyTemplate2<Template_Unused<S_NonMovable> > c8; + S_NeedyTemplate2<Template_Unused<W_NonMovable> > c9; + S_NeedyTemplate2<Template_Unused<WS_NonMovable> > c10; + S_NeedyTemplate2<Template_Unused<SW_NonMovable> > c11; + S_NeedyTemplate2<Template_Unused<SWS_NonMovable> > c12; + + S_NeedyTemplate2<Template_Ref<Movable> > d1; + S_NeedyTemplate2<Template_Ref<S_Movable> > d2; + S_NeedyTemplate2<Template_Ref<W_Movable> > d3; + S_NeedyTemplate2<Template_Ref<WS_Movable> > d4; + S_NeedyTemplate2<Template_Ref<SW_Movable> > d5; + S_NeedyTemplate2<Template_Ref<SWS_Movable> > d6; + S_NeedyTemplate2<Template_Ref<NonMovable> > d7; + S_NeedyTemplate2<Template_Ref<S_NonMovable> > d8; + S_NeedyTemplate2<Template_Ref<W_NonMovable> > d9; + S_NeedyTemplate2<Template_Ref<WS_NonMovable> > d10; + S_NeedyTemplate2<Template_Ref<SW_NonMovable> > d11; + S_NeedyTemplate2<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 3 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate3 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate3<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T> +struct W_NeedyTemplate3 { + NeedyTemplate3<T> m; // expected-note-re 26 {{instantiation of 'NeedyTemplate3<{{.*}}>' requested here}} +}; +void bad3() { + W_NeedyTemplate3<NonMovable> a1; + W_NeedyTemplate3<S_NonMovable> a2; + W_NeedyTemplate3<W_NonMovable> a3; + W_NeedyTemplate3<WS_NonMovable> a4; + W_NeedyTemplate3<SW_NonMovable> a5; + W_NeedyTemplate3<SWS_NonMovable> a6; + + W_NeedyTemplate3<Template_Inline<NonMovable> > b1; + W_NeedyTemplate3<Template_Inline<S_NonMovable> > b2; + W_NeedyTemplate3<Template_Inline<W_NonMovable> > b3; + W_NeedyTemplate3<Template_Inline<WS_NonMovable> > b4; + W_NeedyTemplate3<Template_Inline<SW_NonMovable> > b5; + W_NeedyTemplate3<Template_Inline<SWS_NonMovable> > b6; + + W_NeedyTemplate3<Template_NonMovable<NonMovable> > c1; + W_NeedyTemplate3<Template_NonMovable<S_NonMovable> > c2; + W_NeedyTemplate3<Template_NonMovable<W_NonMovable> > c3; + W_NeedyTemplate3<Template_NonMovable<WS_NonMovable> > c4; + W_NeedyTemplate3<Template_NonMovable<SW_NonMovable> > c5; + W_NeedyTemplate3<Template_NonMovable<SWS_NonMovable> > c6; + W_NeedyTemplate3<Template_NonMovable<Movable> > c7; + W_NeedyTemplate3<Template_NonMovable<S_Movable> > c8; + W_NeedyTemplate3<Template_NonMovable<W_Movable> > c9; + W_NeedyTemplate3<Template_NonMovable<WS_Movable> > c10; + W_NeedyTemplate3<Template_NonMovable<SW_Movable> > c11; + W_NeedyTemplate3<Template_NonMovable<SWS_Movable> > c12; +} + +void good3() { + W_NeedyTemplate3<Movable> a1; + W_NeedyTemplate3<S_Movable> a2; + W_NeedyTemplate3<W_Movable> a3; + W_NeedyTemplate3<WS_Movable> a4; + W_NeedyTemplate3<SW_Movable> a5; + W_NeedyTemplate3<SWS_Movable> a6; + + W_NeedyTemplate3<Template_Inline<Movable> > b1; + W_NeedyTemplate3<Template_Inline<S_Movable> > b2; + W_NeedyTemplate3<Template_Inline<W_Movable> > b3; + W_NeedyTemplate3<Template_Inline<WS_Movable> > b4; + W_NeedyTemplate3<Template_Inline<SW_Movable> > b5; + W_NeedyTemplate3<Template_Inline<SWS_Movable> > b6; + + W_NeedyTemplate3<Template_Unused<Movable> > c1; + W_NeedyTemplate3<Template_Unused<S_Movable> > c2; + W_NeedyTemplate3<Template_Unused<W_Movable> > c3; + W_NeedyTemplate3<Template_Unused<WS_Movable> > c4; + W_NeedyTemplate3<Template_Unused<SW_Movable> > c5; + W_NeedyTemplate3<Template_Unused<SWS_Movable> > c6; + W_NeedyTemplate3<Template_Unused<NonMovable> > c7; + W_NeedyTemplate3<Template_Unused<S_NonMovable> > c8; + W_NeedyTemplate3<Template_Unused<W_NonMovable> > c9; + W_NeedyTemplate3<Template_Unused<WS_NonMovable> > c10; + W_NeedyTemplate3<Template_Unused<SW_NonMovable> > c11; + W_NeedyTemplate3<Template_Unused<SWS_NonMovable> > c12; + + W_NeedyTemplate3<Template_Ref<Movable> > d1; + W_NeedyTemplate3<Template_Ref<S_Movable> > d2; + W_NeedyTemplate3<Template_Ref<W_Movable> > d3; + W_NeedyTemplate3<Template_Ref<WS_Movable> > d4; + W_NeedyTemplate3<Template_Ref<SW_Movable> > d5; + W_NeedyTemplate3<Template_Ref<SWS_Movable> > d6; + W_NeedyTemplate3<Template_Ref<NonMovable> > d7; + W_NeedyTemplate3<Template_Ref<S_NonMovable> > d8; + W_NeedyTemplate3<Template_Ref<W_NonMovable> > d9; + W_NeedyTemplate3<Template_Ref<WS_NonMovable> > d10; + W_NeedyTemplate3<Template_Ref<SW_NonMovable> > d11; + W_NeedyTemplate3<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 4 - Wrapped Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate4 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate4<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T> +struct S_NeedyTemplate4 : NeedyTemplate4<T> {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate4<{{.*}}>' requested here}} +template <class T> +struct WS_NeedyTemplate4 { + S_NeedyTemplate4<T> m; +}; +void bad4() { + WS_NeedyTemplate4<NonMovable> a1; + WS_NeedyTemplate4<S_NonMovable> a2; + WS_NeedyTemplate4<W_NonMovable> a3; + WS_NeedyTemplate4<WS_NonMovable> a4; + WS_NeedyTemplate4<SW_NonMovable> a5; + WS_NeedyTemplate4<SWS_NonMovable> a6; + + WS_NeedyTemplate4<Template_Inline<NonMovable> > b1; + WS_NeedyTemplate4<Template_Inline<S_NonMovable> > b2; + WS_NeedyTemplate4<Template_Inline<W_NonMovable> > b3; + WS_NeedyTemplate4<Template_Inline<WS_NonMovable> > b4; + WS_NeedyTemplate4<Template_Inline<SW_NonMovable> > b5; + WS_NeedyTemplate4<Template_Inline<SWS_NonMovable> > b6; + + WS_NeedyTemplate4<Template_NonMovable<NonMovable> > c1; + WS_NeedyTemplate4<Template_NonMovable<S_NonMovable> > c2; + WS_NeedyTemplate4<Template_NonMovable<W_NonMovable> > c3; + WS_NeedyTemplate4<Template_NonMovable<WS_NonMovable> > c4; + WS_NeedyTemplate4<Template_NonMovable<SW_NonMovable> > c5; + WS_NeedyTemplate4<Template_NonMovable<SWS_NonMovable> > c6; + WS_NeedyTemplate4<Template_NonMovable<Movable> > c7; + WS_NeedyTemplate4<Template_NonMovable<S_Movable> > c8; + WS_NeedyTemplate4<Template_NonMovable<W_Movable> > c9; + WS_NeedyTemplate4<Template_NonMovable<WS_Movable> > c10; + WS_NeedyTemplate4<Template_NonMovable<SW_Movable> > c11; + WS_NeedyTemplate4<Template_NonMovable<SWS_Movable> > c12; +} + +void good4() { + WS_NeedyTemplate4<Movable> a1; + WS_NeedyTemplate4<S_Movable> a2; + WS_NeedyTemplate4<W_Movable> a3; + WS_NeedyTemplate4<WS_Movable> a4; + WS_NeedyTemplate4<SW_Movable> a5; + WS_NeedyTemplate4<SWS_Movable> a6; + + WS_NeedyTemplate4<Template_Inline<Movable> > b1; + WS_NeedyTemplate4<Template_Inline<S_Movable> > b2; + WS_NeedyTemplate4<Template_Inline<W_Movable> > b3; + WS_NeedyTemplate4<Template_Inline<WS_Movable> > b4; + WS_NeedyTemplate4<Template_Inline<SW_Movable> > b5; + WS_NeedyTemplate4<Template_Inline<SWS_Movable> > b6; + + WS_NeedyTemplate4<Template_Unused<Movable> > c1; + WS_NeedyTemplate4<Template_Unused<S_Movable> > c2; + WS_NeedyTemplate4<Template_Unused<W_Movable> > c3; + WS_NeedyTemplate4<Template_Unused<WS_Movable> > c4; + WS_NeedyTemplate4<Template_Unused<SW_Movable> > c5; + WS_NeedyTemplate4<Template_Unused<SWS_Movable> > c6; + WS_NeedyTemplate4<Template_Unused<NonMovable> > c7; + WS_NeedyTemplate4<Template_Unused<S_NonMovable> > c8; + WS_NeedyTemplate4<Template_Unused<W_NonMovable> > c9; + WS_NeedyTemplate4<Template_Unused<WS_NonMovable> > c10; + WS_NeedyTemplate4<Template_Unused<SW_NonMovable> > c11; + WS_NeedyTemplate4<Template_Unused<SWS_NonMovable> > c12; + + WS_NeedyTemplate4<Template_Ref<Movable> > d1; + WS_NeedyTemplate4<Template_Ref<S_Movable> > d2; + WS_NeedyTemplate4<Template_Ref<W_Movable> > d3; + WS_NeedyTemplate4<Template_Ref<WS_Movable> > d4; + WS_NeedyTemplate4<Template_Ref<SW_Movable> > d5; + WS_NeedyTemplate4<Template_Ref<SWS_Movable> > d6; + WS_NeedyTemplate4<Template_Ref<NonMovable> > d7; + WS_NeedyTemplate4<Template_Ref<S_NonMovable> > d8; + WS_NeedyTemplate4<Template_Ref<W_NonMovable> > d9; + WS_NeedyTemplate4<Template_Ref<WS_NonMovable> > d10; + WS_NeedyTemplate4<Template_Ref<SW_NonMovable> > d11; + WS_NeedyTemplate4<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 5 - Subclassed Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate5 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate5<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T> +struct W_NeedyTemplate5 { + NeedyTemplate5<T> m; // expected-note-re 26 {{instantiation of 'NeedyTemplate5<{{.*}}>' requested here}} +}; +template <class T> +struct SW_NeedyTemplate5 : W_NeedyTemplate5<T> {}; +void bad5() { + SW_NeedyTemplate5<NonMovable> a1; + SW_NeedyTemplate5<S_NonMovable> a2; + SW_NeedyTemplate5<W_NonMovable> a3; + SW_NeedyTemplate5<WS_NonMovable> a4; + SW_NeedyTemplate5<SW_NonMovable> a5; + SW_NeedyTemplate5<SWS_NonMovable> a6; + + SW_NeedyTemplate5<Template_Inline<NonMovable> > b1; + SW_NeedyTemplate5<Template_Inline<S_NonMovable> > b2; + SW_NeedyTemplate5<Template_Inline<W_NonMovable> > b3; + SW_NeedyTemplate5<Template_Inline<WS_NonMovable> > b4; + SW_NeedyTemplate5<Template_Inline<SW_NonMovable> > b5; + SW_NeedyTemplate5<Template_Inline<SWS_NonMovable> > b6; + + SW_NeedyTemplate5<Template_NonMovable<NonMovable> > c1; + SW_NeedyTemplate5<Template_NonMovable<S_NonMovable> > c2; + SW_NeedyTemplate5<Template_NonMovable<W_NonMovable> > c3; + SW_NeedyTemplate5<Template_NonMovable<WS_NonMovable> > c4; + SW_NeedyTemplate5<Template_NonMovable<SW_NonMovable> > c5; + SW_NeedyTemplate5<Template_NonMovable<SWS_NonMovable> > c6; + SW_NeedyTemplate5<Template_NonMovable<Movable> > c7; + SW_NeedyTemplate5<Template_NonMovable<S_Movable> > c8; + SW_NeedyTemplate5<Template_NonMovable<W_Movable> > c9; + SW_NeedyTemplate5<Template_NonMovable<WS_Movable> > c10; + SW_NeedyTemplate5<Template_NonMovable<SW_Movable> > c11; + SW_NeedyTemplate5<Template_NonMovable<SWS_Movable> > c12; +} + +void good5() { + SW_NeedyTemplate5<Movable> a1; + SW_NeedyTemplate5<S_Movable> a2; + SW_NeedyTemplate5<W_Movable> a3; + SW_NeedyTemplate5<WS_Movable> a4; + SW_NeedyTemplate5<SW_Movable> a5; + SW_NeedyTemplate5<SWS_Movable> a6; + + SW_NeedyTemplate5<Template_Inline<Movable> > b1; + SW_NeedyTemplate5<Template_Inline<S_Movable> > b2; + SW_NeedyTemplate5<Template_Inline<W_Movable> > b3; + SW_NeedyTemplate5<Template_Inline<WS_Movable> > b4; + SW_NeedyTemplate5<Template_Inline<SW_Movable> > b5; + SW_NeedyTemplate5<Template_Inline<SWS_Movable> > b6; + + SW_NeedyTemplate5<Template_Unused<Movable> > c1; + SW_NeedyTemplate5<Template_Unused<S_Movable> > c2; + SW_NeedyTemplate5<Template_Unused<W_Movable> > c3; + SW_NeedyTemplate5<Template_Unused<WS_Movable> > c4; + SW_NeedyTemplate5<Template_Unused<SW_Movable> > c5; + SW_NeedyTemplate5<Template_Unused<SWS_Movable> > c6; + SW_NeedyTemplate5<Template_Unused<NonMovable> > c7; + SW_NeedyTemplate5<Template_Unused<S_NonMovable> > c8; + SW_NeedyTemplate5<Template_Unused<W_NonMovable> > c9; + SW_NeedyTemplate5<Template_Unused<WS_NonMovable> > c10; + SW_NeedyTemplate5<Template_Unused<SW_NonMovable> > c11; + SW_NeedyTemplate5<Template_Unused<SWS_NonMovable> > c12; + + SW_NeedyTemplate5<Template_Ref<Movable> > d1; + SW_NeedyTemplate5<Template_Ref<S_Movable> > d2; + SW_NeedyTemplate5<Template_Ref<W_Movable> > d3; + SW_NeedyTemplate5<Template_Ref<WS_Movable> > d4; + SW_NeedyTemplate5<Template_Ref<SW_Movable> > d5; + SW_NeedyTemplate5<Template_Ref<SWS_Movable> > d6; + SW_NeedyTemplate5<Template_Ref<NonMovable> > d7; + SW_NeedyTemplate5<Template_Ref<S_NonMovable> > d8; + SW_NeedyTemplate5<Template_Ref<W_NonMovable> > d9; + SW_NeedyTemplate5<Template_Ref<WS_NonMovable> > d10; + SW_NeedyTemplate5<Template_Ref<SW_NonMovable> > d11; + SW_NeedyTemplate5<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 6 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated with default template argument +// +// Note: This has an extra error, because it also includes a test with the default template argument. +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate6 {T m;}; // expected-error-re 27 {{Cannot instantiate 'NeedyTemplate6<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T> +struct W_NeedyTemplate6 { + NeedyTemplate6<T> m; // expected-note-re 27 {{instantiation of 'NeedyTemplate6<{{.*}}>' requested here}} +}; +template <class T> +struct SW_NeedyTemplate6 : W_NeedyTemplate6<T> {}; +// We create a different NonMovable type here, as NeedyTemplate6 will already be instantiated with NonMovable +struct MOZ_NON_MEMMOVABLE NonMovable2 {}; +template <class T = NonMovable2> +struct Defaulted_SW_NeedyTemplate6 { + SW_NeedyTemplate6<T> m; +}; +void bad6() { + Defaulted_SW_NeedyTemplate6<NonMovable> a1; + Defaulted_SW_NeedyTemplate6<S_NonMovable> a2; + Defaulted_SW_NeedyTemplate6<W_NonMovable> a3; + Defaulted_SW_NeedyTemplate6<WS_NonMovable> a4; + Defaulted_SW_NeedyTemplate6<SW_NonMovable> a5; + Defaulted_SW_NeedyTemplate6<SWS_NonMovable> a6; + + Defaulted_SW_NeedyTemplate6<Template_Inline<NonMovable> > b1; + Defaulted_SW_NeedyTemplate6<Template_Inline<S_NonMovable> > b2; + Defaulted_SW_NeedyTemplate6<Template_Inline<W_NonMovable> > b3; + Defaulted_SW_NeedyTemplate6<Template_Inline<WS_NonMovable> > b4; + Defaulted_SW_NeedyTemplate6<Template_Inline<SW_NonMovable> > b5; + Defaulted_SW_NeedyTemplate6<Template_Inline<SWS_NonMovable> > b6; + + Defaulted_SW_NeedyTemplate6<Template_NonMovable<NonMovable> > c1; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<S_NonMovable> > c2; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<W_NonMovable> > c3; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<WS_NonMovable> > c4; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<SW_NonMovable> > c5; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<SWS_NonMovable> > c6; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<Movable> > c7; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<S_Movable> > c8; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<W_Movable> > c9; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<WS_Movable> > c10; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<SW_Movable> > c11; + Defaulted_SW_NeedyTemplate6<Template_NonMovable<SWS_Movable> > c12; + + Defaulted_SW_NeedyTemplate6<> c13; +} + +void good6() { + Defaulted_SW_NeedyTemplate6<Movable> a1; + Defaulted_SW_NeedyTemplate6<S_Movable> a2; + Defaulted_SW_NeedyTemplate6<W_Movable> a3; + Defaulted_SW_NeedyTemplate6<WS_Movable> a4; + Defaulted_SW_NeedyTemplate6<SW_Movable> a5; + Defaulted_SW_NeedyTemplate6<SWS_Movable> a6; + + Defaulted_SW_NeedyTemplate6<Template_Inline<Movable> > b1; + Defaulted_SW_NeedyTemplate6<Template_Inline<S_Movable> > b2; + Defaulted_SW_NeedyTemplate6<Template_Inline<W_Movable> > b3; + Defaulted_SW_NeedyTemplate6<Template_Inline<WS_Movable> > b4; + Defaulted_SW_NeedyTemplate6<Template_Inline<SW_Movable> > b5; + Defaulted_SW_NeedyTemplate6<Template_Inline<SWS_Movable> > b6; + + Defaulted_SW_NeedyTemplate6<Template_Unused<Movable> > c1; + Defaulted_SW_NeedyTemplate6<Template_Unused<S_Movable> > c2; + Defaulted_SW_NeedyTemplate6<Template_Unused<W_Movable> > c3; + Defaulted_SW_NeedyTemplate6<Template_Unused<WS_Movable> > c4; + Defaulted_SW_NeedyTemplate6<Template_Unused<SW_Movable> > c5; + Defaulted_SW_NeedyTemplate6<Template_Unused<SWS_Movable> > c6; + Defaulted_SW_NeedyTemplate6<Template_Unused<NonMovable> > c7; + Defaulted_SW_NeedyTemplate6<Template_Unused<S_NonMovable> > c8; + Defaulted_SW_NeedyTemplate6<Template_Unused<W_NonMovable> > c9; + Defaulted_SW_NeedyTemplate6<Template_Unused<WS_NonMovable> > c10; + Defaulted_SW_NeedyTemplate6<Template_Unused<SW_NonMovable> > c11; + Defaulted_SW_NeedyTemplate6<Template_Unused<SWS_NonMovable> > c12; + + Defaulted_SW_NeedyTemplate6<Template_Ref<Movable> > d1; + Defaulted_SW_NeedyTemplate6<Template_Ref<S_Movable> > d2; + Defaulted_SW_NeedyTemplate6<Template_Ref<W_Movable> > d3; + Defaulted_SW_NeedyTemplate6<Template_Ref<WS_Movable> > d4; + Defaulted_SW_NeedyTemplate6<Template_Ref<SW_Movable> > d5; + Defaulted_SW_NeedyTemplate6<Template_Ref<SWS_Movable> > d6; + Defaulted_SW_NeedyTemplate6<Template_Ref<NonMovable> > d7; + Defaulted_SW_NeedyTemplate6<Template_Ref<S_NonMovable> > d8; + Defaulted_SW_NeedyTemplate6<Template_Ref<W_NonMovable> > d9; + Defaulted_SW_NeedyTemplate6<Template_Ref<WS_NonMovable> > d10; + Defaulted_SW_NeedyTemplate6<Template_Ref<SW_NonMovable> > d11; + Defaulted_SW_NeedyTemplate6<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 7 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate7 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate7<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T, class Q = NeedyTemplate7<T> > +struct Defaulted_Templated_NeedyTemplate7 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate7<{{.*}}>' requested here}} +void bad7() { + Defaulted_Templated_NeedyTemplate7<NonMovable> a1; + Defaulted_Templated_NeedyTemplate7<S_NonMovable> a2; + Defaulted_Templated_NeedyTemplate7<W_NonMovable> a3; + Defaulted_Templated_NeedyTemplate7<WS_NonMovable> a4; + Defaulted_Templated_NeedyTemplate7<SW_NonMovable> a5; + Defaulted_Templated_NeedyTemplate7<SWS_NonMovable> a6; + + Defaulted_Templated_NeedyTemplate7<Template_Inline<NonMovable> > b1; + Defaulted_Templated_NeedyTemplate7<Template_Inline<S_NonMovable> > b2; + Defaulted_Templated_NeedyTemplate7<Template_Inline<W_NonMovable> > b3; + Defaulted_Templated_NeedyTemplate7<Template_Inline<WS_NonMovable> > b4; + Defaulted_Templated_NeedyTemplate7<Template_Inline<SW_NonMovable> > b5; + Defaulted_Templated_NeedyTemplate7<Template_Inline<SWS_NonMovable> > b6; + + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<NonMovable> > c1; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<S_NonMovable> > c2; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<W_NonMovable> > c3; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<WS_NonMovable> > c4; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SW_NonMovable> > c5; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SWS_NonMovable> > c6; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<Movable> > c7; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<S_Movable> > c8; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<W_Movable> > c9; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<WS_Movable> > c10; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SW_Movable> > c11; + Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SWS_Movable> > c12; +} + +void good7() { + Defaulted_Templated_NeedyTemplate7<Movable> a1; + Defaulted_Templated_NeedyTemplate7<S_Movable> a2; + Defaulted_Templated_NeedyTemplate7<W_Movable> a3; + Defaulted_Templated_NeedyTemplate7<WS_Movable> a4; + Defaulted_Templated_NeedyTemplate7<SW_Movable> a5; + Defaulted_Templated_NeedyTemplate7<SWS_Movable> a6; + + Defaulted_Templated_NeedyTemplate7<Template_Inline<Movable> > b1; + Defaulted_Templated_NeedyTemplate7<Template_Inline<S_Movable> > b2; + Defaulted_Templated_NeedyTemplate7<Template_Inline<W_Movable> > b3; + Defaulted_Templated_NeedyTemplate7<Template_Inline<WS_Movable> > b4; + Defaulted_Templated_NeedyTemplate7<Template_Inline<SW_Movable> > b5; + Defaulted_Templated_NeedyTemplate7<Template_Inline<SWS_Movable> > b6; + + Defaulted_Templated_NeedyTemplate7<Template_Unused<Movable> > c1; + Defaulted_Templated_NeedyTemplate7<Template_Unused<S_Movable> > c2; + Defaulted_Templated_NeedyTemplate7<Template_Unused<W_Movable> > c3; + Defaulted_Templated_NeedyTemplate7<Template_Unused<WS_Movable> > c4; + Defaulted_Templated_NeedyTemplate7<Template_Unused<SW_Movable> > c5; + Defaulted_Templated_NeedyTemplate7<Template_Unused<SWS_Movable> > c6; + Defaulted_Templated_NeedyTemplate7<Template_Unused<NonMovable> > c7; + Defaulted_Templated_NeedyTemplate7<Template_Unused<S_NonMovable> > c8; + Defaulted_Templated_NeedyTemplate7<Template_Unused<W_NonMovable> > c9; + Defaulted_Templated_NeedyTemplate7<Template_Unused<WS_NonMovable> > c10; + Defaulted_Templated_NeedyTemplate7<Template_Unused<SW_NonMovable> > c11; + Defaulted_Templated_NeedyTemplate7<Template_Unused<SWS_NonMovable> > c12; + + Defaulted_Templated_NeedyTemplate7<Template_Ref<Movable> > d1; + Defaulted_Templated_NeedyTemplate7<Template_Ref<S_Movable> > d2; + Defaulted_Templated_NeedyTemplate7<Template_Ref<W_Movable> > d3; + Defaulted_Templated_NeedyTemplate7<Template_Ref<WS_Movable> > d4; + Defaulted_Templated_NeedyTemplate7<Template_Ref<SW_Movable> > d5; + Defaulted_Templated_NeedyTemplate7<Template_Ref<SWS_Movable> > d6; + Defaulted_Templated_NeedyTemplate7<Template_Ref<NonMovable> > d7; + Defaulted_Templated_NeedyTemplate7<Template_Ref<S_NonMovable> > d8; + Defaulted_Templated_NeedyTemplate7<Template_Ref<W_NonMovable> > d9; + Defaulted_Templated_NeedyTemplate7<Template_Ref<WS_NonMovable> > d10; + Defaulted_Templated_NeedyTemplate7<Template_Ref<SW_NonMovable> > d11; + Defaulted_Templated_NeedyTemplate7<Template_Ref<SWS_NonMovable> > d12; +} + +// +// 8 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument +// + +template <class T> +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate8 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate8<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template <class T, class Q = NeedyTemplate8<T> > +struct Defaulted_Templated_NeedyTemplate8 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate8<{{.*}}>' requested here}} +template <class T> +struct W_Defaulted_Templated_NeedyTemplate8 { + Defaulted_Templated_NeedyTemplate8<T> m; +}; +void bad8() { + W_Defaulted_Templated_NeedyTemplate8<NonMovable> a1; + W_Defaulted_Templated_NeedyTemplate8<S_NonMovable> a2; + W_Defaulted_Templated_NeedyTemplate8<W_NonMovable> a3; + W_Defaulted_Templated_NeedyTemplate8<WS_NonMovable> a4; + W_Defaulted_Templated_NeedyTemplate8<SW_NonMovable> a5; + W_Defaulted_Templated_NeedyTemplate8<SWS_NonMovable> a6; + + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<NonMovable> > b1; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<S_NonMovable> > b2; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<W_NonMovable> > b3; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<WS_NonMovable> > b4; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SW_NonMovable> > b5; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SWS_NonMovable> > b6; + + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<NonMovable> > c1; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<S_NonMovable> > c2; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<W_NonMovable> > c3; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<WS_NonMovable> > c4; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SW_NonMovable> > c5; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SWS_NonMovable> > c6; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<Movable> > c7; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<S_Movable> > c8; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<W_Movable> > c9; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<WS_Movable> > c10; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SW_Movable> > c11; + W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SWS_Movable> > c12; +} + +void good8() { + W_Defaulted_Templated_NeedyTemplate8<Movable> a1; + W_Defaulted_Templated_NeedyTemplate8<S_Movable> a2; + W_Defaulted_Templated_NeedyTemplate8<W_Movable> a3; + W_Defaulted_Templated_NeedyTemplate8<WS_Movable> a4; + W_Defaulted_Templated_NeedyTemplate8<SW_Movable> a5; + W_Defaulted_Templated_NeedyTemplate8<SWS_Movable> a6; + + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<Movable> > b1; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<S_Movable> > b2; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<W_Movable> > b3; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<WS_Movable> > b4; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SW_Movable> > b5; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SWS_Movable> > b6; + + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<Movable> > c1; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<S_Movable> > c2; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<W_Movable> > c3; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<WS_Movable> > c4; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SW_Movable> > c5; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SWS_Movable> > c6; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<NonMovable> > c7; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<S_NonMovable> > c8; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<W_NonMovable> > c9; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<WS_NonMovable> > c10; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SW_NonMovable> > c11; + W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SWS_NonMovable> > c12; + + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<Movable> > d1; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<S_Movable> > d2; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<W_Movable> > d3; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<WS_Movable> > d4; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SW_Movable> > d5; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SWS_Movable> > d6; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<NonMovable> > d7; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<S_NonMovable> > d8; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<W_NonMovable> > d9; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<WS_NonMovable> > d10; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SW_NonMovable> > d11; + W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SWS_NonMovable> > d12; +} + +/* + SpecializedNonMovable is a non-movable class which has an explicit specialization of NeedyTemplate + for it. Instantiations of NeedyTemplateN<SpecializedNonMovable> should be legal as the explicit + specialization isn't annotated with MOZ_NEEDS_MEMMOVABLE_TYPE. + + However, as it is MOZ_NON_MEMMOVABLE, derived classes and members shouldn't be able to be used to + instantiate NeedyTemplate. +*/ + +struct MOZ_NON_MEMMOVABLE SpecializedNonMovable {}; +struct S_SpecializedNonMovable : SpecializedNonMovable {}; // expected-note 8 {{'S_SpecializedNonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'SpecializedNonMovable'}} + +// Specialize all of the NeedyTemplates with SpecializedNonMovable. +template <> +struct NeedyTemplate1<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate2<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate3<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate4<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate5<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate6<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate7<SpecializedNonMovable> {}; +template <> +struct NeedyTemplate8<SpecializedNonMovable> {}; + +void specialization() { + /* + SpecializedNonMovable has a specialization for every variant of NeedyTemplate, + so these templates are valid, even though SpecializedNonMovable isn't + memmovable + */ + NeedyTemplate1<SpecializedNonMovable> a1; + S_NeedyTemplate2<SpecializedNonMovable> a2; + W_NeedyTemplate3<SpecializedNonMovable> a3; + WS_NeedyTemplate4<SpecializedNonMovable> a4; + SW_NeedyTemplate5<SpecializedNonMovable> a5; + Defaulted_SW_NeedyTemplate6<SpecializedNonMovable> a6; + Defaulted_Templated_NeedyTemplate7<SpecializedNonMovable> a7; + W_Defaulted_Templated_NeedyTemplate8<SpecializedNonMovable> a8; + + /* + These entries contain an element which is SpecializedNonMovable, and are non-movable + as there is no valid specialization, and their member is non-memmovable + */ + NeedyTemplate1<Template_Inline<SpecializedNonMovable> > b1; // expected-note-re {{instantiation of 'NeedyTemplate1<Template_Inline<SpecializedNonMovable>{{ ?}}>' requested here}} + S_NeedyTemplate2<Template_Inline<SpecializedNonMovable> > b2; + W_NeedyTemplate3<Template_Inline<SpecializedNonMovable> > b3; + WS_NeedyTemplate4<Template_Inline<SpecializedNonMovable> > b4; + SW_NeedyTemplate5<Template_Inline<SpecializedNonMovable> > b5; + Defaulted_SW_NeedyTemplate6<Template_Inline<SpecializedNonMovable> > b6; + Defaulted_Templated_NeedyTemplate7<Template_Inline<SpecializedNonMovable> > b7; + W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SpecializedNonMovable> > b8; + + /* + The subclass of SpecializedNonMovable, is also non-memmovable, + as there is no valid specialization. + */ + NeedyTemplate1<S_SpecializedNonMovable> c1; // expected-note {{instantiation of 'NeedyTemplate1<S_SpecializedNonMovable>' requested here}} + S_NeedyTemplate2<S_SpecializedNonMovable> c2; + W_NeedyTemplate3<S_SpecializedNonMovable> c3; + WS_NeedyTemplate4<S_SpecializedNonMovable> c4; + SW_NeedyTemplate5<S_SpecializedNonMovable> c5; + Defaulted_SW_NeedyTemplate6<S_SpecializedNonMovable> c6; + Defaulted_Templated_NeedyTemplate7<S_SpecializedNonMovable> c7; + W_Defaulted_Templated_NeedyTemplate8<S_SpecializedNonMovable> c8; +} + +class MOZ_NEEDS_MEMMOVABLE_MEMBERS NeedsMemMovableMembers { + Movable m1; + NonMovable m2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'm2' of type 'NonMovable'}} + S_Movable sm1; + S_NonMovable sm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'sm2' of type 'S_NonMovable'}} + W_Movable wm1; + W_NonMovable wm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'wm2' of type 'W_NonMovable'}} + SW_Movable swm1; + SW_NonMovable swm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'swm2' of type 'SW_NonMovable'}} + WS_Movable wsm1; + WS_NonMovable wsm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'wsm2' of type 'WS_NonMovable'}} + SWS_Movable swsm1; + SWS_NonMovable swsm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'swsm2' of type 'SWS_NonMovable'}} +}; + +class NeedsMemMovableMembersDerived : public NeedsMemMovableMembers {}; diff --git a/build/clang-plugin/tests/TestNonMemMovableStd.cpp b/build/clang-plugin/tests/TestNonMemMovableStd.cpp new file mode 100644 index 0000000000..b380d07186 --- /dev/null +++ b/build/clang-plugin/tests/TestNonMemMovableStd.cpp @@ -0,0 +1,70 @@ +#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type"))) + +template<class T> +class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { T mForceInst; }; // expected-error-re 9 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}} + +namespace std { +// In theory defining things in std:: like this invokes undefined +// behavior, but in practice it's good enough for this test case. +template<class C> class basic_string { // expected-note 2 {{'std::basic_string<char>' is a non-memmove()able type because it is an stl-provided type not guaranteed to be memmove-able}} expected-note {{'std::string' (aka 'basic_string<char>') is a non-memmove()able type because it is an stl-provided type not guaranteed to be memmove-able}} + public: + basic_string(); + basic_string(const basic_string&); + basic_string(basic_string&&); + basic_string& operator=(const basic_string&); + basic_string& operator=(basic_string&&); + ~basic_string(); +}; +typedef basic_string<char> string; +template<class T, class U> class pair { T mT; U mU; }; // expected-note-re 4 {{'std::pair<bool, {{.*}}>' is a non-memmove()able type because it has a template argument non-memmove()able type '{{.*}}'}} + +struct has_nontrivial_dtor { // expected-note 2 {{'std::has_nontrivial_dtor' is a non-memmove()able type because it is an stl-provided type not guaranteed to be memmove-able}} + has_nontrivial_dtor() = default; + ~has_nontrivial_dtor(); +}; +struct has_nontrivial_copy { // expected-note 2 {{'std::has_nontrivial_copy' is a non-memmove()able type because it is an stl-provided type not guaranteed to be memmove-able}} + has_nontrivial_copy() = default; + has_nontrivial_copy(const has_nontrivial_copy&); + has_nontrivial_copy& operator=(const has_nontrivial_copy&); +}; +struct has_nontrivial_move { // expected-note 2 {{'std::has_nontrivial_move' is a non-memmove()able type because it is an stl-provided type not guaranteed to be memmove-able}} + has_nontrivial_move() = default; + has_nontrivial_move(const has_nontrivial_move&); + has_nontrivial_move& operator=(const has_nontrivial_move&); +}; +struct has_trivial_dtor { + has_trivial_dtor() = default; + ~has_trivial_dtor() = default; +}; +struct has_trivial_copy { + has_trivial_copy() = default; + has_trivial_copy(const has_trivial_copy&) = default; + has_trivial_copy& operator=(const has_trivial_copy&) = default; +}; +struct has_trivial_move { + has_trivial_move() = default; + has_trivial_move(const has_trivial_move&) = default; + has_trivial_move& operator=(const has_trivial_move&) = default; +}; +} + +class HasString { std::string m; }; // expected-note {{'HasString' is a non-memmove()able type because member 'm' is a non-memmove()able type 'std::string' (aka 'basic_string<char>')}} + +static Mover<std::string> bad; // expected-note-re {{instantiation of 'Mover<std::basic_string<char>{{ ?}}>' requested here}} +static Mover<HasString> bad_mem; // expected-note {{instantiation of 'Mover<HasString>' requested here}} +static Mover<std::pair<bool, int>> good; +static Mover<std::pair<bool, std::string>> not_good; // expected-note-re {{instantiation of 'Mover<std::pair<bool, std::basic_string<char>{{ ?}}>{{ ?}}>' requested here}} + +static Mover<std::has_nontrivial_dtor> nontrivial_dtor; // expected-note {{instantiation of 'Mover<std::has_nontrivial_dtor>' requested here}} +static Mover<std::has_nontrivial_copy> nontrivial_copy; // expected-note {{instantiation of 'Mover<std::has_nontrivial_copy>' requested here}} +static Mover<std::has_nontrivial_move> nontrivial_move; // expected-note {{instantiation of 'Mover<std::has_nontrivial_move>' requested here}} +static Mover<std::has_trivial_dtor> trivial_dtor; +static Mover<std::has_trivial_copy> trivial_copy; +static Mover<std::has_trivial_move> trivial_move; + +static Mover<std::pair<bool, std::has_nontrivial_dtor>> pair_nontrivial_dtor; // expected-note {{instantiation of 'Mover<std::pair<bool, std::has_nontrivial_dtor>>' requested here}} +static Mover<std::pair<bool, std::has_nontrivial_copy>> pair_nontrivial_copy; // expected-note {{instantiation of 'Mover<std::pair<bool, std::has_nontrivial_copy>>' requested here}} +static Mover<std::pair<bool, std::has_nontrivial_move>> pair_nontrivial_move; // expected-note {{instantiation of 'Mover<std::pair<bool, std::has_nontrivial_move>>' requested here}} +static Mover<std::pair<bool, std::has_trivial_dtor>> pair_trivial_dtor; +static Mover<std::pair<bool, std::has_trivial_copy>> pair_trivial_copy; +static Mover<std::pair<bool, std::has_trivial_move>> pair_trivial_move; diff --git a/build/clang-plugin/tests/TestNonMemMovableStdAtomic.cpp b/build/clang-plugin/tests/TestNonMemMovableStdAtomic.cpp new file mode 100644 index 0000000000..b8aef2eacd --- /dev/null +++ b/build/clang-plugin/tests/TestNonMemMovableStdAtomic.cpp @@ -0,0 +1,30 @@ +// expected-no-diagnostics + +#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type"))) + +template<class T> +class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { T mForceInst; }; + +#include <atomic> +#include <cstdint> +struct CustomType{}; +static struct { + Mover<std::atomic<CustomType>> m1; + Mover<std::atomic<bool>> m2; + Mover<std::atomic<char>> m3; + Mover<std::atomic<signed char>> m4; + Mover<std::atomic<unsigned char>> m5; + Mover<std::atomic<char16_t>> m6; + Mover<std::atomic<char32_t>> m7; + Mover<std::atomic<wchar_t>> m8; + Mover<std::atomic<short>> m9; + Mover<std::atomic<unsigned short>> m10; + Mover<std::atomic<int>> m11; + Mover<std::atomic<unsigned int>> m12; + Mover<std::atomic<long>> m13; + Mover<std::atomic<unsigned long>> m14; + Mover<std::atomic<long long>> m15; + Mover<std::atomic<unsigned long long>> m16; + Mover<std::atomic<void*>> m17; + Mover<std::atomic<CustomType*>> m18; +} good; diff --git a/build/clang-plugin/tests/TestNonParameterChecker.cpp b/build/clang-plugin/tests/TestNonParameterChecker.cpp new file mode 100644 index 0000000000..291ef949f6 --- /dev/null +++ b/build/clang-plugin/tests/TestNonParameterChecker.cpp @@ -0,0 +1,187 @@ +#define MOZ_NON_PARAM __attribute__((annotate("moz_non_param"))) + +struct Param {}; +struct MOZ_NON_PARAM NonParam {}; +union MOZ_NON_PARAM NonParamUnion {}; +class MOZ_NON_PARAM NonParamClass {}; +enum MOZ_NON_PARAM NonParamEnum { X, Y, Z }; +enum class MOZ_NON_PARAM NonParamEnumClass { X, Y, Z }; + +struct HasNonParamStruct { NonParam x; int y; }; // expected-note 14 {{'HasNonParamStruct' is a non-param type because member 'x' is a non-param type 'NonParam'}} +union HasNonParamUnion { NonParam x; int y; }; // expected-note 18 {{'HasNonParamUnion' is a non-param type because member 'x' is a non-param type 'NonParam'}} +struct HasNonParamStructUnion { HasNonParamUnion z; }; // expected-note 9 {{'HasNonParamStructUnion' is a non-param type because member 'z' is a non-param type 'HasNonParamUnion'}} + +#define MAYBE_STATIC +#include "NonParameterTestCases.h" +#undef MAYBE_STATIC + +// Do not check typedef and using. +typedef void (*funcTypeParam)(Param x); +typedef void (*funcTypeNonParam)(NonParam x); + +using usingFuncTypeParam = void (*)(Param x); +using usingFuncTypeNonParam = void (*)(NonParam x); + +class class_ +{ + explicit class_(Param x) {} + explicit class_(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + explicit class_(HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + explicit class_(HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + explicit class_(HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + +#define MAYBE_STATIC +#include "NonParameterTestCases.h" +#undef MAYBE_STATIC +}; + +class classWithStatic +{ +#define MAYBE_STATIC static +#include "NonParameterTestCases.h" +#undef MAYBE_STATIC +}; + +template <typename T> +class tmplClassForParam +{ +public: + void raw(T x) {} + void rawDefault(T x = T()) {} + void const_(const T x) {} + void ptr(T* x) {} + void ref(T& x) {} + void constRef(const T& x) {} + + void notCalled(T x) {} +}; + +template <typename T> +class tmplClassForNonParam +{ +public: + void raw(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + void rawDefault(T x = T()) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + void const_(const T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + void ptr(T* x) {} + void ref(T& x) {} + void constRef(const T& x) {} + + void notCalled(T x) {} +}; + +template <typename T> +class tmplClassForHasNonParamStruct +{ +public: + void raw(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + void rawDefault(T x = T()) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + void const_(const T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + void ptr(T* x) {} + void ref(T& x) {} + void constRef(const T& x) {} + + void notCalled(T x) {} +}; + +void testTemplateClass() +{ + tmplClassForParam<Param> paramClass; + Param param; + paramClass.raw(param); + paramClass.rawDefault(); + paramClass.const_(param); + paramClass.ptr(¶m); + paramClass.ref(param); + paramClass.constRef(param); + + tmplClassForNonParam<NonParam> nonParamClass; //expected-note 3 {{The bad argument was passed to 'tmplClassForNonParam' here}} + NonParam nonParam; + nonParamClass.raw(nonParam); + nonParamClass.rawDefault(); + nonParamClass.const_(nonParam); + nonParamClass.ptr(&nonParam); + nonParamClass.ref(nonParam); + nonParamClass.constRef(nonParam); + + tmplClassForHasNonParamStruct<HasNonParamStruct> hasNonParamStructClass;//expected-note 3 {{The bad argument was passed to 'tmplClassForHasNonParamStruct' here}} + HasNonParamStruct hasNonParamStruct; + hasNonParamStructClass.raw(hasNonParamStruct); + hasNonParamStructClass.rawDefault(); + hasNonParamStructClass.const_(hasNonParamStruct); + hasNonParamStructClass.ptr(&hasNonParamStruct); + hasNonParamStructClass.ref(hasNonParamStruct); + hasNonParamStructClass.constRef(hasNonParamStruct); +} + +template <typename T> +class NestedTemplateInner +{ +public: + void raw(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +}; + +template <typename T> +class nestedTemplateOuter +{ +public: + void constRef(const T& x) { + NestedTemplateInner<T> inner; //expected-note {{The bad argument was passed to 'NestedTemplateInner' here}} + inner.raw(x); + } +}; + +void testNestedTemplateClass() +{ + nestedTemplateOuter<NonParam> outer; + NonParam nonParam; + outer.constRef(nonParam); // FIXME: this line needs note "The bad argument was passed to 'constRef' here" +} + +template <typename T> +void tmplFuncForParam(T x) {} +template <typename T> +void tmplFuncForNonParam(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +template <typename T> +void tmplFuncForNonParamImplicit(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +template <typename T> +void tmplFuncForHasNonParamStruct(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +template <typename T> +void tmplFuncForHasNonParamStructImplicit(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + +void testTemplateFunc() +{ + Param param; + tmplFuncForParam<Param>(param); + + NonParam nonParam; + tmplFuncForNonParam<NonParam>(nonParam); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForNonParam' here" + tmplFuncForNonParamImplicit(nonParam); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForNonParamImplicit' here" + + HasNonParamStruct hasNonParamStruct; + tmplFuncForHasNonParamStruct<HasNonParamStruct>(hasNonParamStruct); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForHasNonParamStruct' here" + tmplFuncForHasNonParamStructImplicit(hasNonParamStruct); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForHasNonParamStructImplicit' here" +} + +void testLambda() +{ + auto paramLambda = [](Param x) -> void {}; + auto nonParamLambda = [](NonParam x) -> void {}; //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + auto nonParamStructLambda = [](HasNonParamStruct x) -> void {}; //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + auto nonParamUnionLambda = [](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + auto nonParamStructUnionLambda = [](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + + (void)[](Param x) -> void {}; + (void)[](NonParam x) -> void {}; //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + (void)[](HasNonParamStruct x) -> void {}; //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + (void)[](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} + (void)[](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +} + +struct alignas(16) AlignasStruct { char a; ~AlignasStruct(); }; // expected-note {{'AlignasStruct' is a non-param type because it has an explicit alignment of '16'}} +void takesAlignasStruct(AlignasStruct x) { } // expected-error {{Type 'AlignasStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +void takesAlignasStructByRef(const AlignasStruct& x) { } + +struct AlignasMember { alignas(16) char a; ~AlignasMember(); }; // expected-note {{'AlignasMember' is a non-param type because member 'a' has an explicit alignment of '16'}} +void takesAlignasMember(AlignasMember x) { } // expected-error {{Type 'AlignasMember' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +void takesAlignasMemberByRef(const AlignasMember& x) { } diff --git a/build/clang-plugin/tests/TestNonTemporaryClass.cpp b/build/clang-plugin/tests/TestNonTemporaryClass.cpp new file mode 100644 index 0000000000..682c8ad530 --- /dev/null +++ b/build/clang-plugin/tests/TestNonTemporaryClass.cpp @@ -0,0 +1,70 @@ +#define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class"))) +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +#include <stddef.h> + +struct MOZ_NON_TEMPORARY_CLASS NonTemporary { + int i; + NonTemporary() {} + MOZ_IMPLICIT NonTemporary(int a) {} + NonTemporary(int a, int b) {} + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_NON_TEMPORARY_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void gobbleref(const NonTemporary&) { } + +template <class T> +void gobbleanyref(const T&) { } + +void misuseNonTemporaryClass(int len) { + NonTemporary invalid; + NonTemporary alsoInvalid[2]; + static NonTemporary invalidStatic; + static NonTemporary alsoInvalidStatic[2]; + + gobble(&invalid); + gobble(&invalidStatic); + gobble(&alsoInvalid[0]); + + gobbleref(NonTemporary()); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} + gobbleref(NonTemporary(10, 20)); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} + gobbleref(NonTemporary(10)); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} + gobbleref(10); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} + gobbleanyref(TemplateClass<int>()); // expected-error {{variable of type 'TemplateClass<int>' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} + + gobble(new NonTemporary); + gobble(new NonTemporary[10]); + gobble(new TemplateClass<int>); + gobble(len <= 5 ? &invalid : new NonTemporary); + + char buffer[sizeof(NonTemporary)]; + gobble(new (buffer) NonTemporary); +} + +void defaultArg(const NonTemporary& arg = NonTemporary()) { +} + +NonTemporary invalidStatic; +struct RandomClass { + NonTemporary nonstaticMember; // expected-note {{'RandomClass' is a non-temporary type because member 'nonstaticMember' is a non-temporary type 'NonTemporary'}} + static NonTemporary staticMember; +}; +struct MOZ_NON_TEMPORARY_CLASS RandomNonTemporaryClass { + NonTemporary nonstaticMember; + static NonTemporary staticMember; +}; + +struct BadInherit : NonTemporary {}; // expected-note {{'BadInherit' is a non-temporary type because it inherits from a non-temporary type 'NonTemporary'}} + +void useStuffWrongly() { + gobbleanyref(BadInherit()); // expected-error {{variable of type 'BadInherit' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} + gobbleanyref(RandomClass()); // expected-error {{variable of type 'RandomClass' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}} +} diff --git a/build/clang-plugin/tests/TestNonTrivialTypeInFfi.cpp b/build/clang-plugin/tests/TestNonTrivialTypeInFfi.cpp new file mode 100644 index 0000000000..e491122b99 --- /dev/null +++ b/build/clang-plugin/tests/TestNonTrivialTypeInFfi.cpp @@ -0,0 +1,65 @@ +// clang warns for some of these on its own, but we're not testing that, plus +// some of them (TrivialT<int>) is a false positive (clang doesn't realize the +// type is fully specialized below). +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" + +struct Opaque; +struct Trivial { + int foo; + char bar; + Opaque* baz; +}; + +template <typename T> +struct TrivialT { + int foo; + char bar; + T* baz; +}; + +struct NonTrivial { + ~NonTrivial() { + } + + Opaque* ptr; +}; + +template <typename T> +struct NonTrivialT { + ~NonTrivialT() { + delete ptr; + } + + T* ptr; +}; + +struct TransitivelyNonTrivial { + NonTrivial nontrivial; +}; + +extern "C" void Foo(); +extern "C" Trivial Foo1(); +extern "C" NonTrivial Foo2(); // expected-error {{Type 'NonTrivial' must not be used as return type of extern "C" function}} expected-note {{Please consider using a pointer or reference instead}} +extern "C" NonTrivialT<int> Foo3(); // expected-error {{Type 'NonTrivialT<int>' must not be used as return type of extern "C" function}} expected-note {{Please consider using a pointer or reference, or explicitly instantiating the template instead}} +extern "C" NonTrivialT<float> Foo4(); // expected-error {{Type 'NonTrivialT<float>' must not be used as return type of extern "C" function}} expected-note {{Please consider using a pointer or reference, or explicitly instantiating the template instead}} + +extern "C" NonTrivial* Foo5(); + +extern "C" TrivialT<int> Foo6(); +extern "C" TrivialT<float> Foo7(); // expected-error {{Type 'TrivialT<float>' must not be used as return type of extern "C" function}} expected-note {{Please consider using a pointer or reference, or explicitly instantiating the template instead}} +extern "C" Trivial* Foo8(); + +extern "C" void Foo9(Trivial); +extern "C" void Foo10(NonTrivial); // expected-error {{Type 'NonTrivial' must not be used as parameter to extern "C" function}} expected-note {{Please consider using a pointer or reference instead}} +extern "C" void Foo11(NonTrivial*); +extern "C" void Foo12(NonTrivialT<int>); // expected-error {{Type 'NonTrivialT<int>' must not be used as parameter to extern "C" function}} expected-note {{Please consider using a pointer or reference, or explicitly instantiating the template instead}} +extern "C" void Foo13(TrivialT<int>); +extern "C" void Foo14(TrivialT<float>); // expected-error {{Type 'TrivialT<float>' must not be used as parameter to extern "C" function}} expected-note {{Please consider using a pointer or reference, or explicitly instantiating the template instead}} + +extern "C" TransitivelyNonTrivial Foo15(); // expected-error {{Type 'TransitivelyNonTrivial' must not be used as return type of extern "C" function}} expected-note {{Please consider using a pointer or reference instead}} +extern "C" void Foo16(TransitivelyNonTrivial); // expected-error {{Type 'TransitivelyNonTrivial' must not be used as parameter to extern "C" function}} expected-note {{Please consider using a pointer or reference instead}} + +template struct TrivialT<int>; + +#pragma GCC diagnostic pop diff --git a/build/clang-plugin/tests/TestOverrideBaseCall.cpp b/build/clang-plugin/tests/TestOverrideBaseCall.cpp new file mode 100644 index 0000000000..6fdaaad04e --- /dev/null +++ b/build/clang-plugin/tests/TestOverrideBaseCall.cpp @@ -0,0 +1,175 @@ +#define MOZ_REQUIRED_BASE_METHOD __attribute__((annotate("moz_required_base_method"))) + +class Base { +public: + virtual void fo() MOZ_REQUIRED_BASE_METHOD { + } + + virtual int foRet() MOZ_REQUIRED_BASE_METHOD { + return 0; + } +}; + +class BaseOne : public Base { +public: + virtual void fo() MOZ_REQUIRED_BASE_METHOD { + Base::fo(); + } +}; + +class BaseSecond : public Base { +public: + virtual void fo() MOZ_REQUIRED_BASE_METHOD { + Base::fo(); + } +}; + +class Deriv : public BaseOne, public BaseSecond { +public: + void func() { + } + + void fo() { + func(); + BaseSecond::fo(); + BaseOne::fo(); + } +}; + +class DerivSimple : public Base { +public: + void fo() { // expected-error {{Method Base::fo must be called in all overrides, but is not called in this override defined for class DerivSimple}} + } +}; + +class BaseVirtualOne : public virtual Base { +}; + +class BaseVirtualSecond: public virtual Base { +}; + +class DerivVirtual : public BaseVirtualOne, public BaseVirtualSecond { +public: + void fo() { + Base::fo(); + } +}; + +class DerivIf : public Base { +public: + void fo() { + if (true) { + Base::fo(); + } + } +}; + +class DerivIfElse : public Base { +public: + void fo() { + if (true) { + Base::fo(); + } else { + Base::fo(); + } + } +}; + +class DerivFor : public Base { +public: + void fo() { + for (int i = 0; i < 10; i++) { + Base::fo(); + } + } +}; + +class DerivDoWhile : public Base { +public: + void fo() { + do { + Base::fo(); + } while(false); + } +}; + +class DerivWhile : public Base { +public: + void fo() { + while (true) { + Base::fo(); + break; + } + } +}; + +class DerivAssignment : public Base { +public: + int foRet() { + return foRet(); + } +}; + +class BaseOperator { +private: + int value; +public: + BaseOperator() : value(0) { + } + virtual BaseOperator& operator++() MOZ_REQUIRED_BASE_METHOD { + value++; + return *this; + } +}; + +class DerivOperatorErr : public BaseOperator { +private: + int value; +public: + DerivOperatorErr() : value(0) { + } + DerivOperatorErr& operator++() { // expected-error {{Method BaseOperator::operator++ must be called in all overrides, but is not called in this override defined for class DerivOperatorErr}} + value++; + return *this; + } +}; + +class DerivOperator : public BaseOperator { +private: + int value; +public: + DerivOperator() : value(0) { + } + DerivOperator& operator++() { + BaseOperator::operator++(); + value++; + return *this; + } +}; + +class DerivPrime : public Base { +public: + void fo() { + Base::fo(); + } +}; + +class DerivSecondErr : public DerivPrime { +public: + void fo() { // expected-error {{Method Base::fo must be called in all overrides, but is not called in this override defined for class DerivSecondErr}} + } +}; + +class DerivSecond : public DerivPrime { +public: + void fo() { + Base::fo(); + } +}; + +class DerivSecondIndirect : public DerivPrime { +public: + void fo() { + DerivPrime::fo(); + } +}; diff --git a/build/clang-plugin/tests/TestOverrideBaseCallAnnotation.cpp b/build/clang-plugin/tests/TestOverrideBaseCallAnnotation.cpp new file mode 100644 index 0000000000..e268122c69 --- /dev/null +++ b/build/clang-plugin/tests/TestOverrideBaseCallAnnotation.cpp @@ -0,0 +1,47 @@ +#define MOZ_REQUIRED_BASE_METHOD __attribute__((annotate("moz_required_base_method"))) + +class Base { +public: + virtual void fo() MOZ_REQUIRED_BASE_METHOD { + } +}; + +class BaseNonVirtual { +public: + void fo() MOZ_REQUIRED_BASE_METHOD { // expected-error {{MOZ_REQUIRED_BASE_METHOD can be used only on virtual methods}} + } +}; + +class Deriv : public BaseNonVirtual { +public: + virtual void fo() MOZ_REQUIRED_BASE_METHOD { + } +}; + +class DerivVirtual : public Base { +public: + void fo() MOZ_REQUIRED_BASE_METHOD { + Base::fo(); + } +}; + +class BaseOperator { +public: + BaseOperator& operator++() MOZ_REQUIRED_BASE_METHOD { // expected-error {{MOZ_REQUIRED_BASE_METHOD can be used only on virtual methods}} + return *this; + } +}; + +class DerivOperator : public BaseOperator { +public: + virtual DerivOperator& operator++() { + return *this; + } +}; + +class DerivPrimeOperator : public DerivOperator { +public: + DerivPrimeOperator& operator++() { + return *this; + } +}; diff --git a/build/clang-plugin/tests/TestParamTraitsEnum.cpp b/build/clang-plugin/tests/TestParamTraitsEnum.cpp new file mode 100644 index 0000000000..a250250bfe --- /dev/null +++ b/build/clang-plugin/tests/TestParamTraitsEnum.cpp @@ -0,0 +1,94 @@ +typedef enum { + BadFirst, + BadSecond, + BadThird +} BadEnum; + +typedef enum { + NestedFirst, + NestedSecond +} NestedBadEnum; + +typedef enum { + GoodFirst, + GoodSecond, + GoodLast +} GoodEnum; + +enum RawEnum { + RawFirst, + RawLast +}; + +enum class ClassEnum { + ClassFirst, + ClassLast +}; + +template <class P> struct ParamTraits; + +// Simplified EnumSerializer etc. from IPCMessageUtils.h +template <typename E, typename EnumValidator> +struct EnumSerializer { + typedef E paramType; +}; + +template <typename E, + E MinLegal, + E HighBound> +class ContiguousEnumValidator +{}; + +template <typename E, + E MinLegal, + E HighBound> +struct ContiguousEnumSerializer + : EnumSerializer<E, + ContiguousEnumValidator<E, MinLegal, HighBound>> +{}; + +// Typical ParamTraits implementation that should be avoided +template<> +struct ParamTraits<ClassEnum> // expected-error {{Custom ParamTraits implementation for an enum type}} expected-note {{Please use a helper class for example ContiguousEnumSerializer}} +{ + typedef ClassEnum paramType; +}; + +template<> +struct ParamTraits<enum RawEnum> // expected-error {{Custom ParamTraits implementation for an enum type}} expected-note {{Please use a helper class for example ContiguousEnumSerializer}} +{ + typedef enum RawEnum paramType; +}; + +template<> +struct ParamTraits<BadEnum> // expected-error {{Custom ParamTraits implementation for an enum type}} expected-note {{Please use a helper class for example ContiguousEnumSerializer}} +{ + typedef BadEnum paramType; +}; + +// Make sure the analysis catches nested typedefs +typedef NestedBadEnum NestedDefLevel1; +typedef NestedDefLevel1 NestedDefLevel2; + +template<> +struct ParamTraits<NestedDefLevel2> // expected-error {{Custom ParamTraits implementation for an enum type}} expected-note {{Please use a helper class for example ContiguousEnumSerializer}} +{ + typedef NestedDefLevel2 paramType; +}; + +// Make sure a non enum typedef is not accidentally flagged +typedef int IntTypedef; + +template<> +struct ParamTraits<IntTypedef> +{ + typedef IntTypedef paramType; +}; + +// Make sure ParamTraits using helper classes are not flagged +template<> +struct ParamTraits<GoodEnum> +: public ContiguousEnumSerializer<GoodEnum, + GoodEnum::GoodFirst, + GoodEnum::GoodLast> +{}; diff --git a/build/clang-plugin/tests/TestRefCountedCopyConstructor.cpp b/build/clang-plugin/tests/TestRefCountedCopyConstructor.cpp new file mode 100644 index 0000000000..d3bd73084c --- /dev/null +++ b/build/clang-plugin/tests/TestRefCountedCopyConstructor.cpp @@ -0,0 +1,25 @@ +// Implicit copy construct which is unused +class RC1 { + void AddRef(); + void Release(); + int mRefCnt; +}; + +// Explicit copy constructor which is used +class RC2 { +public: + RC2(); + RC2(const RC2&); +private: + void AddRef(); + void Release(); + int mRefCnt; +}; + +void f() { + RC1* r1 = new RC1(); + RC1* r1p = new RC1(*r1); // expected-error {{Invalid use of compiler-provided copy constructor on refcounted type}} expected-note {{The default copy constructor also copies the default mRefCnt property, leading to reference count imbalance issues. Please provide your own copy constructor which only copies the fields which need to be copied}} + + RC2* r2 = new RC2(); + RC2* r2p = new RC2(*r2); +} diff --git a/build/clang-plugin/tests/TestRefCountedThisInsideConstructor.cpp b/build/clang-plugin/tests/TestRefCountedThisInsideConstructor.cpp new file mode 100644 index 0000000000..a6684e3812 --- /dev/null +++ b/build/clang-plugin/tests/TestRefCountedThisInsideConstructor.cpp @@ -0,0 +1,76 @@ +#include <functional> + +#include <mozilla/RefPtr.h> + +struct RefCountedBase { + void AddRef(); + void Release(); +}; + +struct Bar; + +struct Foo : RefCountedBase { + void foo(); +}; + +struct Bar : RefCountedBase { + Bar() { + RefPtr<Bar> self = this; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + auto self2 = RefPtr(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + auto self3 = RefPtr{this}; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + RefPtr<Bar> self4(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + RefPtr<Bar> self5{this}; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + [self=RefPtr{this}]{}(); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + refptr(RefPtr{this}); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + refptr(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + } + + explicit Bar(float f) { + // Does not match member expressions with `this` + RefPtr<Foo> foo = this->mFoo; + foo->foo(); + auto foo2 = RefPtr(this->mFoo); + foo2->foo(); + auto foo3 = RefPtr{this->mFoo}; + foo3->foo(); + } + + explicit Bar(short i); + + explicit Bar(int i): mBar(this) {} // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + explicit Bar(int i, int i2): mBar(RefPtr(this)) {} // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + + void Init() { + // Does not match outside the constructor + RefPtr<Bar> self = this; + auto self2 = RefPtr(this); + auto self3 = RefPtr{this}; + } + + void refptr(const RefPtr<Bar>& aBar) {} + + RefPtr<Foo> mFoo; + RefPtr<Bar> mBar; +}; + +// Test case for non-inline constructor +Bar::Bar(short i) { + RefPtr<Bar> self = this; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + auto self2 = RefPtr(this); // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + auto self3 = RefPtr{this}; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} +} + +// Same goes for any class with MOZ_IS_REFPTR (not including nsCOMPtr because SM +// doesn't have it) +template <typename T> class MOZ_IS_REFPTR MyRefPtr { +public: + MOZ_IMPLICIT MyRefPtr(T *aPtr) : mPtr(aPtr) {} + T *mPtr; +}; + +class Baz : RefCountedBase { + Baz() { + MyRefPtr<Baz> self = this; // expected-error {{Refcounting `this` inside the constructor is a footgun, `this` may be destructed at the end of the constructor unless there's another strong reference. Consider adding a separate Create function and do the work there.}} + (void)self; + } +}; diff --git a/build/clang-plugin/tests/TestSprintfLiteral.cpp b/build/clang-plugin/tests/TestSprintfLiteral.cpp new file mode 100644 index 0000000000..3c54ce004f --- /dev/null +++ b/build/clang-plugin/tests/TestSprintfLiteral.cpp @@ -0,0 +1,41 @@ +#include <cstdio> + +void bad() { + char x[100]; + snprintf(x, sizeof(x), "bar"); // expected-error {{Use SprintfLiteral instead of snprintf when writing into a character array.}} expected-note {{This will prevent passing in the wrong size to snprintf accidentally.}} + snprintf(x, 100, "bar"); // expected-error {{Use SprintfLiteral instead of snprintf when writing into a character array.}} expected-note {{This will prevent passing in the wrong size to snprintf accidentally.}} + const int hundred = 100; + snprintf(x, hundred, "bar"); // expected-error {{Use SprintfLiteral instead of snprintf when writing into a character array.}} expected-note {{This will prevent passing in the wrong size to snprintf accidentally.}} +} + +void ok() { + char x[100]; + int y; + snprintf(x, sizeof(y), "foo"); + + snprintf(x, 50, "foo"); + + int nothundred = 100; + nothundred = 99; + snprintf(x, nothundred, "foo"); +} + +void vargs_bad(va_list args) { + char x[100]; + vsnprintf(x, sizeof(x), "bar", args); // expected-error {{Use VsprintfLiteral instead of vsnprintf when writing into a character array.}} expected-note {{This will prevent passing in the wrong size to vsnprintf accidentally.}} + vsnprintf(x, 100, "bar", args); // expected-error {{Use VsprintfLiteral instead of vsnprintf when writing into a character array.}} expected-note {{This will prevent passing in the wrong size to vsnprintf accidentally.}} + const int hundred = 100; + vsnprintf(x, hundred, "bar", args); // expected-error {{Use VsprintfLiteral instead of vsnprintf when writing into a character array.}} expected-note {{This will prevent passing in the wrong size to vsnprintf accidentally.}} +} + +void vargs_good(va_list args) { + char x[100]; + int y; + vsnprintf(x, sizeof(y), "foo", args); + + vsnprintf(x, 50, "foo", args); + + int nothundred = 100; + nothundred = 99; + vsnprintf(x, nothundred, "foo", args); +} diff --git a/build/clang-plugin/tests/TestStackClass.cpp b/build/clang-plugin/tests/TestStackClass.cpp new file mode 100644 index 0000000000..3289abef1b --- /dev/null +++ b/build/clang-plugin/tests/TestStackClass.cpp @@ -0,0 +1,50 @@ +#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) +#include <stddef.h> + +struct MOZ_STACK_CLASS Stack { + int i; + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_STACK_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void misuseStackClass(int len) { + Stack valid; + Stack alsoValid[2]; + static Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} + static Stack alsoNotValid[2]; // expected-error-re {{variable of type 'Stack{{ ?}}[2]' only valid on the stack}} expected-note-re {{'Stack{{ ?}}[2]' is a stack type because it is an array of stack type 'Stack'}} expected-note {{value incorrectly allocated in a global variable}} + + gobble(&valid); + gobble(¬Valid); + gobble(&alsoValid[0]); + + gobble(new Stack); // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}} + gobble(new Stack[10]); // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}} + gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}} + gobble(len <= 5 ? &valid : new Stack); // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}} + + char buffer[sizeof(Stack)]; + gobble(new (buffer) Stack); +} + +Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +struct RandomClass { + Stack nonstaticMember; // expected-note {{'RandomClass' is a stack type because member 'nonstaticMember' is a stack type 'Stack'}} + static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +}; +struct MOZ_STACK_CLASS RandomStackClass { + Stack nonstaticMember; + static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +}; + +struct BadInherit : Stack {}; // expected-note {{'BadInherit' is a stack type because it inherits from a stack type 'Stack'}} +struct MOZ_STACK_CLASS GoodInherit : Stack {}; + +BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} +RandomClass evenMoreInvalid; // expected-error {{variable of type 'RandomClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}} diff --git a/build/clang-plugin/tests/TestStaticLocalClass.cpp b/build/clang-plugin/tests/TestStaticLocalClass.cpp new file mode 100644 index 0000000000..c3b0d8645a --- /dev/null +++ b/build/clang-plugin/tests/TestStaticLocalClass.cpp @@ -0,0 +1,54 @@ +#define MOZ_STATIC_LOCAL_CLASS __attribute__((annotate("moz_static_local_class"))) +#include <stddef.h> + +struct MOZ_STATIC_LOCAL_CLASS StaticLocal { + int i; + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_STATIC_LOCAL_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void misuseStaticLocalClass(int len) { + StaticLocal notValid; // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated in an automatic variable}} + StaticLocal alsoNotValid[2]; // expected-error-re {{variable of type 'StaticLocal{{ ?}}[2]' is only valid as a static local}} expected-note-re {{'StaticLocal{{ ?}}[2]' is a static-local type because it is an array of static-local type 'StaticLocal'}} expected-note {{value incorrectly allocated in an automatic variable}} + static StaticLocal valid; + static StaticLocal alsoValid[2]; + + gobble(¬Valid); + gobble(&valid); + gobble(&alsoValid[0]); + + gobble(new StaticLocal); // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated on the heap}} + gobble(new StaticLocal[10]); // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated on the heap}} + gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' is only valid as a static local}} expected-note {{value incorrectly allocated on the heap}} + gobble(len <= 5 ? &valid : new StaticLocal); // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated on the heap}} + + char buffer[sizeof(StaticLocal)]; + gobble(new (buffer) StaticLocal); +} + +StaticLocal notValid; // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated in a global variable}} + +struct RandomClass { + StaticLocal nonstaticMember; // expected-note {{'RandomClass' is a static-local type because member 'nonstaticMember' is a static-local type 'StaticLocal'}} + static StaticLocal staticMember; // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated in a global variable}} +}; + +struct MOZ_STATIC_LOCAL_CLASS RandomStaticLocalClass { + StaticLocal nonstaticMember; + static StaticLocal staticMember; // expected-error {{variable of type 'StaticLocal' is only valid as a static local}} expected-note {{value incorrectly allocated in a global variable}} +}; + +struct BadInherit : StaticLocal {}; // expected-note {{'BadInherit' is a static-local type because it inherits from a static-local type 'StaticLocal'}} +struct MOZ_STATIC_LOCAL_CLASS GoodInherit : StaticLocal {}; + +void misuseStaticLocalClassEvenMore(int len) { + BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' is only valid as a static local}} expected-note {{value incorrectly allocated in an automatic variable}} + RandomClass evenMoreInvalid; // expected-error {{variable of type 'RandomClass' is only valid as a static local}} expected-note {{value incorrectly allocated in an automatic variable}} +} diff --git a/build/clang-plugin/tests/TestTemporaryClass.cpp b/build/clang-plugin/tests/TestTemporaryClass.cpp new file mode 100644 index 0000000000..f00acf0d7a --- /dev/null +++ b/build/clang-plugin/tests/TestTemporaryClass.cpp @@ -0,0 +1,72 @@ +#define MOZ_TEMPORARY_CLASS __attribute__((annotate("moz_temporary_class"))) +#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) + +#include <stddef.h> + +struct MOZ_TEMPORARY_CLASS Temporary { + int i; + Temporary() {} + MOZ_IMPLICIT Temporary(int a) {} + Temporary(int a, int b) {} + void *operator new(size_t x) throw() { return 0; } + void *operator new(size_t blah, char *buffer) { return buffer; } +}; + +template <class T> +struct MOZ_TEMPORARY_CLASS TemplateClass { + T i; +}; + +void gobble(void *) { } + +void gobbleref(const Temporary&) { } + +template <class T> +void gobbleanyref(const T&) { } + +void misuseNonTemporaryClass(int len) { + // All of these should error. + Temporary invalid; // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated in an automatic variable}} + Temporary alsoInvalid[2]; // expected-error-re {{variable of type 'Temporary{{ ?}}[2]' is only valid as a temporary}} expected-note {{value incorrectly allocated in an automatic variable}} expected-note-re {{'Temporary{{ ?}}[2]' is a temporary type because it is an array of temporary type 'Temporary'}} + static Temporary invalidStatic; // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated in a global variable}} + static Temporary alsoInvalidStatic[2]; // expected-error-re {{variable of type 'Temporary{{ ?}}[2]' is only valid as a temporary}} expected-note {{value incorrectly allocated in a global variable}} expected-note-re {{'Temporary{{ ?}}[2]' is a temporary type because it is an array of temporary type 'Temporary'}} + + gobble(&invalid); + gobble(&invalidStatic); + gobble(&alsoInvalid[0]); + + // All of these should be fine. + gobbleref(Temporary()); + gobbleref(Temporary(10, 20)); + gobbleref(Temporary(10)); + gobbleref(10); + gobbleanyref(TemplateClass<int>()); + + // All of these should error. + gobble(new Temporary); // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated on the heap}} + gobble(new Temporary[10]); // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated on the heap}} + gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' is only valid as a temporary}} expected-note {{value incorrectly allocated on the heap}} + gobble(len <= 5 ? &invalid : new Temporary); // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated on the heap}} + + // Placement new is odd, but okay. + char buffer[sizeof(Temporary)]; + gobble(new (buffer) Temporary); +} + +void defaultArg(const Temporary& arg = Temporary()) { // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated in an automatic variable}} +} + +// Can't be a global, this should error. +Temporary invalidStatic; // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated in a global variable}} + +struct RandomClass { + Temporary nonstaticMember; // This is okay if RandomClass is only used as a temporary. + static Temporary staticMember; // expected-error {{variable of type 'Temporary' is only valid as a temporary}} expected-note {{value incorrectly allocated in a global variable}} +}; + +struct BadInherit : Temporary {}; + +void useStuffWrongly() { + gobbleanyref(BadInherit()); + gobbleanyref(RandomClass()); +} diff --git a/build/clang-plugin/tests/TestTrivialCtorDtor.cpp b/build/clang-plugin/tests/TestTrivialCtorDtor.cpp new file mode 100644 index 0000000000..a1038b6e63 --- /dev/null +++ b/build/clang-plugin/tests/TestTrivialCtorDtor.cpp @@ -0,0 +1,88 @@ +#define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor"))) + +struct MOZ_TRIVIAL_CTOR_DTOR EmptyClass{}; + +template <class T> +struct MOZ_TRIVIAL_CTOR_DTOR TemplateEmptyClass{}; + +struct MOZ_TRIVIAL_CTOR_DTOR NonEmptyClass { + void *m; +}; + +template <class T> +struct MOZ_TRIVIAL_CTOR_DTOR TemplateNonEmptyClass { + T* m; +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadUserDefinedCtor { // expected-error {{class 'BadUserDefinedCtor' must have trivial constructors and destructors}} + BadUserDefinedCtor() {} +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadUserDefinedDtor { // expected-error {{class 'BadUserDefinedDtor' must have trivial constructors and destructors}} + ~BadUserDefinedDtor() {} +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualDtor { // expected-error {{class 'BadVirtualDtor' must have trivial constructors and destructors}} + virtual ~BadVirtualDtor() {} +}; + +struct MOZ_TRIVIAL_CTOR_DTOR OkVirtualMember { + virtual void f(); +}; + +void foo(); +struct MOZ_TRIVIAL_CTOR_DTOR BadNonEmptyCtorDtor { // expected-error {{class 'BadNonEmptyCtorDtor' must have trivial constructors and destructors}} + BadNonEmptyCtorDtor() { foo(); } + ~BadNonEmptyCtorDtor() { foo(); } +}; + +struct NonTrivialCtor { + NonTrivialCtor() { foo(); } +}; + +struct NonTrivialDtor { + ~NonTrivialDtor() { foo(); } +}; + +struct VirtualMember { + virtual void f(); +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialCtorInBase : NonTrivialCtor { // expected-error {{class 'BadNonTrivialCtorInBase' must have trivial constructors and destructors}} +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialDtorInBase : NonTrivialDtor { // expected-error {{class 'BadNonTrivialDtorInBase' must have trivial constructors and destructors}} +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialCtorInMember { // expected-error {{class 'BadNonTrivialCtorInMember' must have trivial constructors and destructors}} + NonTrivialCtor m; +}; + +struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialDtorInMember { // expected-error {{class 'BadNonTrivialDtorInMember' must have trivial constructors and destructors}} + NonTrivialDtor m; +}; + +struct MOZ_TRIVIAL_CTOR_DTOR OkVirtualMemberInMember { + VirtualMember m; +}; + +struct MOZ_TRIVIAL_CTOR_DTOR OkConstExprConstructor { + constexpr OkConstExprConstructor() {} +}; + +struct MOZ_TRIVIAL_CTOR_DTOR OkConstExprConstructorInMember { + OkConstExprConstructor m; +}; + +#if __cplusplus >= 202002L +struct +#else +// XXX: This error is unfortunate, but is unlikely to come up in real code. +// In this situation, it should be possible to define a constexpr constructor +// which explicitly initializes the members. +struct // expected-error {{class 'BadUnfortunateError' must have trivial constructors and destructors}} +#endif +MOZ_TRIVIAL_CTOR_DTOR BadUnfortunateError { + OkConstExprConstructor m; + void *n; +}; diff --git a/build/clang-plugin/tests/TestTrivialDtor.cpp b/build/clang-plugin/tests/TestTrivialDtor.cpp new file mode 100644 index 0000000000..f86d41b238 --- /dev/null +++ b/build/clang-plugin/tests/TestTrivialDtor.cpp @@ -0,0 +1,52 @@ +#define MOZ_TRIVIAL_DTOR __attribute__((annotate("moz_trivial_dtor"))) + +struct MOZ_TRIVIAL_DTOR EmptyClass{}; + +template <class T> +struct MOZ_TRIVIAL_DTOR TemplateEmptyClass{}; + +struct MOZ_TRIVIAL_DTOR NonEmptyClass { + void *m; +}; + +template <class T> +struct MOZ_TRIVIAL_DTOR TemplateNonEmptyClass { + T* m; +}; + +struct MOZ_TRIVIAL_DTOR BadUserDefinedDtor { // expected-error {{class 'BadUserDefinedDtor' must have a trivial destructor}} + ~BadUserDefinedDtor() {} +}; + +struct MOZ_TRIVIAL_DTOR BadVirtualDtor { // expected-error {{class 'BadVirtualDtor' must have a trivial destructor}} + virtual ~BadVirtualDtor() {} +}; + +struct MOZ_TRIVIAL_DTOR OkVirtualMember { + virtual void f(); +}; + +void foo(); +struct MOZ_TRIVIAL_DTOR BadNonEmptyCtorDtor { // expected-error {{class 'BadNonEmptyCtorDtor' must have a trivial destructor}} + BadNonEmptyCtorDtor() { foo(); } + ~BadNonEmptyCtorDtor() { foo(); } +}; + +struct NonTrivialDtor { + ~NonTrivialDtor() { foo(); } +}; + +struct VirtualMember { + virtual void f(); +}; + +struct MOZ_TRIVIAL_DTOR BadNonTrivialDtorInBase : NonTrivialDtor { // expected-error {{class 'BadNonTrivialDtorInBase' must have a trivial destructor}} +}; + +struct MOZ_TRIVIAL_DTOR BadNonTrivialDtorInMember { // expected-error {{class 'BadNonTrivialDtorInMember' must have a trivial destructor}} + NonTrivialDtor m; +}; + +struct MOZ_TRIVIAL_DTOR OkVirtualMemberInMember { + VirtualMember m; +}; diff --git a/build/clang-plugin/tests/moz.build b/build/clang-plugin/tests/moz.build new file mode 100644 index 0000000000..45f416be44 --- /dev/null +++ b/build/clang-plugin/tests/moz.build @@ -0,0 +1,101 @@ +# -*- 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/. + +# dummy library name to avoid skipping building the sources here. +Library("clang-plugin-tests") + +SOURCES += [ + "TestAssertWithAssignment.cpp", + "TestBadImplicitConversionCtor.cpp", + "TestCanRunScript.cpp", + "TestCustomHeap.cpp", + "TestDanglingOnTemporary.cpp", + "TestExplicitOperatorBool.cpp", + "TestGlobalClass.cpp", + "TestHeapClass.cpp", + "TestInheritTypeAnnotationsFromTemplateArgs.cpp", + "TestJSHandleRootedTypedef.cpp", + "TestKnownLive.cpp", + "TestKungFuDeathGrip.cpp", + "TestMultipleAnnotations.cpp", + "TestMustOverride.cpp", + "TestMustReturnFromCaller.cpp", + "TestNANTestingExpr.cpp", + "TestNANTestingExprC.c", + "TestNeedsNoVTableType.cpp", + "TestNoAddRefReleaseOnReturn.cpp", + "TestNoArithmeticExprInArgument.cpp", + "TestNoAutoType.cpp", + "TestNoDuplicateRefCntMember.cpp", + "TestNoExplicitMoveConstructor.cpp", + "TestNoNewThreadsChecker.cpp", + "TestNonHeapClass.cpp", + "TestNonMemMovable.cpp", + "TestNonMemMovableStd.cpp", + "TestNonMemMovableStdAtomic.cpp", + "TestNonParameterChecker.cpp", + "TestNonTemporaryClass.cpp", + "TestNonTrivialTypeInFfi.cpp", + "TestNoPrincipalGetUri.cpp", + "TestNoRefcountedInsideLambdas.cpp", + "TestNoUsingNamespaceMozillaJava.cpp", + "TestOverrideBaseCall.cpp", + "TestOverrideBaseCallAnnotation.cpp", + "TestParamTraitsEnum.cpp", + "TestRefCountedCopyConstructor.cpp", + "TestRefCountedThisInsideConstructor.cpp", + "TestSprintfLiteral.cpp", + "TestStackClass.cpp", + "TestStaticLocalClass.cpp", + "TestTemporaryClass.cpp", + "TestTrivialCtorDtor.cpp", + "TestTrivialDtor.cpp", +] + +if CONFIG["OS_ARCH"] == "WINNT": + SOURCES += [ + "TestFopenUsage.cpp", + "TestLoadLibraryUsage.cpp", + ] + +include("../external/tests/sources.mozbuild") + +if CONFIG["ENABLE_CLANG_PLUGIN_ALPHA"]: + DEFINES["MOZ_CLANG_PLUGIN_ALPHA"] = "1" + include("../alpha/tests/sources.mozbuild") + +DisableStlWrapping() +NoVisibilityFlags() + +# Build without any warning flags, and with clang verify flag for a +# syntax-only build (no codegen), without a limit on the number of errors. +COMPILE_FLAGS["OS_CXXFLAGS"] = [ + f for f in COMPILE_FLAGS.get("OS_CXXFLAGS", []) if not f.startswith("-W") +] + [ + "-fsyntax-only", + "-Xclang", + "-verify", + "-ferror-limit=0", + "-Wno-invalid-noreturn", + # For SpiderMonkey headers in TestJSHandleRootedTypedef.cpp + "-Wno-attributes", + "-Wno-invalid-offsetof", +] +COMPILE_FLAGS["OS_CFLAGS"] = [ + f for f in COMPILE_FLAGS.get("OS_CFLAGS", []) if not f.startswith("-W") +] + [ + "-fsyntax-only", + "-Xclang", + "-verify", + "-ferror-limit=0", + "-Xclang", + "-std=c11", + "-Wno-invalid-noreturn", +] + +# Don't reflect WARNINGS_CFLAGS into CFLAGS, as the warnings flags should be +# as specified in OS_CFLAGS above. +DisableCompilerWarnings() diff --git a/build/compare-mozconfig/compare-mozconfigs.py b/build/compare-mozconfig/compare-mozconfigs.py new file mode 100644 index 0000000000..210fd0568e --- /dev/null +++ b/build/compare-mozconfig/compare-mozconfigs.py @@ -0,0 +1,176 @@ +#!/usr/bin/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/. + +# originally from https://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py # NOQA: E501 + +import difflib +import logging +import os +import unittest + +import buildconfig +import mozunit + +FAILURE_CODE = 1 +SUCCESS_CODE = 0 + +PLATFORMS = ( + "linux32", + "linux64", + "macosx64", + "win32", + "win64", + "win64-aarch64", +) + +log = logging.getLogger(__name__) + + +class ConfigError(Exception): + pass + + +def readConfig(configfile): + c = {} + execfile(configfile, c) + return c["whitelist"] + + +def verify_mozconfigs( + mozconfig_pair, nightly_mozconfig_pair, platform, mozconfigWhitelist +): + """Compares mozconfig to nightly_mozconfig and compare to an optional + whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair + are pairs containing the mozconfig's identifier and the list of lines in + the mozconfig.""" + + # unpack the pairs to get the names, the names are just for + # identifying the mozconfigs when logging the error messages + mozconfig_name, mozconfig_lines = mozconfig_pair + nightly_mozconfig_name, nightly_mozconfig_lines = nightly_mozconfig_pair + + if not mozconfig_lines or not nightly_mozconfig_lines: + log.info("Missing mozconfigs to compare for %s" % platform) + return False + + success = True + + diff_instance = difflib.Differ() + diff_result = diff_instance.compare(mozconfig_lines, nightly_mozconfig_lines) + diff_list = list(diff_result) + + for line in diff_list: + clean_line = line[1:].strip() + if (line[0] == "-" or line[0] == "+") and len(clean_line) > 1: + # skip comment lines + if clean_line.startswith("#"): + continue + # compare to whitelist + message = "" + if line[0] == "-": + # handle lines that move around in diff + if "+" + line[1:] in diff_list: + continue + if platform in mozconfigWhitelist.get("release", {}): + if clean_line in mozconfigWhitelist["release"][platform]: + continue + elif line[0] == "+": + if "-" + line[1:] in diff_list: + continue + if platform in mozconfigWhitelist.get("nightly", {}): + if clean_line in mozconfigWhitelist["nightly"][platform]: + continue + else: + log.warning( + "%s not in %s %s!" + % ( + clean_line, + platform, + mozconfigWhitelist["nightly"][platform], + ) + ) + else: + log.error("Skipping line %s!" % line) + continue + message = "found in %s but not in %s: %s" + if line[0] == "-": + log.error( + message % (mozconfig_name, nightly_mozconfig_name, clean_line) + ) + else: + log.error( + message % (nightly_mozconfig_name, mozconfig_name, clean_line) + ) + success = False + return success + + +def get_mozconfig(path): + """Consumes a path and returns a list of lines from the mozconfig file.""" + with open(path, "rb") as fh: + return fh.readlines() + + +def compare(topsrcdir): + app = os.path.join(topsrcdir, "browser") + whitelist = readConfig(os.path.join(app, "config", "mozconfigs", "whitelist")) + + success = True + + def normalize_lines(lines): + return {l.strip() for l in lines} + + for platform in PLATFORMS: + log.info("Comparing platform %s" % platform) + + mozconfigs_path = os.path.join(app, "config", "mozconfigs", platform) + + nightly_path = os.path.join(mozconfigs_path, "nightly") + beta_path = os.path.join(mozconfigs_path, "beta") + release_path = os.path.join(mozconfigs_path, "release") + + nightly_lines = get_mozconfig(nightly_path) + beta_lines = get_mozconfig(beta_path) + release_lines = get_mozconfig(release_path) + + # Validate that entries in whitelist['nightly'][platform] are actually + # present. + whitelist_normalized = normalize_lines(whitelist["nightly"].get(platform, [])) + nightly_normalized = normalize_lines(nightly_lines) + + for line in sorted(whitelist_normalized - nightly_normalized): + log.error("extra line in nightly whitelist: %s" % line) + success = False + + log.info("Comparing beta and nightly mozconfigs") + passed = verify_mozconfigs( + (beta_path, beta_lines), (nightly_path, nightly_lines), platform, whitelist + ) + + if not passed: + success = False + + log.info("Comparing release and nightly mozconfigs") + passed = verify_mozconfigs( + (release_path, release_lines), + (nightly_path, nightly_lines), + platform, + whitelist, + ) + if not passed: + success = False + + return success + + +class TestCompareMozconfigs(unittest.TestCase): + def test_compare_mozconfigs(self): + topsrcdir = buildconfig.substs["top_srcdir"] + self.assertTrue(compare(topsrcdir)) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + mozunit.main() diff --git a/build/compare-mozconfig/python.toml b/build/compare-mozconfig/python.toml new file mode 100644 index 0000000000..8398d582f2 --- /dev/null +++ b/build/compare-mozconfig/python.toml @@ -0,0 +1,5 @@ +[DEFAULT] +skip-if = ["true"] # fails on Python 3 +subsuite = "mozbuild" + +["compare-mozconfigs.py"] diff --git a/build/debian-packages/pygobject.diff b/build/debian-packages/pygobject.diff new file mode 100644 index 0000000000..b56edfae54 --- /dev/null +++ b/build/debian-packages/pygobject.diff @@ -0,0 +1,117 @@ +diff -Nru pygobject-3.26.1/debian/changelog pygobject-3.26.1/debian/changelog
+--- pygobject-3.26.1/debian/changelog 2019-01-29 21:46:03.000000000 +0900
++++ pygobject-3.26.1/debian/changelog 2023-12-08 09:22:32.000000000 +0900
+@@ -1,3 +1,9 @@
++pygobject (3.26.1-2ubuntu1.ub18moz1) bionic; urgency=medium
++
++ * Backport fix for python 3.8 support.
++
++ -- Mike Hommey <mhommey@mozilla.com> Fri, 08 Dec 2023 09:22:32 +0900
++
+ pygobject (3.26.1-2ubuntu1) bionic; urgency=medium
+
+ * Update Vcs fields for ubuntu/bionic branch
+diff -Nru pygobject-3.26.1/debian/patches/python3.8.patch pygobject-3.26.1/debian/patches/python3.8.patch
+--- pygobject-3.26.1/debian/patches/python3.8.patch 1970-01-01 09:00:00.000000000 +0900
++++ pygobject-3.26.1/debian/patches/python3.8.patch 2023-12-08 09:22:32.000000000 +0900
+@@ -0,0 +1,94 @@
++Description: Backport fix for python 3.8 support
++
++Original upstream patch:
++https://gitlab.gnome.org/GNOME/pygobject/-/commit/bfc759c9c0bb
++
++Original backport to 3.28:
++https://svnweb.freebsd.org/ports/head/devel/pygobject3-common/files/patch-python38?view=markup&pathrev=537996
++
++--- pygobject-3.26.1.orig/gi/gimodule.c
+++++ pygobject-3.26.1/gi/gimodule.c
++@@ -689,7 +689,10 @@ PYGLIB_MODULE_START(_gi, "_gi")
++ pygi_error_register_types (module);
++ _pygi_repository_register_types (module);
++ _pygi_info_register_types (module);
+++ pygobject_type_register_types (module_dict);
+++ pygobject_pointer_register_types (module_dict);
++ _pygi_struct_register_types (module);
+++ pygobject_boxed_register_types (module_dict);
++ _pygi_boxed_register_types (module);
++ _pygi_ccallback_register_types (module);
++ pygi_resulttuple_register_types (module);
++@@ -703,12 +706,9 @@ PYGLIB_MODULE_START(_gi, "_gi")
++ pygobject_register_features (module_dict);
++ pygobject_register_version_tuples (module_dict);
++ pygobject_register_warnings (module_dict);
++- pygobject_type_register_types (module_dict);
++ pygobject_object_register_types (module_dict);
++ pygobject_interface_register_types (module_dict);
++ pygobject_paramspec_register_types (module_dict);
++- pygobject_boxed_register_types (module_dict);
++- pygobject_pointer_register_types (module_dict);
++ pygobject_enum_register_types (module_dict);
++ pygobject_flags_register_types (module_dict);
++
++--- pygobject-3.26.1.orig/gi/pygboxed.c
+++++ pygobject-3.26.1/gi/pygboxed.c
++@@ -162,6 +162,7 @@ pyg_register_boxed(PyObject *dict, const
++ if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_boxed_dealloc;
++
++ Py_TYPE(type) = &PyType_Type;
+++ g_assert (Py_TYPE (&PyGBoxed_Type) != NULL);
++ type->tp_base = &PyGBoxed_Type;
++
++ if (PyType_Ready(type) < 0) {
++--- pygobject-3.26.1.orig/gi/pygi-boxed.c
+++++ pygobject-3.26.1/gi/pygi-boxed.c
++@@ -242,6 +242,7 @@ void
++ _pygi_boxed_register_types (PyObject *m)
++ {
++ Py_TYPE(&PyGIBoxed_Type) = &PyType_Type;
+++ g_assert (Py_TYPE (&PyGBoxed_Type) != NULL);
++ PyGIBoxed_Type.tp_base = &PyGBoxed_Type;
++ PyGIBoxed_Type.tp_new = (newfunc) _boxed_new;
++ PyGIBoxed_Type.tp_init = (initproc) _boxed_init;
++--- pygobject-3.26.1.orig/gi/pygi-struct.c
+++++ pygobject-3.26.1/gi/pygi-struct.c
++@@ -221,6 +221,7 @@ void
++ _pygi_struct_register_types (PyObject *m)
++ {
++ Py_TYPE(&PyGIStruct_Type) = &PyType_Type;
+++ g_assert (Py_TYPE (&PyGPointer_Type) != NULL);
++ PyGIStruct_Type.tp_base = &PyGPointer_Type;
++ PyGIStruct_Type.tp_new = (newfunc) _struct_new;
++ PyGIStruct_Type.tp_init = (initproc) _struct_init;
++--- pygobject-3.26.1.orig/gi/pyginterface.c
+++++ pygobject-3.26.1/gi/pyginterface.c
++@@ -72,6 +72,7 @@ pyg_register_interface(PyObject *dict, c
++ PyObject *o;
++
++ Py_TYPE(type) = &PyType_Type;
+++ g_assert (Py_TYPE (&PyGInterface_Type) != NULL);
++ type->tp_base = &PyGInterface_Type;
++
++ if (PyType_Ready(type) < 0) {
++--- pygobject-3.26.1.orig/gi/pygpointer.c
+++++ pygobject-3.26.1/gi/pygpointer.c
++@@ -117,6 +117,7 @@ pyg_register_pointer(PyObject *dict, con
++ if (!type->tp_dealloc) type->tp_dealloc = (destructor)pyg_pointer_dealloc;
++
++ Py_TYPE(type) = &PyType_Type;
+++ g_assert (Py_TYPE (&PyGPointer_Type) != NULL);
++ type->tp_base = &PyGPointer_Type;
++
++ if (PyType_Ready(type) < 0) {
++--- pygobject-3.26.1.orig/gi/pygtype.c
+++++ pygobject-3.26.1/gi/pygtype.c
++@@ -345,6 +345,7 @@ pyg_type_wrapper_new(GType type)
++ {
++ PyGTypeWrapper *self;
++
+++ g_assert (Py_TYPE (&PyGTypeWrapper_Type) != NULL);
++ self = (PyGTypeWrapper *)PyObject_NEW(PyGTypeWrapper,
++ &PyGTypeWrapper_Type);
++ if (self == NULL)
+diff -Nru pygobject-3.26.1/debian/patches/series pygobject-3.26.1/debian/patches/series
+--- pygobject-3.26.1/debian/patches/series 2019-01-29 21:46:03.000000000 +0900
++++ pygobject-3.26.1/debian/patches/series 2023-12-08 09:22:20.000000000 +0900
+@@ -1 +1,2 @@
+ fix-tests-with-newest-glib.patch
++python3.8.patch
diff --git a/build/debian-packages/ubuntu-glibc.diff b/build/debian-packages/ubuntu-glibc.diff new file mode 100644 index 0000000000..949d7b393b --- /dev/null +++ b/build/debian-packages/ubuntu-glibc.diff @@ -0,0 +1,13 @@ +diff -Nru glibc-2.27/debian/changelog glibc-2.27/debian/changelog +--- glibc-2.27/debian/changelog 2020-06-05 02:25:26.000000000 +0900 ++++ glibc-2.27/debian/changelog 2021-06-25 17:54:19.000000000 +0900 +@@ -1,3 +1,9 @@ ++glibc (2.27-3ubuntu1.2.ub18moz1) bionic; urgency=medium ++ ++ * Mozilla backport for bionic. ++ ++ -- Mike Hommey <mhommey@mozilla.com> Fri, 25 Jun 2021 17:54:19 +0900 ++ + glibc (2.27-3ubuntu1.2) bionic-security; urgency=medium + + * SECURITY UPDATE: integer overflow in realpath diff --git a/build/defines.sh b/build/defines.sh new file mode 100644 index 0000000000..cf98c3d8bf --- /dev/null +++ b/build/defines.sh @@ -0,0 +1,3 @@ +# Define indicating that this build is prior to one of the early betas. To be +# unset mid-way through the beta cycle. +EARLY_BETA_OR_EARLIER= diff --git a/build/docs/build-overview.rst b/build/docs/build-overview.rst new file mode 100644 index 0000000000..a7784e7b1a --- /dev/null +++ b/build/docs/build-overview.rst @@ -0,0 +1,117 @@ +.. _build_overview: + +===================== +Build System Overview +===================== + +This document provides an overview on how the build system works. It is +targeted at people wanting to learn about internals of the build system. +It is not meant for persons who casually interact with the build system. +That being said, knowledge empowers, so consider reading on. + +The build system is composed of many different components working in +harmony to build the source tree. We begin with a graphic overview. + +.. graphviz:: + + digraph build_components { + rankdir="LR"; + "configure" -> "config.status" -> "build backend" -> "build output" + } + +Phase 1: Configuration +====================== + +Phase 1 centers around the ``configure`` script, which is a bash shell script. +The file is generated from a file called ``configure.in`` which is written in M4 +and processed using Autoconf 2.13 to create the final configure script. +You don't have to worry about how you obtain a ``configure`` file: the build +system does this for you. + +The primary job of ``configure`` is to determine characteristics of the system +and compiler, apply options passed into it, and validate everything looks OK to +build. The primary output of the ``configure`` script is an executable file +in the object directory called ``config.status``. ``configure`` also produces +some additional files (like ``autoconf.mk``). However, the most important file +in terms of architecture is ``config.status``. + +The existence of a ``config.status`` file may be familiar to those who have worked +with Autoconf before. However, Mozilla's ``config.status`` is different from almost +any other ``config.status`` you've ever seen: it's written in Python! Instead of +having our ``configure`` script produce a shell script, we have it generating +Python. + +Now is as good a time as any to mention that Python is prevalent in our build +system. If we need to write code for the build system, we do it in Python. +That's just how we roll. For more, see :ref:`python`. + +``config.status`` contains 2 parts: data structures representing the output of +``configure`` and a command-line interface for preparing/configuring/generating +an appropriate build backend. (A build backend is merely a tool used to build +the tree - like GNU Make or Tup). These data structures essentially describe +the current state of the system and what the existing build configuration looks +like. For example, it defines which compiler to use, how to invoke it, which +application features are enabled, etc. You are encouraged to open up +``config.status`` to have a look for yourself! + +Once we have emitted a ``config.status`` file, we pass into the realm of +phase 2. + +Phase 2: Build Backend Preparation and the Build Definition +=========================================================== + +Once ``configure`` has determined what the current build configuration is, +we need to apply this to the source tree so we can actually build. + +What essentially happens is the automatically-produced ``config.status`` Python +script is executed as soon as ``configure`` has generated it. ``config.status`` +is charged with the task of tell a tool how to build the tree. To do this, +``config.status`` must first scan the build system definition. + +The build system definition consists of various ``moz.build`` files in the tree. +There is roughly one ``moz.build`` file per directory or per set of related directories. +Each ``moz.build`` files defines how its part of the build config works. For +example it says *I want these C++ files compiled* or *look for additional +information in these directories.* config.status starts with the ``moz.build`` +file from the root directory and then descends into referenced ``moz.build`` +files by following ``DIRS`` variables or similar. + +As the ``moz.build`` files are read, data structures describing the overall +build system definition are emitted. These data structures are then fed into a +build backend, which then performs actions, such as writing out files to +be read by a build tool. e.g. a ``make`` backend will write a +``Makefile``. + +When ``config.status`` runs, you'll see the following output:: + + Reticulating splines... + Finished reading 1096 moz.build files into 1276 descriptors in 2.40s + Backend executed in 2.39s + 2188 total backend files. 0 created; 1 updated; 2187 unchanged + Total wall time: 5.03s; CPU time: 3.79s; Efficiency: 75% + +What this is saying is that a total of *1096* ``moz.build`` files were read. +Altogether, *1276* data structures describing the build configuration were +derived from them. It took *2.40s* wall time to just read these files and +produce the data structures. The *1276* data structures were fed into the +build backend which then determined it had to manage *2188* files derived +from those data structures. Most of them already existed and didn't need +changed. However, *1* was updated as a result of the new configuration. +The whole process took *5.03s*. Although, only *3.79s* was in +CPU time. That likely means we spent roughly *25%* of the time waiting on +I/O. + +For more on how ``moz.build`` files work, see :ref:`mozbuild-files`. + +Phase 3: Invocation of the Build Backend +======================================== + +When most people think of the build system, they think of phase 3. This is +where we take all the code in the tree and produce Firefox or whatever +application you are creating. Phase 3 effectively takes whatever was +generated by phase 2 and runs it. Since the dawn of Mozilla, this has been +make consuming Makefiles. However, with the transition to moz.build files, +you may soon see non-Make build backends, such as Tup or Visual Studio. + +When building the tree, most of the time is spent in phase 3. This is when +header files are installed, C++ files are compiled, files are preprocessed, etc. diff --git a/build/docs/build-targets.rst b/build/docs/build-targets.rst new file mode 100644 index 0000000000..dacd46c7f4 --- /dev/null +++ b/build/docs/build-targets.rst @@ -0,0 +1,62 @@ +.. _build_targets: + +============= +Build Targets +============= + +When you build with ``mach build``, there are some special targets that can be +built. This page attempts to document them. + +Partial Tree Targets +==================== + +The targets in this section only build part of the tree. Please note that +partial tree builds can be unreliable. Use at your own risk. + +export + Build the *export* tier. The *export* tier builds everything that is + required for C/C++ compilation. It stages all header files, processes + IDLs, etc. + +compile + Build the *compile* tier. The *compile* tier compiles all C/C++ files. + +libs + Build the *libs* tier. The *libs* tier performs linking and performs + most build steps which aren't related to compilation. + +tools + Build the *tools* tier. The *tools* tier mostly deals with supplementary + tools and compiled tests. It will link tools against libXUL, including + compiled test binaries. + +binaries: + Recompiles and relinks C/C++ files. Only works after a complete normal + build, but allows for much faster rebuilds of C/C++ code. For performance + reasons, however, it skips nss, nspr, icu and ffi. This is targeted to + improve local developer workflow when touching C/C++ code. + +install-manifests + Process install manifests. Install manifests handle the installation of + files into the object directory. + + Unless ``NO_REMOVE=1`` is defined in the environment, files not accounted + in the install manifests will be deleted from the object directory. + +install-tests + Processes the tests install manifest. + +Common Actions +============== + +The targets in this section correspond to common build-related actions. Many +of the actions in this section are effectively frontends to shell scripts. +These actions will likely all be replaced by mach commands someday. + +buildsymbols + Create a symbols archive for the current build. + + This must be performed after a successful build. + +check + Run build system tests. diff --git a/build/docs/chrome-registration.rst b/build/docs/chrome-registration.rst new file mode 100644 index 0000000000..5c40f5ced7 --- /dev/null +++ b/build/docs/chrome-registration.rst @@ -0,0 +1,459 @@ +Chrome Registration +------------------- + +What is chrome? +--------------- + +`Chrome` is the set of user interface elements of the +application window that are outside the window's content area. Toolbars, +menu bars, progress bars, and window title bars are all examples of +elements that are typically part of the chrome. + +``chrome.manifest`` files are used to register XPCOM components and sources for the chrome protocol. +Every application supplies a root ``chrome.manifest`` file that Mozilla reads on startup. + +Chrome providers +---------------- + +A supplier of chrome for a given window type (e.g., for the browser +window) is called a chrome provider. The providers work together to +supply a complete set of chrome for a particular window, from the images +on the toolbar buttons to the files that describe the text, content, and +appearance of the window itself. + +There are three basic types of chrome providers: + +Content + The main source file for a window description comes from the content + provider, and it can be any file type viewable from within Mozilla. + It will typically be a XUL file, since XUL is designed for describing + the contents of windows and dialogs. The JavaScript files that define + the user interface are also contained within the content packages. + +Locale + Localizable applications keep all their localized information in + locale providers and Fluent FTL files, which are handled separately. + This allows translators to plug in a different + chrome package to translate an application without altering the rest + of the source code. In a chrome provider, localizable files are mostly + Java-style properties files. +Skin + A skin provider is responsible for providing a complete set of files + that describe the visual appearance of the chrome. Typically a skin + provider will provide CSS files and + images. + +The chrome registry +------------------- + +The Gecko runtime maintains a service known as the chrome registry that +provides mappings from chrome package names to the physical location of +chrome packages on disk. + +This chrome registry is configurable and persistent, and thus a user can +install different chrome providers, and select a preferred skin and +locale. This is accomplished through xpinstall and the extension +manager. + +In order to inform the chrome registry of the available chrome, a text +manifest is used: this manifest is "chrome.manifest" in the root of an +extension, or theme, or XULRunner application. + +The plaintext chrome manifests are in a simple line-based format. Each +line is parsed individually; if the line is parsable the chrome registry +takes the action identified by that line, otherwise the chrome registry +ignores that line (and prints a warning message in the runtime error +console). + +.. code:: text + + locale packagename localename path/to/files + skin packagename skinname path/to/files + +.. note:: + + The characters @ # ; : ? / are not allowed in the + packagename. + +Manifest instructions +--------------------- + +comments +~~~~~~~~ + +.. code:: text + + # this line is a comment - you can put here whatever you want + +A line is a comment if it begins with the character '#'. Any following +character in the same line is ignored. + +manifest +~~~~~~~~ + +:: + + manifest subdirectory/foo.manifest [flags] + +This will load a secondary manifest file. This can be useful for +separating component and chrome registration instructions, or separate +platform-specific registration data. + +component +~~~~~~~~~ + +:: + + component {00000000-0000-0000-0000-000000000000} components/mycomponent.js [flags] + +Informs Mozilla about a component CID implemented by an XPCOM component +implemented in JavaScript (or another scripting language, if +applicable). The ClassID {0000...} must match the ClassID implemented by +the component. To generate a unique ClassID, use a UUID generator +program or site. + +contract +~~~~~~~~ + +:: + + contract @foobar/mycontract;1 {00000000-0000-0000-0000-000000000000} [flags] + +Maps a contract ID (a readable string) to the ClassID for a specific +implementation. Typically a contract ID will be paired with a component +entry immediately preceding. + +category +~~~~~~~~ + +:: + + category category entry-name value [flags] + +Registers an entry in the `category manager`. The +specific format and meaning of category entries depend on the category. + +content +~~~~~~~ + +A content package is registered with the line: + +:: + + content packagename uri/to/files/ [flags] + +This will register a location to use when resolving the URI +``chrome://packagename/content/...``. The URI may be absolute or +relative to the location of the manifest file. Note: it must end with a +'/'. + +locale +~~~~~~ + +A locale package is registered with the line: + +.. code:: text + + locale packagename localename uri/to/files/ [flags] + +This will register a locale package when resolving the URI +chrome://*packagename*/locale/... . The *localename* is usually a plain +language identifier "en" or a language-country identifier "en-US". If +more than one locale is registered for a package, the chrome registry +will select the best-fit locale using the user's preferences. + +skin +~~~~ + +A skin package is registered with the line: + +.. code:: text + + skin packagename skinname uri/to/files/ [flags] + +This will register a skin package when resolving the URI +chrome://packagename/skin/... . The *skinname* is an opaque string +identifying an installed skin. If more than one skin is registered for a +package, the chrome registry will select the best-fit skin using the +user's preferences. + +style +~~~~~ + +Style overlays (custom CSS which will be applied to a chrome page) are +registered with the following syntax: + +.. code:: text + + style chrome://URI-to-style chrome://stylesheet-URI [flags] + +override +~~~~~~~~ + +In some cases an extension or embedder may wish to override a chrome +file provided by the application or XULRunner. In order to allow for +this, the chrome registration manifest allows for "override" +instructions: + +.. code:: text + + override chrome://package/type/original-uri.whatever new-resolved-URI [flags] + +Note: overrides are not recursive (so overriding +chrome://foo/content/bar/ with file:///home/john/blah/ will not usually +do what you want or expect it to do). Also, the path inside overridden +files is relative to the overridden path, not the original one (this can +be annoying and/or useful in CSS files, for example). + +.. _chrome_manifest_resource: + +resource +~~~~~~~~ + +Aliases can be created using the ``resource`` instruction: + +.. code:: text + + resource aliasname uri/to/files/ [flags] + +This will create a mapping for ``resource://<aliasname>/`` URIs to the +path given. + +.. note:: + + **Note:** There are no security restrictions preventing web content + from including content at resource: URIs, so take care what you make + visible there. + +Manifest flags +-------------- + +Manifest lines can have multiple, space-delimited flags added at the end +of the registration line. These flags mark special attributes of chrome +in that package, or limit the conditions under which the line is used. + +application +~~~~~~~~~~~ + +Extensions may install into multiple applications. There may be chrome +registration lines which only apply to one particular application. The +flag + +.. code:: text + + application=app-ID + +indicates that the instruction should only be applied if the extension +is installed into the application identified by *app-ID*. Multiple +application flags may be included on a single line, in which case the +line is applied if any of the flags match. + +This example shows how a different overlay can be used for different +applications: + +:: + + overlay chrome://browser/content/browser.xul chrome://myaddon/content/ffOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} + overlay chrome://messenger/content/mailWindowOverlay.xul chrome://myaddon/content/tbOverlay.xul application={3550f703-e582-4d05-9a08-453d09bdfdc6} + overlay chrome://songbird/content/xul/layoutBaseOverlay.xul chrome://myaddon/content/sbOverlay.xul application=songbird@songbirdnest.com + +appversion +~~~~~~~~~~ + +Extensions may install into multiple versions of an application. There +may be chrome registration lines which only apply to a particular +application version. The flag + +.. code:: text + + appversion=version + appversion<version + appversion<=version + appversion>version + appversion>=version + +indicates that the instruction should only be applied if the extension +is installed into the application version identified. Multiple +``appversion`` flags may be included on a single line, in which case the +line is applied if any of the flags match. The version string must +conform to the `Toolkit version format`. + +platformversion +~~~~~~~~~~~~~~~ + +When supporting more then one application, it is often more convenient +for an extension to specify which Gecko version it is compatible with. +This is particularly true for binary components. If there are chrome +registration lines which only apply to a particular Gecko version, the +flag + +.. code:: text + + platformversion=version + platformversion<version + platformversion<=version + platformversion>version + platformversion>=version + +indicates that the instruction should only be applied if the extension +is installed into an application using the Gecko version identified. +Multiple ``platformversion`` flags may be included on a single line, in +which case the line is applied if any of the flags match. + +contentaccessible +~~~~~~~~~~~~~~~~~ + +Chrome resources can no longer be referenced from within <img>, +<script>, or other elements contained in, or added to, content that was +loaded from an untrusted source. This restriction applies to both +elements defined by the untrusted source and to elements added by +trusted extensions. If such references need to be explicitly allowed, +set the ``contentaccessible`` flag to ``yes`` to obtain the behavior +found in older versions of Firefox. See +`bug 436989 <https://bugzilla.mozilla.org/show_bug.cgi?id=436989>`__. + +The ``contentaccessible`` flag applies only to content packages: it is +not recognized for locale or skin registration. However, the matching +locale and skin packages will also be exposed to content. + +**n.b.:** Because older versions of Firefox do not understand the +``contentaccessible`` flag, any extension designed to work with both +Firefox 3 and older versions of Firefox will need to provide a fallback. +For example: + +:: + + content packagename chrome/path/ + content packagename chrome/path/ contentaccessible=yes + +os +~~ + +Extensions (or themes) may offer different features depending on the +operating system on which Firefox is running. The value is compared to +the value of `OS_TARGET` for the platform. + +.. code:: text + + os=WINNT + os=Darwin + +osversion +~~~~~~~~~ + +An extension or theme may need to operate differently depending on which +version of an operating system is running. For example, a theme may wish +to adopt a different look on Mac OS X 10.5 than 10.4: + +.. code:: text + + osversion>=10.5 + +abi +~~~ + +If a component is only compatible with a particular ABI, it can specify +which ABI/OS by using this directive. The value is taken from the +`nsIXULRuntime` OS and +XPCOMABI values (concatenated with an underscore). For example: + +:: + + binary-component component/myLib.dll abi=WINNT_x86-MSVC + binary-component component/myLib.so abi=Linux_x86-gcc3 + +platform (Platform-specific packages) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some packages are marked with a special flag indicating that they are +platform specific. Some parts of content, skin, and locales may be +different based on the platform being run. These packages contain three +different sets of files, for Windows and OS/2, Macintosh, and Unix-like +platforms. For example, the order of the "OK" and "Cancel" buttons in a +dialog is different, as well as the names of some items. + +The "platform" modifier is only parsed for content registration; it is +not recognized for locale or skin registration. However, it applies to +content, locale, and skin parts of the package, when specified. + +process +~~~~~~~ + +In electrolysis registrations can be set to only apply in either the +main process or any content processes. The "process" flag selects +between these two. This can allow you to register different components +for the same contract ID or ensure a component can only be loaded in the +main process. + +:: + + component {09543782-22b1-4a0b-ba07-9134365776ee} maincomponent.js process=main + component {98309951-ac89-4642-afea-7b2b6216bcef} contentcomponent.js process=content + +remoteenabled +~~~~~~~~~~~~~ + +In `multiprocess Firefox`, the +default is that a given chrome: URI will always be loaded into the +chrome process. If you set the "remoteenabled" flag, then the page will +be loaded in the same process as the ``browser`` that loaded it: + +:: + + content packagename chrome/path/ remoteenabled=yes + +remoterequired +~~~~~~~~~~~~~~ + +In `multiprocess Firefox`, the +default is that a given chrome: URI will always be loaded into the +chrome process. If you set the "remoterequired" flag, then the page will +always be loaded into a child process: + +:: + + content packagename chrome/path/ remoterequired=yes + +Example chrome manifest +----------------------- + +.. list-table:: + :widths: 20 20 20 20 + + + * - type + - engine + - language + - url + * - content + - branding + - browser/content/branding/ + - contentaccessible=yes + * - content + - browser + - browser/content/browser/ + - contentaccessible=yes + * - override + - + - chrome://global/content/license.html + - chrome://browser/content/license.html + * - resource + - payments + - browser/res/payments/ + - + * - skin + - browser + - classic/1.0 browser/skin/classic/browser/ + - + * - locale + - branding + - en-US + - en-US/locale/branding/ + * - locale + - browser + - en-US + - en-US/locale/browser/ + * - locale + - browser-region + - en-US + - en-US/locale/browser-region/ diff --git a/build/docs/cppeclipse.rst b/build/docs/cppeclipse.rst new file mode 100644 index 0000000000..920190feb9 --- /dev/null +++ b/build/docs/cppeclipse.rst @@ -0,0 +1,53 @@ +.. _build_cppeclipse: + +===================== +Cpp Eclipse Projects +===================== + +For additional information on using Eclipse CDT see +`the MDN page +<https://developer.mozilla.org/en-US/docs/Eclipse_CDT>`_. + +The build system contains alpha support for generating C++ Eclipse +project files to aid with development. + +Please report bugs to bugzilla and make them depend on bug 973770. + +To generate a C++ Eclipse project files, you'll need to have a fully +built tree:: + + mach build + +Then, simply generate the C++ Eclipse build backend:: + + mach build-backend -b CppEclipse + +If all goes well, the path to the generated workspace should be +printed. + +To use the generated C++ Eclipse project files, you'll need to +have a Eclipse CDT 8.3 (We plan to follow the latest Eclipse release) +`Eclipse CDT plugin +<https://www.eclipse.org/cdt/>`_ +installed. You can then import all the projects into Eclipse using +*File > Import ... > General > Existing Projects into Workspace* +-only- if you have not ran the background indexer. + +Updating Project Files +====================== + +As you pull and update the source tree, your C++ Eclipse files may +fall out of sync with the build configuration. The tree should still +build fine from within Eclipse, but source files may be missing and in +rare circumstances Eclipse's index may not have the proper build +configuration. + +To account for this, you'll want to periodically regenerate the +C++ Eclipse project files. You can do this by running ``mach build +&& mach build-backend -b CppEclipse`` from the +command line. + +Currently, regeneration rewrites the original project files. **If +you've made any customizations to the projects, they will likely get +overwritten.** We would like to improve this user experience in the +future. diff --git a/build/docs/cross-compile.rst b/build/docs/cross-compile.rst new file mode 100644 index 0000000000..b9ab59d8b8 --- /dev/null +++ b/build/docs/cross-compile.rst @@ -0,0 +1,15 @@ +================= +Cross-compilation +================= + +If you are planning to perform cross-compilation e.g. for Linux/Aarch64, you +will probably want to use experimental feature ``--enable-bootstrap`` in your +``.mozconfig``. Then, you just have to specify the the target arch, after which +the build system will automatically set up the sysroot. + +For example, cross-compiling for Linux/Aarch64: + +.. code-block:: text + + ac_add_options --target=aarch64-linux-gnu + ac_add_options --enable-bootstrap diff --git a/build/docs/defining-binaries.rst b/build/docs/defining-binaries.rst new file mode 100644 index 0000000000..fdac27e26a --- /dev/null +++ b/build/docs/defining-binaries.rst @@ -0,0 +1,345 @@ +.. _defining_binaries: + +====================================== +Defining Binaries for the Build System +====================================== + +One part of what the build system does is compile C/C++ and link the resulting +objects to produce executables and/or libraries. This document describes the +basics of defining what is going to be built and how. All the following +describes constructs to use in moz.build files. + + +Source files +============ + +Source files to be used in a given directory are registered in the ``SOURCES`` +and ``UNIFIED_SOURCES`` variables. ``UNIFIED_SOURCES`` have a special behavior +in that they are aggregated by batches of 16, requiring, for example, that there +are no conflicting variables in those source files. + +``SOURCES`` and ``UNIFIED_SOURCES`` are lists which must be appended to, and +each append requires the given list to be alphanumerically ordered. + +.. code-block:: python + + UNIFIED_SOURCES += [ + 'FirstSource.cpp', + 'SecondSource.cpp', + 'ThirdSource.cpp', + ] + + SOURCES += [ + 'OtherSource.cpp', + ] + +``SOURCES`` and ``UNIFIED_SOURCES`` can contain a mix of different file types, +for C, C++, and Objective C. + + +Static Libraries +================ + +To build a static library, other than defining the source files (see above), one +just needs to define a library name with the ``Library`` template. + +.. code-block:: python + + Library('foo') + +The library file name will be ``libfoo.a`` on UNIX systems and ``foo.lib`` on +Windows. + +If the static library needs to aggregate other static libraries, a list of +``Library`` names can be added to the ``USE_LIBS`` variable. Like ``SOURCES``, it +requires the appended list to be alphanumerically ordered. + +.. code-block:: python + + USE_LIBS += ['bar', 'baz'] + +If there are multiple directories containing the same ``Library`` name, it is +possible to disambiguate by prefixing with the path to the wanted one (relative +or absolute): + +.. code-block:: python + + USE_LIBS += [ + '/path/from/topsrcdir/to/bar', + '../relative/baz', + ] + +Note that the leaf name in those paths is the ``Library`` name, not an actual +file name. + +Note that currently, the build system may not create an actual library for +static libraries. It is an implementation detail that shouldn't need to be +worried about. + +As a special rule, ``USE_LIBS`` is allowed to contain references to shared +libraries. In such cases, programs and shared libraries linking this static +library will inherit those shared library dependencies. + + +Intermediate (Static) Libraries +=============================== + +In many cases in the tree, static libraries are built with the only purpose +of being linked into another, bigger one (like libxul). Instead of adding all +required libraries to ``USE_LIBS`` for the bigger one, it is possible to tell +the build system that the library built in the current directory is meant to +be linked to that bigger library, with the ``FINAL_LIBRARY`` variable. + +.. code-block:: python + + FINAL_LIBRARY = 'xul' + +The ``FINAL_LIBRARY`` value must match a unique ``Library`` name somewhere +in the tree. + +As a special rule, those intermediate libraries don't need a ``Library`` name +for themselves. + + +Shared Libraries +================ + +Sometimes, we want shared libraries, a.k.a. dynamic libraries. Such libraries +are defined similarly to static libraries, using the ``SharedLibrary`` template +instead of ``Library``. + +.. code-block:: python + + SharedLibrary('foo') + +When this template is used, no static library is built. See further below to +build both types of libraries. + +With a ``SharedLibrary`` name of ``foo``, the library file name will be +``libfoo.dylib`` on OSX, ``libfoo.so`` on ELF systems (Linux, etc.), and +``foo.dll`` on Windows. On Windows, there is also an import library named +``foo.lib``, used on the linker command line. ``libfoo.dylib`` and +``libfoo.so`` are considered the import library name for, resp. OSX and ELF +systems. + +On OSX, one may want to create a special kind of dynamic library: frameworks. +This is done with the ``Framework`` template. + +.. code-block:: python + + Framework('foo') + +With a ``Framework`` name of ``foo``, the framework file name will be ``foo``. +This template however affects the behavior on all platforms, so it needs to +be set only on OSX. + + +Executables +=========== + +Executables, a.k.a. programs, are, in the simplest form, defined with the +``Program`` template. + +.. code-block:: python + + Program('foobar') + +On UNIX systems, the executable file name will be ``foobar``, while on Windows, +it will be ``foobar.exe``. + +Like static and shared libraries, the build system can be instructed to link +libraries to the executable with ``USE_LIBS``, listing various ``Library`` +names. + +In some cases, we want to create an executable per source file in the current +directory, in which case we can use the ``SimplePrograms`` template + +.. code-block:: python + + SimplePrograms([ + 'FirstProgram', + 'SecondProgram', + ]) + +Contrary to ``Program``, which requires corresponding ``SOURCES``, when using +``SimplePrograms``, the corresponding ``SOURCES`` are implied. If the +corresponding ``sources`` have an extension different from ``.cpp``, it is +possible to specify the proper extension: + +.. code-block:: python + + SimplePrograms([ + 'ThirdProgram', + 'FourthProgram', + ], ext='.c') + +Please note this construct was added for compatibility with what already lives +in the mozilla tree ; it is recommended not to add new simple programs with +sources with a different extension than ``.cpp``. + +Similar to ``SimplePrograms``, is the ``CppUnitTests`` template, which defines, +with the same rules, C++ unit tests programs. Like ``SimplePrograms``, it takes +an ``ext`` argument to specify the extension for the corresponding ``SOURCES``, +if it's different from ``.cpp``. + + +Linking with system libraries +============================= + +Programs and libraries usually need to link with system libraries, such as a +widget toolkit, etc. Those required dependencies can be given with the +``OS_LIBS`` variable. + +.. code-block:: python + + OS_LIBS += [ + 'foo', + 'bar', + ] + +This expands to ``foo.lib bar.lib`` when building with MSVC, and +``-lfoo -lbar`` otherwise. + +For convenience with ``pkg-config``, ``OS_LIBS`` can also take linker flags +such as ``-L/some/path`` and ``-llib``, such that it is possible to directly +assign ``LIBS`` variables from ``CONFIG``, such as: + +.. code-block:: python + + OS_LIBS += CONFIG['MOZ_PANGO_LIBS'] + +(assuming ``CONFIG['MOZ_PANGO_LIBS']`` is a list, not a string) + +Like ``USE_LIBS``, this variable applies to static and shared libraries, as +well as programs. + + +Libraries from third party build system +======================================= + +Some libraries in the tree are not built by the moz.build-governed build +system, and there is no ``Library`` corresponding to them. + +However, ``USE_LIBS`` allows to reference such libraries by giving a full +path (like when disambiguating identical ``Library`` names). The same naming +rules apply as other uses of ``USE_LIBS``, so only the library name without +prefix and suffix shall be given. + +.. code-block:: python + + USE_LIBS += [ + '/path/from/topsrcdir/to/third-party/bar', + '../relative/third-party/baz', + ] + +Note that ``/path/from/topsrcdir/to/third-party`` and +``../relative/third-party/baz`` must lead under a subconfigured directory (a +directory with an AC_OUTPUT_SUBDIRS in configure.in), or ``security/nss``. + + +Building both static and shared libraries +========================================= + +When both types of libraries are required, one needs to set both +``FORCE_SHARED_LIB`` and ``FORCE_STATIC_LIB`` boolean variables. + +.. code-block:: python + + FORCE_SHARED_LIB = True + FORCE_STATIC_LIB = True + +But because static libraries and Windows import libraries have the same file +names, either the static or the shared library name needs to be different +than the name given to the ``Library`` template. + +The ``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME`` variables can be used +to change either the static or the shared library name. + +.. code-block:: python + + Library('foo') + STATIC_LIBRARY_NAME = 'foo_s' + +With the above, on Windows, ``foo_s.lib`` will be the static library, +``foo.dll`` the shared library, and ``foo.lib`` the import library. + +In some cases, for convenience, it is possible to set both +``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME``. For example: + +.. code-block:: python + + Library('mylib') + STATIC_LIBRARY_NAME = 'mylib_s' + SHARED_LIBRARY_NAME = CONFIG['SHARED_NAME'] + +This allows to use ``mylib`` in the ``USE_LIBS`` of another library or +executable. + +When referring to a ``Library`` name building both types of libraries in +``USE_LIBS``, the shared library is chosen to be linked. But sometimes, +it is wanted to link the static version, in which case the ``Library`` name +needs to be prefixed with ``static:`` in ``USE_LIBS`` + +:: + + a/moz.build: + Library('mylib') + FORCE_SHARED_LIB = True + FORCE_STATIC_LIB = True + STATIC_LIBRARY_NAME = 'mylib_s' + b/moz.build: + Program('myprog') + USE_LIBS += [ + 'static:mylib', + ] + + +Miscellaneous +============= + +The ``SONAME`` variable declares a "shared object name" for the library. It +defaults to the ``Library`` name or the ``SHARED_LIBRARY_NAME`` if set. When +linking to a library with a ``SONAME``, the resulting library or program will +have a dependency on the library with the name corresponding to the ``SONAME`` +instead of the ``Library`` name. This only impacts ELF systems. + +:: + + a/moz.build: + Library('mylib') + b/moz.build: + Library('otherlib') + SONAME = 'foo' + c/moz.build: + Program('myprog') + USE_LIBS += [ + 'mylib', + 'otherlib', + ] + +On e.g. Linux, the above ``myprog`` will have DT_NEEDED markers for +``libmylib.so`` and ``libfoo.so`` instead of ``libmylib.so`` and +``libotherlib.so`` if there weren't a ``SONAME``. This means the runtime +requirement for ``myprog`` is ``libfoo.so`` instead of ``libotherlib.so``. + + +Gecko-related binaries +====================== + +Some programs or libraries are totally independent of Gecko, and can use the +above mentioned templates. Others are Gecko-related in some way, and may +need XPCOM linkage, mozglue. These things are tedious. A set of additional +templates exists to ease defining such programs and libraries. They are +essentially the same as the above mentioned templates, prefixed with "Gecko": + + - ``GeckoProgram`` + - ``GeckoSimplePrograms`` + - ``GeckoCppUnitTests`` + - ``GeckoSharedLibrary`` + - ``GeckoFramework`` + +All the Gecko-prefixed templates take the same arguments as their +non-Gecko-prefixed counterparts, and can take a few more arguments +for non-standard cases. See the definition of ``GeckoBinary`` in +build/gecko_templates.mozbuild for more details, but most usecases +should not require these additional arguments. diff --git a/build/docs/defining-xpcom-components.rst b/build/docs/defining-xpcom-components.rst new file mode 100644 index 0000000000..8e4f66c9c0 --- /dev/null +++ b/build/docs/defining-xpcom-components.rst @@ -0,0 +1,318 @@ +.. _defining_xpcom_components: + +========================= +Defining XPCOM Components +========================= + +This document explains how to write a :code:`components.conf` file. For +documentation on the idl format see :ref:`XPIDL`. For a tutorial on writing +a new XPCOM interface, see +:ref:`writing_xpcom_interface`. + +Native XPCOM components are registered at build time, and compiled into static +data structures which allow them to be accessed with little runtime overhead. +Each module which wishes to register components must provide a manifest +describing each component it implements, its type, and how it should be +constructed. + +Manifest files are Python data files registered in ``moz.build`` files in a +``XPCOM_MANIFESTS`` file list: + +.. code-block:: python + + XPCOM_MANIFESTS += [ + 'components.conf', + ] + +The files may define any of the following special variables: + +.. code-block:: python + + # Optional: A function to be called once, the first time any component + # listed in this manifest is instantiated. + InitFunc = 'nsInitFooModule' + # Optional: A function to be called at shutdown if any component listed in + # this manifest has been instantiated. + UnloadFunc = 'nsUnloadFooModule' + + # Optional: A processing priority, to determine how early or late the + # manifest is processed. Defaults to 50. In practice, this mainly affects + # the order in which unload functions are called at shutdown, with higher + # priority numbers being called later. + Priority = 10 + + # Optional: A list of header files to include before calling init or + # unload functions, or any legacy constructor functions. + # + # Any header path beginning with a `/` is loaded relative to the root of + # the source tree, and must not rely on any local includes. + # + # Any relative header path must be exported. + Headers = [ + '/foo/nsFooModule.h', + 'nsFoo.h', + ] + + # A list of component classes provided by this module. + Classes = [ + { + # ... + }, + # ... + ] + + # A list of category registrations + Categories = { + 'category': { + 'name': 'value', + 'other-name': ('value', ProcessSelector.MAIN_PROCESS_ONLY), + # ... + }, + # ... + } + +Class definitions may have the following properties: + +``name`` (optional) + If present, this component will generate an entry with the given name in the + ``mozilla::components`` namespace in ``mozilla/Components.h``, which gives + easy access to its CID, service, and instance constructors as (e.g.,) + ``components::Foo::CID()``, ``components::Foo::Service()``, and + ``components::Foo::Create()``, respectively. + +``cid`` + A UUID string containing this component's CID, in the form + ``'{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}'``. + +``contract_ids`` (optional) + A list of contract IDs to register for this class. + +``categories`` (optional) + A dict of category entries to register for this component's contract ID. + Each key in the dict is the name of the category. Each value is either a + string containing a single entry, or a list of entries. Each entry is either + a string name, or a dictionary of the form ``{'name': 'value', 'backgroundtasks': + BackgroundTasksSelector.ALL_TASKS}``. By default, category entries are registered + for **no background tasks**: they have + ``'backgroundtasks': BackgroundTasksSelector.NO_TASKS``. + +``type`` (optional, default=``nsISupports``) + The fully-qualified type of the class implementing this component. Defaults + to ``nsISupports``, but **must** be provided if the ``init_method`` property + is specified, or if neither the ``constructor`` nor ``legacy_constructor`` + properties are provided. + +``headers`` (optional) + A list of headers to include in order to call this component's constructor, + in the same format as the global ``Headers`` property. + +``init_method`` (optional) + The name of a method to call on newly-created instances of this class before + returning them. The method must take no arguments, and must return a + ``nsresult``. If it returns failure, that failure is propagated to the + ``getService`` or ``createInstance`` caller. + +``constructor`` (optional) + The fully-qualified name of a constructor function to call in order to + create instances of this class. This function must be declared in one of the + headers listed in the ``headers`` property, must take no arguments, and must + return ``already_AddRefed<iface>`` where ``iface`` is the interface provided + in the ``type`` property. + + This property is incompatible with ``legacy_constructor``. + +``esModule`` (optional) + If provided, must be the URL of a + `JavaScript module <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules>`_ + which contains a JavaScript implementation of the component. + The ``constructor`` property must contain the name of an exported + function which can be constructed to create a new instance of the component. + + +``jsm`` (deprecated, optional) + Do not use. Use ``esModule`` instead. + +``legacy_constructor`` (optional) + This property is deprecated, and should not be used in new code. + + The fully-qualified name of a constructor function to call in order to + create instances of this class. This function must be declared in one of the + headers listed in the ``headers`` property, and must have the signature + ``nsresult(const nsID& aIID, void** aResult)``, and behave equivalently to + ``nsIFactory::CreateInstance``. + + This property is incompatible with ``constructor``. + +``singleton`` (optional, default=``False``) + If true, this component's constructor is expected to return the same + singleton for every call, and no ``mozilla::components::<name>::Create()`` + method will be generated for it. + +``overridable`` (optional, default=``False``) + If true, this component's contract ID is expected to be overridden by some + tests, and its ``mozilla::components::<name>::Service()`` getter will + therefore look it up by contract ID for every call. This component must, + therefore, provide at least one contract ID in its ``contract_ids`` array. + + If false, the ``Service()`` getter will always retrieve the service based on + its static data, and it cannot be overridden. + + Note: Enabling this option is expensive, and should not be done when it can + be avoided, or when the getter is used by any hot code. + +``external`` (optional, default=``False`` if any ``headers`` are provided, ``True`` otherwise) + If true, a constructor for this component's ``type`` must be defined in + another translation unit, using ``NS_IMPL_COMPONENT_FACTORY(type)``. The + constructor must return an ``already_AddRefed<nsISupports>``, and will be + used to construct instances of this type. + + This option should only be used in cases where the headers which define the + component's concrete type cannot be easily included without local includes. + + Note: External constructors may not specify an ``init_method``, since the + generated code will not have the necessary type information required to call + it. This option is also incompatible with ``constructor`` and + ``legacy_constructor``. + +``processes`` (optional, default=``ProcessSelector.ANY_PROCESS``) + An optional specifier restricting which types of process this component may + be loaded in. This must be a property of ``ProcessSelector`` with the same + name as one of the values in the ``Module::ProcessSelector`` enum. + + +Conditional Compilation +======================= + +This manifest may run any appropriate Python code to customize the values of +the ``Classes`` array based on build configuration. To simplify this process, +the following globals are available: + +``defined`` + A function which returns true if the given build config setting is defined + and true. + +``buildconfig`` + The ``buildconfig`` python module, with a ``substs`` property containing a + dict of all available build substitutions. + + +Component Constructors +====================== + +There are several ways to define component constructors, which vary mostly +depending on how old the code that uses them is: + +Class Constructors +------------------ + +This simplest way to define a component is to include a header defining a +concrete type, and let the component manager call that class's constructor: + +.. code-block:: python + + 'type': 'mozilla::foo::Foo', + 'headers': ['mozilla/Foo.h'], + +This is generally the preferred method of defining non-singleton constructors, +but may not be practicable for classes which rely on local includes for their +definitions. + +Singleton Constructors +---------------------- + +Singleton classes are generally expected to provide their own constructor +function which caches a singleton instance the first time it is called, and +returns the same instance on subsequent calls. This requires declaring the +constructor in an included header, and implementing it in a separate source +file: + +.. code-block:: python + + 'type': 'mozilla::foo::Foo', + 'headers': ['mozilla/Foo.h'], + 'constructor': 'mozilla::Foo::GetSingleton', + +``Foo.h`` + +.. code-block:: cpp + + class Foo final : public nsISupports { + public: + static already_AddRefed<Foo> GetSingleton(); + }; + +``Foo.cpp`` + +.. code-block:: cpp + + already_AddRefed<Foo> Foo::GetSingleton() { + // ... + } + +External Constructors +--------------------- + +For types whose headers can't easily be included, constructors can be defined +using a template specialization on an incomplete type: + +.. code-block:: python + + 'type': 'mozilla::foo::Foo', + 'external: True,' + +``Foo.cpp`` + +.. code-block:: cpp + + NS_IMPL_COMPONENT_FACTORY(Foo) { + return do_AddRef(new Foo()).downcast<nsISupports>(); + } + +Legacy Constructors +------------------- + +These should not be used in new code, and are left as an exercise for the +reader. + + +Registering Categories +====================== + +Classes which need define category entries with the same value as their +contract ID may do so using the following: + +.. code-block:: python + + 'contract_ids': ['@mozilla.org/foo;1'], + 'categories': { + 'content-policy': 'm-foo', + 'Gecko-Content-Viewers': ['image/jpeg', 'image/png'], + }, + +This will define each of the following category entries: + +* ``"content-policy"`` ``"m-foo",`` ``"@mozilla.org/foo;1"`` +* ``"Gecko-Content-Viewers"`` ``"image/jpeg"`` ``"@mozilla.org/foo;1"`` +* ``"Gecko-Content-Viewers"`` ``"image/png"`` ``"@mozilla.org/foo;1"`` + +Some category entries do not have a contract ID as a value. These entries can +be specified by adding to a global ``Categories`` dictionary: + +.. code-block:: python + + Categories = { + 'update-timer': { + 'nsUpdateService': '@mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,43200,86400', + } + } + +It is possible to limit these on a per-process basis by using a tuple as the +value: + +.. code-block:: python + + Categories = { + '@mozilla.org/streamconv;1': { + '?from=gzip&to=uncompressed': ('', ProcessSelector.ALLOW_IN_SOCKET_PROCESS), + } + } diff --git a/build/docs/environment-variables.rst b/build/docs/environment-variables.rst new file mode 100644 index 0000000000..c463391596 --- /dev/null +++ b/build/docs/environment-variables.rst @@ -0,0 +1,31 @@ +.. _environment_variables: + +================================================ +Environment Variables Impacting the Build System +================================================ + +Various environment variables have an impact on the behavior of the +build system. This document attempts to document them. + +AUTOCLOBBER + If defines, the build system will automatically clobber as needed. + The default behavior is to print a message and error out when a + clobber is needed. + + This variable is typically defined in a :ref:`mozconfig <mozconfig>` + file via ``mk_add_options``. + +REBUILD_CHECK + If defined, the build system will print information about why + certain files were rebuilt. + + This feature is disabled by default because it makes the build slower. + +MACH_NO_TERMINAL_FOOTER + If defined, the terminal footer displayed when building with mach in + a TTY is disabled. + +MACH_NO_WRITE_TIMES + If defined, mach commands will not prefix output lines with the + elapsed time since program start. This option is equivalent to + passing ``--log-no-times`` to mach. diff --git a/build/docs/files-metadata.rst b/build/docs/files-metadata.rst new file mode 100644 index 0000000000..6a7290c55e --- /dev/null +++ b/build/docs/files-metadata.rst @@ -0,0 +1,178 @@ +.. _mozbuild_files_metadata: + +============== +Files Metadata +============== + +:ref:`mozbuild-files` provide a mechanism for attaching metadata to +files. Essentially, you define some flags to set on a file or file +pattern. Later, some tool or process queries for metadata attached to a +file of interest and it does something intelligent with that data. + +Defining Metadata +================= + +Files metadata is defined by using the +:ref:`Files Sub-Context <mozbuild_subcontext_Files>` in ``moz.build`` +files. e.g.:: + + with Files('**/Makefile.in'): + BUG_COMPONENT = ('Firefox Build System', 'General') + +This working example says, *for all Makefile.in files in every directory +underneath this one - including this directory - set the Bugzilla +component to Firefox Build System :: General*. + +For more info, read the +:ref:`docs on Files <mozbuild_subcontext_Files>`. + +How Metadata is Read +==================== + +``Files`` metadata is extracted in :ref:`mozbuild_fs_reading_mode`. + +Reading starts by specifying a set of files whose metadata you are +interested in. For each file, the filesystem is walked to the root +of the source directory. Any ``moz.build`` encountered during this +walking are marked as relevant to the file. + +Let's say you have the following filesystem content:: + + /moz.build + /root_file + /dir1/moz.build + /dir1/foo + /dir1/subdir1/foo + /dir2/foo + +For ``/root_file``, the relevant ``moz.build`` files are just +``/moz.build``. + +For ``/dir1/foo`` and ``/dir1/subdir1/foo``, the relevant files are +``/moz.build`` and ``/dir1/moz.build``. + +For ``/dir2``, the relevant file is just ``/moz.build``. + +Once the list of relevant ``moz.build`` files is obtained, each +``moz.build`` file is evaluated. Root ``moz.build`` file first, +leaf-most files last. This follows the rules of +:ref:`mozbuild_fs_reading_mode`, with the set of evaluated ``moz.build`` +files being controlled by filesystem content, not ``DIRS`` variables. + +The file whose metadata is being resolved maps to a set of ``moz.build`` +files which in turn evaluates to a list of contexts. For file metadata, +we only care about one of these contexts: +:ref:`Files <mozbuild_subcontext_Files>`. + +We start with an empty ``Files`` instance to represent the file. As +we encounter a *files sub-context*, we see if it is appropriate to +this file. If it is, we apply its values. This process is repeated +until all *files sub-contexts* have been applied or skipped. The final +state of the ``Files`` instance is used to represent the metadata for +this particular file. + +It may help to visualize this. Say we have 2 ``moz.build`` files:: + + # /moz.build + with Files('*.cpp'): + BUG_COMPONENT = ('Core', 'XPCOM') + + with Files('**/*.js'): + BUG_COMPONENT = ('Firefox', 'General') + + # /foo/moz.build + with Files('*.js'): + BUG_COMPONENT = ('Another', 'Component') + +Querying for metadata for the file ``/foo/test.js`` will reveal 3 +relevant ``Files`` sub-contexts. They are evaluated as follows: + +1. ``/moz.build - Files('*.cpp')``. Does ``/*.cpp`` match + ``/foo/test.js``? **No**. Ignore this context. +2. ``/moz.build - Files('**/*.js')``. Does ``/**/*.js`` match + ``/foo/test.js``? **Yes**. Apply ``BUG_COMPONENT = ('Firefox', 'General')`` + to us. +3. ``/foo/moz.build - Files('*.js')``. Does ``/foo/*.js`` match + ``/foo/test.js``? **Yes**. Apply + ``BUG_COMPONENT = ('Another', 'Component')``. + +At the end of execution, we have +``BUG_COMPONENT = ('Another', 'Component')`` as the metadata for +``/foo/test.js``. + +One way to look at file metadata is as a stack of data structures. +Each ``Files`` sub-context relevant to a given file is applied on top +of the previous state, starting from an empty state. The final state +wins. + +.. _mozbuild_files_metadata_finalizing: + +Finalizing Values +================= + +The default behavior of ``Files`` sub-context evaluation is to apply new +values on top of old. In most circumstances, this results in desired +behavior. However, there are circumstances where this may not be +desired. There is thus a mechanism to *finalize* or *freeze* values. + +Finalizing values is useful for scenarios where you want to prevent +wildcard matches from overwriting previously-set values. This is useful +for one-off files. + +Let's take ``Makefile.in`` files as an example. The build system module +policy dictates that ``Makefile.in`` files are part of the ``Build +Config`` module and should be reviewed by peers of that module. However, +there exist ``Makefile.in`` files in many directories in the source +tree. Without finalization, a ``*`` or ``**`` wildcard matching rule +would match ``Makefile.in`` files and overwrite their metadata. + +Finalizing of values is performed by setting the ``FINAL`` variable +on ``Files`` sub-contexts. See the +:ref:`Files documentation <mozbuild_subcontext_Files>` for more. + +Here is an example with ``Makefile.in`` files, showing how it is +possible to finalize the ``BUG_COMPONENT`` value.:: + + # /moz.build + with Files('**/Makefile.in'): + BUG_COMPONENT = ('Firefox Build System', 'General') + FINAL = True + + # /foo/moz.build + with Files('**'): + BUG_COMPONENT = ('Another', 'Component') + +If we query for metadata of ``/foo/Makefile.in``, both ``Files`` +sub-contexts match the file pattern. However, since ``BUG_COMPONENT`` is +marked as finalized by ``/moz.build``, the assignment from +``/foo/moz.build`` is ignored. The final value for ``BUG_COMPONENT`` +is ``('Firefox Build System', 'General')``. + +Here is another example:: + + with Files('*.cpp'): + BUG_COMPONENT = ('One-Off', 'For C++') + FINAL = True + + with Files('**'): + BUG_COMPONENT = ('Regular', 'Component') + +For every files except ``foo.cpp``, the bug component will be resolved +as ``Regular :: Component``. However, ``foo.cpp`` has its value of +``One-Off :: For C++`` preserved because it is finalized. + +.. important:: + + ``FINAL`` only applied to variables defined in a context. + + If you want to mark one variable as finalized but want to leave + another mutable, you'll need to use 2 ``Files`` contexts. + +Guidelines for Defining Metadata +================================ + +In general, values defined towards the root of the source tree are +generic and become more specific towards the leaves. For example, +the ``BUG_COMPONENT`` for ``/browser`` might be ``Firefox :: General`` +whereas ``/browser/components/preferences`` would list +``Firefox :: Preferences``. diff --git a/build/docs/glossary.rst b/build/docs/glossary.rst new file mode 100644 index 0000000000..d610f07443 --- /dev/null +++ b/build/docs/glossary.rst @@ -0,0 +1,47 @@ +Build Glossary +============== + +.. glossary:: + :sorted: + + object directory + A directory holding the output of the build system. The build + system attempts to isolate all file modifications to this + directory. By convention, object directories are commonly + directories under the source directory prefixed with **obj-**. + e.g. **obj-firefox**. + + mozconfig + A shell script used to configure the build system. + + configure + A generated shell script which detects the current system + environment, applies a requested set of build configuration + options, and writes out metadata to be consumed by the build + system. + + config.status + An executable file produced by **configure** that takes the + generated build config and writes out files used to build the + tree. Traditionally, config.status writes out a bunch of + Makefiles. + + install manifest + A file containing metadata describing file installation rules. + A large part of the build system consists of copying files + around to appropriate places. We write out special files + describing the set of required operations so we can process the + actions efficiently. These files are install manifests. + + clobber build + A build performed with an initially empty object directory. All + build actions must be performed. + + incremental build + A build performed with the result of a previous build in an + object directory. The build should not have to work as hard because + it will be able to reuse the work from previous builds. + + mozinfo + An API for accessing a common and limited subset of the build and + run-time configuration. See :ref:`mozinfo`. diff --git a/build/docs/gn.rst b/build/docs/gn.rst new file mode 100644 index 0000000000..2a8c769130 --- /dev/null +++ b/build/docs/gn.rst @@ -0,0 +1,17 @@ +.. _gn: + +============================== +GN support in the build system +============================== + +:abbr:`GN (Generated Ninja)` is a third-party build tool used by chromium and +some related projects that are vendored in mozilla-central. Rather than +requiring ``GN`` to build or writing our own build definitions for these projects, +we have support in the build system for translating GN configuration +files into moz.build files. In most cases these moz.build files will be like any +others in the tree (except that they shouldn't be modified by hand), however +those updating vendored code or building on platforms not supported by +Mozilla automation may need to re-generate these files. This is a per-project +process, described in dom/media/webrtc/third_party_build/gn-configs/README.md for +webrtc. As of writing, it is very specific to webrtc, and likely doesn't work as-is +for other projects. diff --git a/build/docs/index.rst b/build/docs/index.rst new file mode 100644 index 0000000000..4fee23359d --- /dev/null +++ b/build/docs/index.rst @@ -0,0 +1,66 @@ +============ +Build System +============ + +Important Concepts +================== +.. toctree:: + :maxdepth: 1 + + glossary + build-overview + supported-configurations + Mozconfig Files <mozconfigs> + mozbuild-files + mozbuild-symbols + files-metadata + Profile Guided Optimization <pgo> + slow + environment-variables + build-targets + python + test_manifests + mozinfo + preprocessor + jar-manifests + defining-binaries + defining-xpcom-components + toolchains + locales + unified-builds + cross-compile + rust + sparse + Support for projects building with GN <gn> + telemetry + sccache-dist + test_certificates + +integrated development environment (IDE) +======================================== +.. toctree:: + :maxdepth: 1 + + cppeclipse + visualstudio + +mozbuild +======== + +mozbuild is a Python package containing a lot of the code for the +Mozilla build system. + +.. toctree:: + :maxdepth: 1 + + mozbuild/index + +Snap Package +============ + +`Snap <https://snapcraft.io/docs>`_ is a packaging format + +.. toctree:: + :maxdepth: 1 + + snap diff --git a/build/docs/jar-manifests.rst b/build/docs/jar-manifests.rst new file mode 100644 index 0000000000..b6b1be781c --- /dev/null +++ b/build/docs/jar-manifests.rst @@ -0,0 +1,123 @@ +.. _jar_manifests: + +============= +JAR Manifests +============= + +JAR Manifests are plaintext files in the tree that are used to package chrome +files into ``.jar`` files and create :ref:`Chrome Registration <Chrome Registration>` +manifests. JAR Manifests are commonly named ``jar.mn``. They are declared in ``moz.build`` files using the ``JAR_MANIFESTS`` variable, which makes up a collection of ``jar.mn`` files. +All files declared in JAR Manifests are processed and installed into ``omni.ja`` files in ``browser/`` and ``toolkit/`` when building Firefox. + +``jar.mn`` files are automatically processed by the build system when building a +source directory that contains one. The ``jar.mn`` is run through the +:ref:`preprocessor` before being passed to the manifest processor. In order to +have ``@variables@`` expanded (such as ``@AB_CD@``) throughout the file, add +the line ``#filter substitution`` at the top of your ``jar.mn`` file. + +The format of a jar.mn is fairly simple; it consists of a heading specifying +which JAR file is being packaged, followed by indented lines listing files and +chrome registration instructions. + +For a simple ``jar.mn`` file, see `toolkit/profile/jar.mn <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/toolkit/profile/jar.mn>`_. For a much +more complex ``jar.mn`` file, see `toolkit/locales/jar.mn <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/toolkit/locales/jar.mn>`_. More examples with specific formats and uses are available below. + +Shipping Chrome Files +====================== +General Format +^^^^^^^^^^^^^^ +To ship chrome files in a JAR, an indented line indicates a file to be packaged:: + + <jarfile>.jar: + path/in/jar/file_name.xul (source/tree/location/file_name.xul) + +Note that file path mappings are listed by destination (left) followed by source (right). + +Same Directory Omission +^^^^^^^^^^^^^^^^^^^^^^^ +If the JAR manifest and packaged files live in the same directory, the source path and parentheses can be omitted. +A sample of a ``jar.mn`` file with omitted source paths and parentheses is `this revision of browser/components/colorways/jar.mn <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/browser/components/colorways/jar.mn>`_:: + + browser.jar: + content/browser/colorwaycloset.html + content/browser/colorwaycloset.css + content/browser/colorwaycloset.js + +Writing the following is equivalent, given that the aforementioned files exist in the same directory as the ``jar.mn``. Notice the ``.jar`` file is named ``browser.jar``:: + + browser.jar: + content/browser/colorwaycloset.html (colorwaycloset.html) + content/browser/colorwaycloset.css (colorwaycloset.css) + content/browser/colorwaycloset.js (colorwaycloset.js) + +This manifest is responsible for packaging files needed by Colorway Closet, including +JS scripts, localization files, images (ex. PNGs, AVIFs), and CSS styling. Look at `browser/components/colorways/colorwaycloset.html <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/browser/components/colorways/colorwaycloset.html#18>`_ +to see how a file may be referenced using its chrome URL. + +Absolute Paths +^^^^^^^^^^^^^^ +The source tree location may also be an absolute path (taken from the top of the source tree). +One such example can be found in `toolkit/components/pictureinpicture/jar.mn <https://searchfox.org/mozilla-central/rev/2005e8d87ee045f19dac58e5bff32eff7d01bc9b/toolkit/components/pictureinpicture/jar.mn>`_:: + + toolkit.jar: + * content/global/pictureinpicture/player.xhtml (content/player.xhtml) + content/global/pictureinpicture/player.js (content/player.js) + +Asterisk Marker (Preprocessing) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +An asterisk marker (``*``) at the beginning of the line indicates that the file should be processed by the :ref:`preprocessor` before being packaged. +The file `toolkit/profile/jar.mn <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/toolkit/profile/jar.mn>`_ indicates that the file `toolkit/profile/content/profileDowngrade.xhtml <https://searchfox.org/mozilla-central/rev/2005e8d87ee045f19dac58e5bff32eff7d01bc9b/toolkit/profile/content/profileDowngrade.xhtml#34,36>`_ should be +run through the preprocessor, since it contains ``#ifdef`` and ``#endif`` statements that need to be interpreted:: + + * content/mozapps/profile/profileDowngrade.xhtml (content/profileDowngrade.xhtml) + +Base Path, Variables, Wildcards and Localized Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The ``.jar`` file location may be preceded with a base path between square brackets. +The file `toolkit/locales/jar.mn <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/toolkit/locales/jar.mn>`_ uses a base path so that the ``.jar`` file is under a ``localization`` directory, +which is a `special directory parsed by mozbuild <https://searchfox.org/mozilla-central/rev/2005e8d87ee045f19dac58e5bff32eff7d01bc9b/python/mozbuild/mozpack/packager/l10n.py#260-265>`_. + +It is also named according to the value passed by the variable ``@AB_CD@``, normally a locale. Note the use of the preprocessor directive ``#filter substitution`` at the top of the file for replacing the variable with the value:: + + #filter substitution + + ... + + [localization] @AB_CD@.jar: + crashreporter (%crashreporter/**/*.ftl) + toolkit (%toolkit/**/*.ftl) + +The percentage sign in front of the source paths designates the locale to target as a source. By default, this is ``en-US``. With this specific example, `/toolkit/locales/en-US <https://searchfox.org/mozilla-central/source/toolkit/locales/en-US>`_ would be targeted. +Otherwise, the file from an alternate localization source tree ``/l10n/<locale>/toolkit/`` is read if building a localized version. +The wildcards in ``**/*.ftl`` tell the processor to install all Fluent files within the ``crashreporter`` and ``toolkit`` directories, as well as their subdirectories. + +Registering Chrome +================== + +:ref:`Chrome Registration <Chrome Registration>` instructions are marked with a percent sign (``%``) at the beginning of the +line, and must be part of the definition of a JAR file. Any additional percents +signs are replaced with an appropriate relative URL of the JAR file being +packaged. + +There are two possible locations for a manifest file. If the chrome is being +built into a standalone application, the ``jar.mn`` processor creates a +``<jarfilename>.manifest`` next to the JAR file itself. This is the default +behavior. + +If the ``moz.build`` specifies ``USE_EXTENSION_MANIFEST = 1``, the ``jar.mn`` processor +creates a single ``chrome.manifest`` file suitable for registering chrome as +an extension. + +Example +^^^^^^^ + +The file `browser/themes/addons/jar.mn <https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/browser/themes/addons/jar.mn>`_ registers a ``resource`` chrome package under the name ``builtin-themes``. Its source files are in ``%content/builtin-themes/``:: + + browser.jar: + % resource builtin-themes %content/builtin-themes/ + + content/builtin-themes/alpenglow (alpenglow/*.svg) + content/builtin-themes/alpenglow/manifest.json (alpenglow/manifest.json) + +Notice how other files declare an installation destination using the ``builtin-themes`` resource that is defined. As such, a SVG file ``preview.svg`` for a theme ``Alpenglow`` may be loaded using the resource URL ``resource://builtin-themes/alpenglow/preview.svg`` +so that a preview of the theme is available on ``about:addons``. See :ref:`Chrome Registration <Chrome Registration>` for more details on ``resource`` and other manifest instructions. diff --git a/build/docs/locales.rst b/build/docs/locales.rst new file mode 100644 index 0000000000..07b9728353 --- /dev/null +++ b/build/docs/locales.rst @@ -0,0 +1,368 @@ +.. _localization: + +================ +Localized Builds +================ + +Localization repacks +==================== + +To save on build time, the build system and automation collaborate to allow +downloading a packaged en-US Firefox, performing some locale-specific +post-processing, and re-packaging a locale-specific Firefox. Such artifacts +are termed "single-locale language repacks". There is another concept of a +"multi-locale language build", which is more like a regular build and less +like a re-packaging post-processing step. + +.. note:: + + These builds rely on make targets that don't work for + `artifact builds <https://bugzilla.mozilla.org/show_bug.cgi?id=1387485>`_. + +Instructions for single-locale repacks for developers +----------------------------------------------------- + +This assumes that ``$AB_CD`` is the locale you want to repack with; you +find the available localizations on `l10n-central <https://hg.mozilla.org/l10n-central/>`_. + +#. You must have a built and packaged object directory, or a pre-built + ``en-US`` package. + + .. code-block:: shell + + ./mach build + ./mach package + +#. Repackage using the locale-specific changes. + + .. code-block:: shell + + ./mach build installers-$AB_CD + +You should find a re-packaged build at ``OBJDIR/dist/``, and a +runnable binary in ``OBJDIR/dist/l10n-stage/``. +The ``installers`` target runs quite a few things for you, including getting +the repository for the requested locale from +https://hg.mozilla.org/l10n-central/. It will clone them into +``~/.mozbuild/l10n-central``. If you have an existing repository there, you +may want to occasionally update that via ``hg pull -u``. If you prefer +to have the l10n repositories at a different location on your disk, you +can point to the directory via + + .. code-block:: shell + + ac_add_options --with-l10n-base=/make/this/a/absolute/path + +This build also packages a language pack. + +Instructions for language packs +------------------------------- + +Language packs are extensions that contain just the localized resources. Building +them doesn't require an actual build, but they're only compatible with the +``mozilla-central`` source they're built with. + + +.. code-block:: shell + + ./mach build langpack-$AB_CD + +This target shares much of the logic of the ``installers-$AB_CD`` target above, +and does the check-out of the localization repository etc. It doesn't require +a package or a build, though. The generated language pack is in +``OBJDIR/dist/$(MOZ_PKG_PLATFORM)/xpi/``. + +.. note:: + + Despite the platform-dependent location in the build directory, language packs + are platform independent, and the content that goes into them needs to be + built in a platform-independent way. + +Instructions for multi-locale builds +------------------------------------ + +If you want to create a single build with multiple locales, you will do + +#. Create a build and package + + .. code-block:: shell + + ./mach build + ./mach package + +#. Create the multi-locale package: + + .. code-block:: shell + + ./mach package-multi-locale --locales de it zh-TW + +On Android, this produces a multi-locale GeckoView AAR and multi-locale APKs, +including GeckoViewExample. You can test different locales by changing your +Android OS locale and restarting GeckoViewExample. You'll need to install with +the ``MOZ_CHROME_MULTILOCALE`` variable set, like: + + .. code-block:: shell + + env MOZ_CHROME_MULTILOCALE=en-US,de,it,zh-TW ./mach android install-geckoview_example + +Multi-locale builds without compiling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For deep technical reasons, artifact builds do not support multi-locale builds. +However, with a little work, we can achieve the same effect: + +#. Arrange a ``mozconfig`` without a compilation environment but with support + for the ``RecursiveMake`` build backend, like: + + .. code-block:: shell + + ac_add_options --disable-compile-environment + export BUILD_BACKENDS=FasterMake,RecursiveMake + ... other options ... + +#. Configure. + + .. code-block:: shell + + ./mach configure + +#. Manually provide compiled artifacts. + + .. code-block:: shell + + ./mach artifact install [-v] + +#. Build. + + .. code-block:: shell + + ./mach build + +#. Produce a multi-locale package. + + .. code-block:: shell + + ./mach package-multi-locale --locales de it zh-TW + +This build configuration is fragile and not generally useful for active +development (for that, use a full/compiled build), but it certainly speeds +testing multi-locale packaging. + +General flow of repacks +----------------------- + +The general flow of the locale repacks is controlled by +``$MOZ_BUILD_APP/locales/Makefile.in`` and ``toolkit/locales/l10n.mk``, plus +the packaging build system. The three main entry points above all trigger +related build flows: + +#. Get the localization repository, if needed +#. Run l10n-merge with a prior clobber of the merge dir +#. Copy l10n files to ``dist``, with minor differences here between ``l10n-%`` and ``chrome-%`` +#. Repackage and package + +Details on l10n-merge are described in its own section below. +The copying of files is mainly controlled by ``jar.mn``, in the few source +directories that include localizable files. ``l10n-%`` is used for repacks, +``chrome-%`` for multi-locale packages. The repackaging is dedicated +Python code in ``toolkit/mozapps/installer/l10n-repack.py``, using an existing +package. It strips existing ``chrome`` l10n resources, and adds localizations +and metadata. + +Language packs don't require repackaging. The windows installers are generated +by merely packaging an existing repackaged zip into to an installer. + +Exposing strings +================ + +The localization flow handles a few file formats in well-known locations in the +source tree. + +Alongside being built by including the directory in ``$MOZ_BUILD_APP/locales/Makefile.in`` +and respective entries in a ``jar.mn``, we also have configuration files tailored +to localization tools and infrastructure. They're also controlling which +files l10n-merge handles, and how. + +These configurations are TOML files. They're part of the bigger +localization ecosystem at Mozilla, and `the documentation about the +file format <http://moz-l10n-config.readthedocs.io/en/latest/fileformat.html>`_ +explains how to set them up, and what the entries mean. In short, you find + +.. code-block:: toml + + [paths] + reference = browser/locales/en-US/** + l10n = {l}browser/** + +to add a directory for all localizations. Changes to these files are best +submitted for review by :Pike or :flod. + +These configuration files are the future, and right now, we still have +support for the previous way to configuring l10n, which is described below. + +The locations are commonly in directories like + + :file:`browser/`\ ``locales/en-US/``\ :file:`subdir/file.ext` + +The first thing to note is that only files beneath :file:`locales/en-US` are +exposed to localizers. The second thing to note is that only a few directories +are exposed. Which directories are exposed is defined in files called +``l10n.ini``, which are at a +`few places <https://searchfox.org/mozilla-central/search?q=path%3Al10n.ini&redirect=true>`_ +in the source code. + +An example looks like this + +.. code-block:: ini + + [general] + depth = ../.. + + [compare] + dirs = browser + browser/branding/official + + [includes] + toolkit = toolkit/locales/l10n.ini + +This tells the l10n infrastructure three things: + +* resolve the paths against the directory two levels up +* include files in :file:`browser/locales/en-US` and + :file:`browser/branding/official/locales/en-US` +* load more data from :file:`toolkit/locales/l10n.ini` + +For projects like Thunderbird and SeaMonkey in ``comm-central``, additional +data needs to be provided when including an ``l10n.ini`` from a different +repository: + +.. code-block:: ini + + [include_toolkit] + type = hg + mozilla = mozilla-central + repo = https://hg.mozilla.org/ + l10n.ini = toolkit/locales/l10n.ini + +This tells the l10n infrastructure where to find the repository, and where inside +that repository the ``l10n.ini`` file is. This is needed because for local +builds, :file:`mail/locales/l10n.ini` references +:file:`mozilla/toolkit/locales/l10n.ini`, which is where the comm-central +build setup expects toolkit to be. + +Now that the directories exposed to l10n are known, we can talk about the +supported file formats. + +File formats +------------ + +The following file formats are known to the l10n tool chains: + +Fluent + Used in Firefox UI, both declarative and programmatically. +Properties + Used from JavaScript and C++. When used from js, also comes with + plural support (avoid if possible). +ini + Used by the crashreporter and updater, avoid if possible. + +Adding new formats involves changing various different tools, and is strongly +discouraged. + +Exceptions +---------- +Generally, anything that exists in ``en-US`` needs a one-to-one mapping in +all localizations. There are a few cases where that's not wanted, notably +around locale configuration and locale-dependent metadata. + +For optional strings and files, l10n-merge won't add ``en-US`` content if +the localization doesn't have that content. + +For the TOML files, the +`[[filters]] documentation <https://moz-l10n-config.readthedocs.io/en/latest/fileformat.html#filters>`_ +is a good reference. In short, filters match the localized source code, optionally +a ``key``, and an action. An example like + +.. code-block:: toml + + [filters] + path = "{l}calendar/chrome/calendar/calendar-event-dialog.properties" + key = "re:.*Nounclass[1-9].*" + action = "ignore" + +indicates that the matching messages in ``calendar-event-dialog.properties`` are optional. + +For the legacy ini configuration files, there's a Python module +``filter.py`` next to the main ``l10n.ini``, implementing :py:func:`test`, with the following +signature + +.. code-block:: python + + def test(mod, path, entity = None): + if does_not_matter: + return "ignore" + if show_but_do_not_merge: + return "report" + # default behavior, localizer or build need to do something + return "error" + +For any missing file, this function is called with ``mod`` being +the *module*, and ``path`` being the relative path inside +:file:`locales/en-US`. The module is the top-level dir as referenced in +:file:`l10n.ini`. + +For missing strings, the :py:data:`entity` parameter is the key of the string +in the en-US file. + +l10n-merge +========== + +The chrome registry in Gecko doesn't support fallback from a localization to ``en-US`` at runtime. +Thus, the build needs to ensure that the localization as it's built into +the package has all required strings, and that the strings don't contain +errors. To ensure that, we're *merging* the localization and ``en-US`` +at build time, nick-named l10n-merge. + +For Fluent, we're also removing erroneous messages. For many errors in Fluent, +that's cosmetic, but when a localization has different values or attributes +on a message, that's actually important so that the DOM bindings of Fluent +can apply the translation without having to load the ``en-US`` source to +compare against. + +The process can be manually triggered via + +.. code-block:: bash + + $> ./mach build merge-$AB_CD + +It creates another directory in the object dir, :file:`browser/locales/merge-dir/$AB_CD`, in +which the sanitized files are stored. The actual repackaging process only looks +in the merged directory, so the preparation steps of l10n-merge need to ensure +that all files are generated or copied. + +l10n-merge modifies a file if it supports the particular file type, and there +are missing strings which are not filtered out, or if an existing string +shows an error. See the Checks section below for details. If the files are +not modified, l10n-merge copies them over to the respective location in the +merge dir. + +Checks +------ + +As part of the build and other localization tool chains, we run a variety +of source-based checks. Think of them as linters. + +The suite of checks is usually determined by file type, i.e., there's a +suite of checks for Fluent files and one for properties files, etc. + +Localizations +------------- + +Now that we talked in-depth about how to expose content to localizers, +where are the localizations? + +We host a mercurial repository per locale. All of our +localizations can be found on https://hg.mozilla.org/l10n-central/. + +You can search inside our localized files on +`Transvision <https://transvision.mozfr.org/>`_. diff --git a/build/docs/mozbuild-files.rst b/build/docs/mozbuild-files.rst new file mode 100644 index 0000000000..9d69404732 --- /dev/null +++ b/build/docs/mozbuild-files.rst @@ -0,0 +1,176 @@ +.. _mozbuild-files: + +=============== +moz.build Files +=============== + +``moz.build`` files are the mechanism by which tree metadata (notably +the build configuration) is defined. + +Directories in the tree contain ``moz.build`` files which declare +functionality for their respective part of the tree. This includes +things such as the list of C++ files to compile, where to find tests, +etc. + +``moz.build`` files are actually Python scripts. However, their +execution is governed by special rules. This is explained below. + +moz.build Python Sandbox +======================== + +As mentioned above, ``moz.build`` files are Python scripts. However, +they are executed in a special Python *sandbox* that significantly +changes and limits the execution environment. The environment is so +different, it's doubtful most ``moz.build`` files would execute without +error if executed by a vanilla Python interpreter (e.g. ``python +moz.build``. + +The following properties make execution of ``moz.build`` files special: + +1. The execution environment exposes a limited subset of Python. +2. There is a special set of global symbols and an enforced naming + convention of symbols. +3. Some symbols are inherited from previously-executed ``moz.build`` + files. + +The limited subset of Python is actually an extremely limited subset. +Only a few symbols from ``__builtin__`` are exposed. These include +``True``, ``False``, ``None``, ``sorted``, ``int``, and ``set``. Global +functions like ``import``, ``print``, and ``open`` aren't available. +Without these, ``moz.build`` files can do very little. *This is by design*. + +The execution sandbox treats all ``UPPERCASE`` variables specially. Any +``UPPERCASE`` variable must be known to the sandbox before the script +executes. Any attempt to read or write to an unknown ``UPPERCASE`` +variable will result in an exception being raised. Furthermore, the +types of all ``UPPERCASE`` variables is strictly enforced. Attempts to +assign an incompatible type to an ``UPPERCASE`` variable will result in +an exception being raised. + +The strictness of behavior with ``UPPERCASE`` variables is a very +intentional design decision. By ensuring strict behavior, any operation +involving an ``UPPERCASE`` variable is guaranteed to have well-defined +side-effects. Previously, when the build configuration was defined in +``Makefiles``, assignments to variables that did nothing would go +unnoticed. ``moz.build`` files fix this problem by eliminating the +potential for false promises. + +After a ``moz.build`` file has completed execution, only the +``UPPERCASE`` variables are used to retrieve state. + +The set of variables and functions available to the Python sandbox is +defined by the :py:mod:`mozbuild.frontend.context` module. The +data structures in this module are consumed by the +:py:class:`mozbuild.frontend.reader.MozbuildSandbox` class to construct +the sandbox. There are tests to ensure that the set of symbols exposed +to an empty sandbox are all defined in the ``context`` module. +This module also contains documentation for each symbol, so nothing can +sneak into the sandbox without being explicitly defined and documented. + +Reading and Traversing moz.build Files +====================================== + +The process for reading ``moz.build`` files roughly consists of: + +1. Start at the root ``moz.build`` (``<topsrcdir>/moz.build``). +2. Evaluate the ``moz.build`` file in a new sandbox. +3. Emit the main *context* and any *sub-contexts* from the executed + sandbox. +4. Extract a set of ``moz.build`` files to execute next. +5. For each additional ``moz.build`` file, goto #2 and repeat until all + referenced files have executed. + +From the perspective of the consumer, the output of reading is a stream +of :py:class:`mozbuild.frontend.reader.context.Context` instances. Each +``Context`` defines a particular aspect of data. Consumers iterate over +these objects and do something with the data inside. Each object is +essentially a dictionary of all the ``UPPERCASE`` variables populated +during its execution. + +.. note:: + + Historically, there was only one ``context`` per ``moz.build`` file. + As the number of things tracked by ``moz.build`` files grew and more + and more complex processing was desired, it was necessary to split these + contexts into multiple logical parts. It is now common to emit + multiple contexts per ``moz.build`` file. + +Build System Reading Mode +------------------------- + +The traditional mode of evaluation of ``moz.build`` files is what's +called *build system traversal mode.* In this mode, the ``CONFIG`` +variable in each ``moz.build`` sandbox is populated from data coming +from ``config.status``, which is produced by ``configure``. + +During evaluation, ``moz.build`` files often make decisions conditional +on the state of the build configuration. e.g. *only compile foo.cpp if +feature X is enabled*. + +In this mode, traversal of ``moz.build`` files is governed by variables +like ``DIRS`` and ``TEST_DIRS``. For example, to execute a child +directory, ``foo``, you would add ``DIRS += ['foo']`` to a ``moz.build`` +file and ``foo/moz.build`` would be evaluated. + +.. _mozbuild_fs_reading_mode: + +Filesystem Reading Mode +----------------------- + +There is an alternative reading mode that doesn't involve the build +system and doesn't use ``DIRS`` variables to control traversal into +child directories. This mode is called *filesystem reading mode*. + +In this reading mode, the ``CONFIG`` variable is a dummy, mostly empty +object. Accessing all but a few special variables will return an empty +value. This means that nearly all ``if CONFIG['FOO']:`` branches will +not be taken. + +Instead of using content from within the evaluated ``moz.build`` +file to drive traversal into subsequent ``moz.build`` files, the set +of files to evaluate is controlled by the thing doing the reading. + +A single ``moz.build`` file is not guaranteed to be executable in +isolation. Instead, we must evaluate all *parent* ``moz.build`` files +first. For example, in order to evaluate ``/foo/moz.build``, one must +execute ``/moz.build`` and have its state influence the execution of +``/foo/moz.build``. + +Filesystem reading mode is utilized to power the +:ref:`mozbuild_files_metadata` feature. + +Technical Details +----------------- + +The code for reading ``moz.build`` files lives in +:py:mod:`mozbuild.frontend.reader`. The Python sandboxes evaluation results +(:py:class:`mozbuild.frontend.context.Context`) are passed into +:py:mod:`mozbuild.frontend.emitter`, which converts them to classes defined +in :py:mod:`mozbuild.frontend.data`. Each class in this module defines a +domain-specific component of tree metadata. e.g. there will be separate +classes that represent a JavaScript file vs a compiled C++ file or test +manifests. This means downstream consumers of this data can filter on class +types to only consume what they are interested in. + +There is no well-defined mapping between ``moz.build`` file instances +and the number of :py:mod:`mozbuild.frontend.data` classes derived from +each. Depending on the content of the ``moz.build`` file, there may be 1 +object derived or 100. + +The purpose of the ``emitter`` layer between low-level sandbox execution +and metadata representation is to facilitate a unified normalization and +verification step. There are multiple downstream consumers of the +``moz.build``-derived data and many will perform the same actions. This +logic can be complicated, so we have a component dedicated to it. + +:py:class:`mozbuild.frontend.reader.BuildReader`` and +:py:class:`mozbuild.frontend.reader.TreeMetadataEmitter`` have a +stream-based API courtesy of generators. When you hook them up properly, +the :py:mod:`mozbuild.frontend.data` classes are emitted before all +``moz.build`` files have been read. This means that downstream errors +are raised soon after sandbox execution. + +Lots of the code for evaluating Python sandboxes is applicable to +non-Mozilla systems. In theory, it could be extracted into a standalone +and generic package. However, until there is a need, there will +likely be some tightly coupled bits. diff --git a/build/docs/mozbuild-symbols.rst b/build/docs/mozbuild-symbols.rst new file mode 100644 index 0000000000..4e9a8853a0 --- /dev/null +++ b/build/docs/mozbuild-symbols.rst @@ -0,0 +1,7 @@ +.. _mozbuild_symbols: + +======================== +mozbuild Sandbox Symbols +======================== + +.. mozbuildsymbols:: mozbuild.frontend.context diff --git a/build/docs/mozbuild/index.rst b/build/docs/mozbuild/index.rst new file mode 100644 index 0000000000..1dbb368034 --- /dev/null +++ b/build/docs/mozbuild/index.rst @@ -0,0 +1,40 @@ +======== +mozbuild +======== + +mozbuild is a Python package providing functionality used by Mozilla's +build system. + +Modules Overview +================ + +* mozbuild.backend -- Functionality for producing and interacting with build + backends. A build backend is an entity that consumes build system metadata + (from mozbuild.frontend) and does something useful with it (typically writing + out files that can be used by a build tool to build the tree). +* mozbuild.compilation -- Functionality related to compiling. This + includes managing compiler warnings. +* mozbuild.frontend -- Functionality for reading build frontend files + (what defines the build system) and converting them to data structures + which are fed into build backends to produce backend configurations. +* mozpack -- Functionality related to packaging builds. + +Overview +======== + +The build system consists of frontend files that define what to do. They +say things like "compile X" "copy Y." + +The mozbuild.frontend package contains code for reading these frontend +files and converting them to static data structures. The set of produced +static data structures for the tree constitute the current build +configuration. + +There exist entities called build backends. From a high level, build +backends consume the build configuration and do something with it. They +typically produce tool-specific files such as make files which can be used +to build the tree. + +Piecing it all together, we have frontend files that are parsed into data +structures. These data structures are fed into a build backend. The output +from build backends is used by builders to build the tree. diff --git a/build/docs/mozconfigs.rst b/build/docs/mozconfigs.rst new file mode 100644 index 0000000000..1859b87875 --- /dev/null +++ b/build/docs/mozconfigs.rst @@ -0,0 +1,69 @@ +.. _mozconfig: + +=============== +mozconfig Files +=============== + +mozconfig files are used to configure how a build works. + +mozconfig files are actually shell scripts. They are executed in a +special context with specific variables and functions exposed to them. + +API +=== + +Functions +--------- + +The following special functions are available to a mozconfig script. + +ac_add_options +^^^^^^^^^^^^^^ + +This function is used to declare extra options/arguments to pass into +configure. + +e.g.:: + + ac_add_options --disable-tests + ac_add_options --enable-optimize + +mk_add_options +^^^^^^^^^^^^^^ + +This function is used to inject statements into client.mk for execution. +It is typically used to define variables, notably the object directory. + +e.g.:: + + mk_add_options AUTOCLOBBER=1 + +Special mk_add_options Variables +-------------------------------- + +For historical reasons, the method for communicating certain +well-defined variables is via mk_add_options(). In this section, we +document what those special variables are. + +MOZ_OBJDIR +^^^^^^^^^^ + +This variable is used to define the :term:`object directory` for the current +build. + +Finding the active mozconfig +============================ + +Multiple mozconfig files can exist to provide different configuration +options for different tasks. The rules for finding the active mozconfig +are defined in the +:py:func:`mozboot.mozconfig.find_mozconfig` method. + +.. automodule:: mozboot.mozconfig + :members: find_mozconfig + +Loading the active mozconfig +---------------------------- + +.. autoclass:: mozbuild.mozconfig.MozconfigLoader + :members: read_mozconfig diff --git a/build/docs/mozinfo.rst b/build/docs/mozinfo.rst new file mode 100644 index 0000000000..d2f2499af9 --- /dev/null +++ b/build/docs/mozinfo.rst @@ -0,0 +1,181 @@ +.. _mozinfo: + +======= +mozinfo +======= + +``mozinfo`` is a solution for representing a subset of build +configuration and run-time data. + +``mozinfo`` data is typically accessed through a ``mozinfo.json`` file +which is written to the :term:`object directory` during build +configuration. The code for writing this file lives in +:py:mod:`mozbuild.mozinfo`. + +``mozinfo.json`` is an object/dictionary of simple string values. + +The attributes in ``mozinfo.json`` are used for many purposes. One use +is to filter tests for applicability to the current build. For more on +this, see :ref:`test_manifests`. + +.. _mozinfo_attributes: + +mozinfo.json Attributes +================================= + +``mozinfo`` currently records the following attributes. + +appname + The application being built. + + Value comes from ``MOZ_APP_NAME`` from ``config.status``. + + Optional. + +asan + Whether address sanitization is enabled. + + Values are ``true`` and ``false``. + + Always defined. + +bin_suffix + The file suffix for binaries produced with this build. + + Values may be an empty string, as not all platforms have a binary + suffix. + + Always defined. + +bits + The number of bits in the CPU this build targets. + + Values are typically ``32`` or ``64``. + + Universal Mac builds do not have this key defined. + + Unknown processor architectures (see ``processor`` below) may not have + this key defined. + + Optional. + +buildapp + The path to the XUL application being built. + + For desktop Firefox, this is ``browser``. For Fennec, it's + ``mobile/android``. + +crashreporter + Whether the crash reporter is enabled for this build. + + Values are ``true`` and ``false``. + + Always defined. + +datareporting + Whether data reporting (MOZ_DATA_REPORTING) is enabled for this build. + + Values are ``true`` and ``false``. + + Always defined. + +debug + Whether this is a debug build. + + Values are ``true`` and ``false``. + + Always defined. + +devedition + Whether this is a devedition build. + + Values are ``true`` and ``false``. + + Always defined. + +healthreport + Whether the Health Report feature is enabled. + + Values are ``true`` and ``false``. + + Always defined. + +mozconfig + The path of the :ref:`mozconfig file <mozconfig>` used to produce this build. + + Optional. + +nightly_build + Whether this is a nightly build. + + Values are ``true`` and ``false``. + + Always defined. + +os + The operating system the build is produced for. Values for tier-1 + supported platforms are ``linux``, ``win``, ``mac``, and + ``android``. For other platforms, the value is the lowercase version + of the ``OS_TARGET`` variable from ``config.status``. + + Always defined. + +processor + Information about the processor architecture this build targets. + + Values come from ``TARGET_CPU``, however some massaging may be + performed. + + If the build is a universal build on Mac (it targets both 32-bit and + 64-bit), the value is ``universal-x86-x86_64``. + + If the value starts with ``arm``, the value is ``arm``. + + If the value starts with a string of the form ``i[3-9]86]``, the + value is ``x86``. + + Always defined. + +release_or_beta + Whether this is a release or beta build. + + Values are ``true`` and ``false``. + + Always defined. + +stylo + Whether the Stylo styling system is being used. + + Values are ``true`` and ``false``. + + Always defined. + +tests_enabled + Whether tests are enabled for this build. + + Values are ``true`` and ``false``. + + Always defined. + +toolkit + The widget toolkit in case. The value comes from the + ``MOZ_WIDGET_TOOLKIT`` ``config.status`` variable. + + Always defined. + +topsrcdir + The path to the source directory the build came from. + + Always defined. + +topobjdir + The path to the obj directory the build came from. + + Always defined. + +webrender + Whether or not WebRender is enabled as the Gecko compositor. + + Values are ``true`` and ``false``. + + Always defined. diff --git a/build/docs/pgo.rst b/build/docs/pgo.rst new file mode 100644 index 0000000000..722056c727 --- /dev/null +++ b/build/docs/pgo.rst @@ -0,0 +1,28 @@ +.. _pgo: + +=========================== +Profile Guided Optimization +=========================== + +:abbr:`PGO (Profile Guided Optimization)` is the process of adding +probes to a compiled binary, running said binary, then using the +run-time information to *recompile* the binary to (hopefully) make it +faster. + +How PGO Builds Work +=================== + +The supported interface for invoking a PGO build is to add ``MOZ_PGO=1`` to +configure flags and then build. e.g. in your mozconfig:: + + ac_add_options MOZ_PGO=1 + +Then:: + + $ ./mach build + +This is roughly equivalent to:: + +#. Perform a build with *--enable-profile-generate* in $topobjdir/instrumented +#. Perform a run of the instrumented binaries with build/pgo/profileserver.py +#. Perform a build with *--enable-profile-use* in $topobjdir diff --git a/build/docs/preprocessor.rst b/build/docs/preprocessor.rst new file mode 100644 index 0000000000..5ce9092ed9 --- /dev/null +++ b/build/docs/preprocessor.rst @@ -0,0 +1,219 @@ +.. _preprocessor: + +================= +Text Preprocessor +================= + +The build system contains a text preprocessor similar to the C preprocessor, +meant for processing files which have no built-in preprocessor such as XUL +and JavaScript documents. It is implemented at ``python/mozbuild/mozbuild/preprocessor.py`` and +is typically invoked via :ref:`jar_manifests`. + +While used to preprocess CSS files, the directives are changed to begin with +``%`` instead of ``#`` to avoid conflict of the id selectors. + +Directives +========== + +Variable Definition +------------------- + +define +^^^^^^ + +:: + + #define variable + #define variable value + +Defines a preprocessor variable. + +Note that, unlike the C preprocessor, instances of this variable later in the +source are not automatically replaced (see #filter). If value is not supplied, +it defaults to ``1``. + +Note that whitespace is significant, so ``"#define foo one"`` and +``"#define foo one "`` is different (in the second case, ``foo`` is defined to +be a four-character string). + +undef +^^^^^ + +:: + + #undef variable + +Undefines a preprocessor variable. + +Conditionals +------------ + +if +^^ + +:: + + #if variable + #if !variable + #if variable == string + #if variable != string + +Disables output if the conditional is false. This can be nested to arbitrary +depths. Note that in the equality checks, the variable must come first. + +else +^^^^ + +:: + + #else + +Reverses the state of the previous conditional block; for example, if the +last ``#if`` was true (output was enabled), an ``#else`` makes it off +(output gets disabled). + +endif +^^^^^ + +:: + + #endif + +Ends the conditional block. + +ifdef / ifndef +^^^^^^^^^^^^^^ + +:: + + #ifdef variable + #ifndef variable + +An ``#if`` conditional that is true only if the preprocessor variable +variable is defined (in the case of ``ifdef``) or not defined (``ifndef``). + +elif / elifdef / elifndef +^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + #elif variable + #elif !variable + #elif variable == string + #elif variable != string + #elifdef variable + #elifndef variable + +A shorthand to mean an ``#else`` combined with the relevant conditional. +The following two blocks are equivalent:: + + #ifdef foo + block 1 + #elifdef bar + block 2 + #endif + +:: + + #ifdef foo + block 1 + #else + #ifdef bar + block 2 + #endif + #endif + +File Inclusion +-------------- + +include +^^^^^^^ + +:: + + #include filename + +The file specified by filename is processed as if the contents was placed +at this position. This also means that preprocessor conditionals can even +be started in one file and ended in another (but is highly discouraged). +There is no limit on depth of inclusion, or repeated inclusion of the same +file, or self inclusion; thus, care should be taken to avoid infinite loops. + +includesubst +^^^^^^^^^^^^ + +:: + + #includesubst @variable@filename + +Same as a ``#include`` except that all instances of variable in the included +file is also expanded as in ``#filter`` substitution + +expand +^^^^^^ + +:: + + #expand string + +All variables wrapped in ``__`` are replaced with their value, for this line +only. If the variable is not defined, it expands to an empty string. For +example, if ``foo`` has the value ``bar``, and ``baz`` is not defined, then:: + + #expand This <__foo__> <__baz__> gets expanded + +Is expanded to:: + + This <bar> <> gets expanded + +filter / unfilter +^^^^^^^^^^^^^^^^^ + +:: + + #filter filter1 filter2 ... filterN + #unfilter filter1 filter2 ... filterN + +``#filter`` turns on the given filter. + +Filters are run in alphabetical order on a per-line basis. + +``#unfilter`` turns off the given filter. Available filters are: + +emptyLines + strips blank lines from the output +dumbComments + dumbComments: empties out any line that consists of optional whitespace + followed by a ``//``. Good for getting rid of comments that are on their + own lines, and being smarter with a simple regexp filter is impossible +substitution + all variables wrapped in @ are replaced with their value. If the + variable is not defined, it is a fatal error. Similar to ``#expand`` + and ``#filter`` +attemptSubstitution + all variables wrapped in ``@`` are replaced with their value, or an + empty string if the variable is not defined. Similar to ``#expand``. + +literal +^^^^^^^ + +:: + + #literal string + +Output the string (i.e. the rest of the line) literally, with no other fixups. +This is useful to output lines starting with ``#``, or to temporarily +disable filters. + +Other +----- + +#error +^^^^^^ + +:: + + #error string + +Cause a fatal error at this point, with the error message being the +given string. diff --git a/build/docs/python.rst b/build/docs/python.rst new file mode 100644 index 0000000000..4edef1244d --- /dev/null +++ b/build/docs/python.rst @@ -0,0 +1,165 @@ +.. _python: + +=========================== +Python and the Build System +=========================== + +The Python programming language is used significantly in the build +system. If we need to write code for the build system or for a tool +related to the build system, Python is typically the first choice. + +Python Requirements +=================== + +The tree requires Python 3.8 or greater to build. +All Python packages not in the Python distribution are included in the +source tree. So all you should need is a vanilla Python install and you +should be good to go. + +Only CPython (the Python distribution available from www.python.org) is +supported. + +Compiled Python Packages +======================== + +There are some features of the build that rely on compiled Python packages +(packages containing C source). These features are currently all +optional because not every system contains the Python development +headers required to build these extensions. + +We recommend you have the Python development headers installed (``mach +bootstrap`` should do this for you) so you can take advantage of these +features. + +Issues with OS X System Python +============================== + +The Python that ships with OS X has historically been littered with +subtle bugs and suboptimalities. + +OS X 10.8 and below users will be required to install a new Python +distribution. This may not be necessary for OS X 10.9+. However, we +still recommend installing a separate Python because of the history with +OS X's system Python issues. + +We recommend installing Python through Homebrew or MacPorts. If you run +``mach bootstrap``, this should be done for you. + +Virtual Environments +==================== + +The build system relies heavily on +`venv <https://docs.python.org/3/library/venv.html>`_. Venv provides +standalone and isolated Python "virtual environments". The problem a venv +solves is that of dependencies across multiple Python components. If two +components on a system relied on different versions of a package, there +could be a conflict. Instead of managing multiple versions of a package +simultaneously, Python and venv take the route that it is easier +to just keep them separate so there is no potential for conflicts. + +Very early in the build process, a venv is created inside the +:term:`object directory`. The venv is configured such that it can +find all the Python packages in the source tree. The code for this lives +in ``mach.site``. + +Deficiencies +------------ + +There are numerous deficiencies with the way virtual environments are +handled in the build system. + +* mach reinvents the venv. + + There is code in ``build/mach_initialize.py`` that configures ``sys.path`` + much the same way the venv does. There are various bugs tracking + this. However, no clear solution has yet been devised. It's not a huge + problem and thus not a huge priority. + +* They aren't preserved across copies and packaging. + + If you attempt to copy an entire tree from one machine to another or + from one directory to another, chances are the venv will fall + apart. It would be nice if we could preserve it somehow. Instead of + actually solving portable venv, all we really need to solve is + encapsulating the logic for populating the venv along with all + dependent files in the appropriate place. + +* .pyc files written to source directory. + + We rely heavily on ``.pth`` files in our venv. A ``.pth`` file + is a special file that contains a list of paths. Python will take the + set of listed paths encountered in ``.pth`` files and add them to + ``sys.path``. + + When Python compiles a ``.py`` file to bytecode, it writes out a + ``.pyc`` file so it doesn't have to perform this compilation again. + It puts these ``.pyc`` files alongside the ``.pyc`` file. Python + provides very little control for determining where these ``.pyc`` files + go, even in Python 3 (which offers customer importers). + + With ``.pth`` files pointing back to directories in the source tree + and not the object directory, ``.pyc`` files are created in the source + tree. This is bad because when Python imports a module, it first looks + for a ``.pyc`` file before the ``.py`` file. If there is a ``.pyc`` + file but no ``.py`` file, it will happily import the module. This + wreaks havoc during file moves, refactoring, etc. + + There are various proposals for fixing this. See bug 795995. + +Installing Python Manually +========================== + +We highly recommend you use your system's package manager or a +well-supported 3rd party package manager to install Python for you. If +these are not available to you, we recommend the following tools for +installing Python: + +* `buildout.python <https://github.com/collective/buildout.python>`_ +* `pyenv <https://github.com/yyuu/pyenv>`_ +* An official installer from http://www.python.org. + +If all else fails, consider compiling Python from source manually. But this +should be viewed as the least desirable option. + +Common Issues with Python +========================= + +Upgrading your Python distribution breaks the venv +-------------------------------------------------------- + +If you upgrade the Python distribution (e.g. install Python 3.6.15 +from 3.6.9), chances are parts of the venv will break. +This commonly manifests as a cryptic ``Cannot import XXX`` exception. +More often than not, the module being imported contains binary/compiled +components. + +If you upgrade or reinstall your Python distribution, we recommend +clobbering your build. + +Packages installed at the system level conflict with build system's +------------------------------------------------------------------- + +It is common for people to install Python packages using ``sudo`` (e.g. +``sudo pip install psutil``) or with the system's package manager +(e.g. ``apt-get install python-mysql``. + +A problem with this is that packages installed at the system level may +conflict with the package provided by the source tree. As of bug 907902 +and changeset f18eae7c3b27 (September 16, 2013), this should no longer +be an issue since the venv created as part of the build doesn't +add the system's ``site-packages`` directory to ``sys.path``. However, +poorly installed packages may still find a way to creep into the mix and +interfere with our venv. + +As a general principle, we recommend against using your system's package +manager or using ``sudo`` to install Python packages. Instead, create +virtual environments and isolated Python environments for all of your +Python projects. + +Python on $PATH is not appropriate +---------------------------------- + +Tools like ``mach`` will look for Python by performing ``/usr/bin/env +python`` or equivalent. Please be sure the appropriate Python 2.7.3+ +path is on $PATH. On OS X, this likely means you'll need to modify your +shell's init script to put something ahead of ``/usr/bin``. diff --git a/build/docs/rust.rst b/build/docs/rust.rst new file mode 100644 index 0000000000..4d79f7ca4e --- /dev/null +++ b/build/docs/rust.rst @@ -0,0 +1,181 @@ +.. _rust: + +============================== +Including Rust Code in Firefox +============================== + +This page explains how to add, build, link, and vendor Rust crates. + +The `code documentation <../../writing-rust-code>`_ explains how to write and +work with Rust code in Firefox. The +`test documentation <../../testing-rust-code>`_ explains how to test and debug +Rust code in Firefox. + +Linking Rust crates into libxul +=============================== + +Rust crates that you want to link into libxul should be listed in the +``dependencies`` section of +`toolkit/library/rust/shared/Cargo.toml <https://searchfox.org/mozilla-central/source/toolkit/library/rust/shared/Cargo.toml>`_. +You must also add an ``extern crate`` reference to +`toolkit/library/rust/shared/lib.rs <https://searchfox.org/mozilla-central/source/toolkit/library/rust/shared/lib.rs>`_. +This ensures that the Rust code will be linked properly into libxul as well +as the copy of libxul used for gtests. (Even though Rust 2018 mostly doesn't +require ``extern crate`` declarations, these ones are necessary because the +gkrust setup is non-typical.) + +After adding your crate, execute ``cargo update -p gkrust-shared`` to update +the ``Cargo.lock`` file. You will also need to do this any time you change the +dependencies in a ``Cargo.toml`` file. If you don't, you will get a build error +saying **"error: the lock file /home/njn/moz/mc3/Cargo.lock needs to be updated +but --frozen was passed to prevent this"**. + +By default, all Cargo packages in the mozilla-central repository are part of +the same +`workspace <https://searchfox.org/mozilla-central/source/toolkit/library/rust/shared/lib.rs>`_ +and will share the ``Cargo.lock`` file and ``target`` directory in the root of +the repository. You can change this behavior by adding a path to the +``exclude`` list in the top-level ``Cargo.toml`` file. You may want to do +this if your package's development workflow includes dev-dependencies that +aren't needed by general Firefox developers or test infrastructure. + +The actual build mechanism is as follows. The build system generates a special +'Rust unified library' crate, compiles that to a static library +(``libgkrust.a``), and links that into libxul, so all public symbols will be +available to C++ code. Building a static library that is linked into a dynamic +library is easier than building dynamic libraries directly, and it also avoids +some subtle issues around how mozalloc works that make the Rust dynamic library +path a little wonky. + +Linking Rust crates into something else +======================================= + +To link Rust code into libraries other than libxul, create a directory with a +``Cargo.toml`` file for your crate, and a ``moz.build`` file that contains: + +.. code-block:: python + + RustLibrary('crate_name') + +where ``crate_name`` matches the name from the ``[package]`` section of your +``Cargo.toml``. You can refer to `the moz.build file <https://searchfox.org/mozilla-central/rev/603b9fded7a11ff213c0f415198cd637b7c86614/toolkit/library/rust/moz.build#9>`_ and `the Cargo.toml file <https://searchfox.org/mozilla-central/rev/603b9fded7a11ff213c0f415198cd637b7c86614/toolkit/library/rust/Cargo.toml>`_ that are used for libxul. + +You can then add ``USE_LIBS += ['crate_name']`` to the ``moz.build`` file +that defines the binary as you would with any other library in the tree. + +.. important:: + + You cannot link a Rust crate into an intermediate library that will be + eventually linked into libxul. The build system enforces that only a single + ``RustLibrary`` may be linked into a binary. If you need to do this, you + will have to add a ``RustLibrary`` to link to any standalone binaries that + link the intermediate library, and also add the Rust crate to the libxul + dependencies as in `linking Rust Crates into libxul`_. + +Conditional compilation +======================== + +Edit `tool/library/rust/gkrust-features.mozbuild +<https://searchfox.org/mozilla-central/source/toolkit/library/rust/gkrust-features.mozbuild>`_ +to expose build flags as Cargo features. + +Standalone Rust programs +======================== + +It is also possible to build standalone Rust programs. First, put the Rust +program (including the ``Cargo.toml`` file and the ``src`` directory) in its +own directory, and add an empty ``moz.build`` file to the same directory. + +Then, if the standalone Rust program must run on the compile target (e.g. +because it's shipped with Firefox) then add this rule to the ``moz.build`` +file: + +.. code-block:: python + + RUST_PROGRAMS = ['prog_name'] + +where *prog_name* is the name of the executable as specified in the +``Cargo.toml`` (and probably also matches the name of the directory). + +Otherwise, if the standalone Rust program must run on the compile host (e.g. +because it's used to build Firefox but not shipped with Firefox) then do the +same thing, but use ``HOST_RUST_PROGRAMS`` instead of ``RUST_PROGRAMS``. + +Where should I put my crate? +============================ + +If your crate's canonical home is mozilla-central, you can put it next to the +related code in the appropriate directory. + +If your crate is mirrored into mozilla-central from another repository, and +will not be actively developed in mozilla-central, you can simply list it +as a ``crates.io``-style dependency with a version number, and let it be +vendored into the ``third_party/rust`` directory. + +If your crate is mirrored into mozilla-central from another repository, but +will be actively developed in both locations, you should send mail to the +dev-builds mailing list to start a discussion on how to meet your needs. + +Third-party crate dependencies +============================== + +Third-party dependencies for in-tree Rust crates are *vendored* into the +``third_party/rust`` directory of mozilla-central. This means that a copy of +each third-party crate's code is committed into mozilla-central. As a result, +building Firefox does not involve downloading any third-party crates. + +If you add a dependency on a new crate you must run ``mach vendor rust`` to +vendor the dependencies into that directory. (Note that ``mach vendor rust`` +`may not work as well on Windows <https://bugzilla.mozilla.org/show_bug.cgi?id=1647582>`_ +as on other platforms.) + +When it comes to checking the suitability of third-party code for inclusion +into mozilla-central, keep the following in mind. + +- ``mach vendor rust`` will check that the licenses of all crates are suitable. +- ``mach vendor rust`` will run ``cargo vet`` to ensure that the crates have been audited. If not, + you will have to audit them using ``mach cargo vet`` to check that the code looks reasonable + (especially unsafe code) and that there are reasonable tests. All vendored crates must be audited. +- Third-party crate tests aren't run, which means that large test fixtures will + bloat mozilla-central. Consider working with upstream to mark those test + fixtures with ``[package] exclude = ...`` as described + `here <https://doc.rust-lang.org/cargo/reference/manifest.html#the-exclude-and-include-fields>`_. +- If you specify a dependency on a branch, pin it to a specific revision, + otherwise other people will get unexpected changes when they run ``./mach + vendor rust`` any time the branch gets updated. See `bug 1612619 + <https://bugzil.la/1612619>`_ for a case where such a problem was fixed. +- Other than that, there is no formal sign-off procedure, but one may be added + in the future. + +Note that all dependencies will be vendored, even ones that aren't used due to +disabled features. It's possible that multiple versions of a crate will end up +vendored into mozilla-central. + +Patching third-party crates +=========================== + +Sometimes you might want to temporarily patch a third-party crate, for local +builds or for a try push. + +To do this, first add an entry to the ``[patch.crates-io]`` section of the +top-level ``Cargo.toml`` that points to the crate within ``third_party``. For +example + +.. code-block:: toml + + bitflags = { path = "third_party/rust/bitflags" } + +Next, run ``cargo update -p $CRATE_NAME --precise $VERSION``, where +``$CRATE_NAME`` is the name of the patched crate, and ``$VERSION`` is its +version number. This will update the ``Cargo.lock`` file. + +Then, make the local changes to the crate. + +Finally, make sure you don't accidentally land the changes to the crate or the +``Cargo.lock`` file. + +For an example of a more complex workflow involving a third-party crate, see +`mp4parse-rust/README.md <https://searchfox.org/mozilla-central/source/media/mp4parse-rust/README.md>`_. +It describes the workflow for a crate that is hosted on GitHub, and for which +changes are made via GitHub pull requests, but all pull requests must also be +tested within mozilla-central before being merged. diff --git a/build/docs/sccache-dist.rst b/build/docs/sccache-dist.rst new file mode 100644 index 0000000000..edd9ead909 --- /dev/null +++ b/build/docs/sccache-dist.rst @@ -0,0 +1,199 @@ +.. _sccache_dist: + +================================== +Distributed sccache (sccache-dist) +================================== + +`sccache <https://github.com/mozilla/sccache>`_ is a ccache-like tool written in +Rust by Mozilla and many contributors. + +sccache-dist, its distributed variant, elevates this functionality by enabling +the distribution and caching of Rust compilations across multiple machines. +Please consider using sccache-dist when you have several machines +compiling Firefox on the same network. + +The steps for setting up your machine as an sccache-dist server are detailed below. + +In addition to improved security properties, distributed sccache offers +distribution and caching of rust compilation, so it should be an improvement +above and beyond what we see with icecc. Build servers run on Linux and +distributing builds is currently supported from Linux, macOS, and Windows. + + +Steps for distributing a build as an sccache-dist client +======================================================== + +Start by following the instructions at https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#configure-a-client +to configure your sccache distributed client. +*NOTE* If you're distributing from Linux a toolchain will be packaged +automatically and provided to the build server. If you're distributing from +Windows or macOS, start by using the cross-toolchains provided by +``./mach bootstrap`` rather than attempting to use ``icecc-create-env``. +sccache 0.2.12 or above is recommended, and the auth section of your config +must read:: + + [dist.auth] + type = "mozilla" + +* If you're compiling from a macOS client, there are a handful of additional + considerations outlined here: + https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#considerations-when-distributing-from-macos. + + Run ``./mach bootstrap`` to download prebuilt toolchains to + ``~/.mozbuild/clang-dist-toolchain.tar.xz`` and + ``~/.mozbuild/rustc-dist-toolchain.tar.xz``. This is an example of the paths + that should be added to your client config to specify toolchains to build on + macOS, located at ``~/Library/Application Support/Mozilla.sccache/config``:: + + [[dist.toolchains]] + type = "path_override" + compiler_executable = "/path/to/home/.rustup/toolchains/stable-x86_64-apple-darwin/bin/rustc" + archive = "/path/to/home/.mozbuild/rustc-dist-toolchain.tar.xz" + archive_compiler_executable = "/builds/worker/toolchains/rustc/bin/rustc" + + [[dist.toolchains]] + type = "path_override" + compiler_executable = "/path/to/home/.mozbuild/clang/bin/clang" + archive = "/path/to/home/.mozbuild/clang-dist-toolchain.tar.xz" + archive_compiler_executable = "/builds/worker/toolchains/clang/bin/clang" + + [[dist.toolchains]] + type = "path_override" + compiler_executable = "/path/to/home/.mozbuild/clang/bin/clang++" + archive = "/path/to/home/.mozbuild/clang-dist-toolchain.tar.xz" + archive_compiler_executable = "/builds/worker/toolchains/clang/bin/clang" + + Note that the version of ``rustc`` found in ``rustc-dist-toolchain.tar.xz`` + must match the version of ``rustc`` used locally. The distributed archive + will contain the version of ``rustc`` used by automation builds, which may + lag behind stable for a few days after Rust releases, which is specified by + the task definition in + `this file <https://hg.mozilla.org/mozilla-central/file/tip/taskcluster/ci/toolchain/dist-toolchains.yml>`_. + For instance, to specify 1.37.0 rather than the current stable, run + ``rustup toolchain add 1.37.0`` and point to + ``/path/to/home/.rustup/toolchains/1.37.0-x86_64-apple-darwin/bin/rustc`` in your + client config. + + The build system currently requires an explicit target to be passed with + ``HOST_CFLAGS`` and ``HOST_CXXFLAGS`` e.g.:: + + export HOST_CFLAGS="--target=x86_64-apple-darwin16.0.0" + export HOST_CXXFLAGS="--target=x86_64-apple-darwin16.0.0" + +* Compiling from a Windows client is supported but hasn't seen as much testing + as other platforms. The following example mozconfig can be used as a guide:: + + ac_add_options CCACHE="C:/Users/<USER>/.mozbuild/sccache/sccache.exe" + + export CC="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl" + export CXX="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl" + export HOST_CC="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl" + export HOST_CXX="C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe --driver-mode=cl" + + The client config should be located at + ``~/AppData/Roaming/Mozilla/sccache/config/config``, and as on macOS custom + toolchains should be obtained with ``./mach bootstrap`` and specified in the + client config, for example:: + + [[dist.toolchains]] + type = "path_override" + compiler_executable = "C:/Users/<USER>/.mozbuild/clang/bin/clang-cl.exe" + archive = "C:/Users/<USER>/.mozbuild/clang-dist-toolchain.tar.xz" + archive_compiler_executable = "/builds/worker/toolchains/clang/bin/clang" + + [[dist.toolchains]] + type = "path_override" + compiler_executable = "C:/Users/<USER>/.rustup/toolchains/stable-x86_64-pc-windows-msvc/bin/rustc.exe" + archive = "C:/Users/<USER>/.mozbuild/rustc-dist-toolchain.tar.xz" + archive_compiler_executable = "/builds/worker/toolchains/rustc/bin/rustc" + +* Add the following to your mozconfig:: + + ac_add_options CCACHE=/path/to/home/.mozbuild/sccache/sccache + + If you're compiling from a macOS client, you might need some additional configuration:: + + # Set the target flag to Darwin + export CFLAGS="--target=x86_64-apple-darwin16.0.0" + export CXXFLAGS="--target=x86_64-apple-darwin16.0.0" + export HOST_CFLAGS="--target=x86_64-apple-darwin16.0.0" + export HOST_CXXFLAGS="--target=x86_64-apple-darwin16.0.0" + + # Specify the macOS SDK to use + ac_add_options --with-macos-sdk=/path/to/MacOSX-SDKs/MacOSX13.3.sdk + + You can get the right macOS SDK by downloading an old version of XCode from + `developer.apple.com <https://developer.apple.com>`_ and unpacking the SDK + from it. + +* When attempting to get your client running, the output of ``sccache -s`` should + be consulted to confirm compilations are being distributed. To receive helpful + logging from the local daemon in case they aren't, run + ``SCCACHE_NO_DAEMON=1 SCCACHE_START_SERVER=1 SCCACHE_LOG=sccache=trace path/to/sccache`` + in a terminal window separate from your build prior to building. *NOTE* use + ``RUST_LOG`` instead of ``SCCACHE_LOG`` if your build of ``sccache`` does not + include `pull request 822 + <https://github.com/mozilla/sccache/pull/822>`_. (``sccache`` binaries from + ``mach bootstrap`` do include this PR.) + +* Run ``./mach build -j<value>`` with an appropriately large ``<value>``. + ``sccache --dist-status`` should provide the number of cores available to you + (or a message if you're not connected). In the future this will be integrated + with the build system to automatically select an appropriate value. + +This should be enough to distribute your build and replace your use of icecc. +Bear in mind there may be a few speedbumps, and please ensure your version of +sccache is current before investigating further. Please see the common questions +section below and ask for help if anything is preventing you from using it over +email (dev-builds), on slack in #sccache, or in #build on irc. + +Steps for setting up a server +============================= + +Build servers must run linux and use bubblewrap 0.3.0+ for sandboxing of compile +processes. This requires a kernel 4.6 or greater, so Ubuntu 18+, RHEL 8, or +similar. + +* Run ``./mach bootstrap`` or + ``./mach artifact toolchain --from-build linux64-sccache`` to acquire a recent + version of ``sccache-dist``. Please use a ``sccache-dist`` binary acquired in + this fashion to ensure compatibility with statically linked dependencies. + +* The instructions at https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#configure-a-build-server + should contain everything else required to configure and run the server. + + *NOTE* Port 10500 will be used by convention for builders. + Please use port 10500 in the ``public_addr`` section of your builder config. + + Extra logging may be helpful when setting up a server. To enable logging, + run your server with + ``sudo env SCCACHE_LOG=sccache=trace ~/.mozbuild/sccache/sccache-dist server --config ~/.config/sccache/server.conf`` + (or similar). *NOTE* ``sudo`` *must* come before setting environment variables + for this to work. *NOTE* use ``RUST_LOG`` instead of ``SCCACHE_LOG`` if your + build of ``sccache`` does not include `pull request 822 + <https://github.com/mozilla/sccache/pull/822>`_. (``sccache`` binaries from + ``mach bootstrap`` do include this PR.) + + +Common questions/considerations +=============================== + +* My build is still slow: scache-dist can only do so much with parts of the + build that aren't able to be parallelized. To start debugging a slow build, + ensure the "Successful distributed compilations" line in the output of + ``sccache -s`` dominates other counts. For a full build, at least a 2-3x + improvement should be observed. + +* My build output is incomprehensible due to a flood of warnings: clang will + treat some warnings differently when it's fed preprocessed code in a separate + invocation (preprocessing occurs locally with sccache-dist). Adding + ``rewrite_includes_only = true`` to the ``dist`` section of your client config + will improve this; however, setting this will cause build failures with a + commonly deployed version of ``glibc``. This option will default to ``true`` + once the fix is more widely available. Details of this fix can be found in + `this patch <https://sourceware.org/ml/libc-alpha/2019-11/msg00431.html>`_. + +* My build fails with a message about incompatible versions of rustc between + dependent crates: if you're using a custom toolchain check that the version + of rustc in your ``rustc-dist-toolchain.tar.xz`` is the same as the version + you're running locally. diff --git a/build/docs/slow.rst b/build/docs/slow.rst new file mode 100644 index 0000000000..3dfdd5b631 --- /dev/null +++ b/build/docs/slow.rst @@ -0,0 +1,153 @@ +.. _slow: + +================================== +Why the Build System might be slow +================================== + +A common complaint about the build system is that it can be slow. There are +many reasons contributing to its slowness. +However, on modern hardware, Firefox can be built in less than 10 minutes. + +First, it is important to distinguish between a :term:`clobber build` +and an :term:`incremental build`. The reasons for why each are slow can +be different. + +The build does a lot of work +============================ + +It may not be obvious, but the main reason the build system is slow is +because it does a lot of work! The source tree consists of a few +thousand C++ files. On a modern machine, we spend over 120 minutes of CPU +core time compiling files! So, if you are looking for the root cause of +slow clobber builds, look at the sheer volume of C++ files in the tree. + +You don't have enough CPU cores and MHz +======================================= + +The build should be CPU bound. If the build system maintainers are +optimizing the build system perfectly, every CPU core in your machine +should be 100% saturated during a build. While this isn't currently the +case (keep reading below), generally speaking, the more CPU cores you +have in your machine and the more total MHz in your machine, the better. + +**We highly recommend building with no fewer than 4 physical CPU +cores.** Please note the *physical* in this sentence. Hyperthreaded +cores (an Intel Core i7 will report 8 CPU cores but only 4 are physical +for example) only yield at most a 1.25x speedup per core. + +This cause impacts both clobber and incremental builds. + +You are building with a slow I/O layer +====================================== + +The build system can be I/O bound if your I/O layer is slow. Linking +libxul on some platforms and build architectures can perform gigabytes +of I/O. + +To minimize the impact of slow I/O on build performance, **we highly +recommend building with an SSD.** Power users with enough memory may opt +to build from a RAM disk. Mechanical disks should be avoided if at all +possible. + +Some may dispute the importance of an SSD on build times. It is true +that the beneficial impact of an SSD can be mitigated if your system has +lots of memory and the build files stay in the page cache. However, +operating system memory management is complicated. You don't really have +control over what or when something is evicted from the page cache. +Therefore, unless your machine is a dedicated build machine or you have +more memory than is needed by everything running on your machine, +chances are you'll run into page cache eviction and you I/O layer will +impact build performance. That being said, an SSD certainly doesn't +hurt build times. And, anyone who has used a machine with an SSD will +tell you how great of an investment it is for performance all around the +operating system. On top of that, some automated tests are I/O bound +(like those touching SQLite databases), so an SSD will make tests +faster. + +This cause impacts both clobber and incremental builds. + +You don't have enough memory +============================ + +The build system allocates a lot of memory, especially when building +many things in parallel. If you don't have enough free system memory, +the build will cause swap activity, slowing down your system and the +build. Even if you never get to the point of swapping, the build system +performs a lot of I/O and having all accessed files in memory and the +page cache can significantly reduce the influence of the I/O layer on +the build system. + +**We recommend building with no less than 8 GB of system memory.** As +always, the more memory you have, the better. For a bare bones machine +doing nothing more than building the source tree, anything more than 16 +GB is likely entering the point of diminishing returns. + +This cause impacts both clobber and incremental builds. + +You are building on Windows +=========================== + +New processes on Windows are about a magnitude slower to spawn than on +UNIX-y systems such as Linux. This is because Windows has optimized new +threads while the \*NIX platforms typically optimize new processes. +Anyway, the build system spawns thousands of new processes during a +build. Parts of the build that rely on rapid spawning of new processes +are slow on Windows as a result. This is most pronounced when running +*configure*. The configure file is a giant shell script and shell +scripts rely heavily on new processes. This is why configure +can run over a minute slower on Windows. + +Another reason Windows builds are slower is because Windows lacks proper +symlink support. On systems that support symlinks, we can generate a +file into a staging area then symlink it into the final directory very +quickly. On Windows, we have to perform a full file copy. This incurs +much more I/O. And if done poorly, can muck with file modification +times, messing up build dependencies. + +These issues impact both clobber and incremental builds. + +make is inefficient +=================== + +Compared to modern build backends like Tup or Ninja, `make` is slow and +inefficient. We can only make `make` so fast. At some point, we'll hit a +performance plateau and will need to use a different tool to make builds +faster. + +Please note that clobber and incremental builds are different. A clobber build +with `make` will likely be as fast as a clobber build with a modern build +system. + +C++ header dependency hell +========================== + +Modifying a *.h* file can have significant impact on the build system. +If you modify a *.h* that is used by 1000 C++ files, all of those 1000 +C++ files will be recompiled. + +Our code base has traditionally been sloppy managing the impact of +changed headers on build performance. Bug 785103 tracks improving the +situation. + +This issue mostly impacts the times of an :term:`incremental build`. + +A search/indexing service on your machine is running +==================================================== + +Many operating systems have a background service that automatically +indexes filesystem content to make searching faster. On Windows, you +have the Windows Search Service. On OS X, you have Finder. + +These background services sometimes take a keen interest in the files +being produced as part of the build. Since the build system produces +hundreds of megabytes or even a few gigabytes of file data, you can +imagine how much work this is to index! If this work is being performed +while the build is running, your build will be slower. + +OS X's Finder is notorious for indexing when the build is running. And, +it has a tendency to suck up a whole CPU core. This can make builds +several minutes slower. If you build with ``mach`` and have the optional +``psutil`` package built (it requires Python development headers - see +:ref:`python` for more) and Finder is running during a build, mach will +print a warning at the end of the build, complete with instructions on +how to fix it. diff --git a/build/docs/snap.rst b/build/docs/snap.rst new file mode 100644 index 0000000000..6ff52da4e8 --- /dev/null +++ b/build/docs/snap.rst @@ -0,0 +1,132 @@ +.. _snap: + +====================== +Firefox Snap Packaging +====================== + +This page explains interactions between Firefox and Snap packaging format. + +Where is the upstream +===================== + +The code reference itself is mozilla-central, but the packaging is being worked +within the `Canonical's firefox-snap repository <https://github.com/canonical/firefox-snap/>`_. + +This packaging includes a few more bits and dependencies, including compiler. +It will also re-download the mercurial repository: this is on purpose. + +Where to report bugs +==================== + +All bugs should be reported to Bugzilla's ``Third Party Packaging`` component, +and marked as blocking ``snap`` meta-bug. + +Build process +============= + +While there is an existing ``repackage`` `task +<https://searchfox.org/mozilla-central/source/taskcluster/docker/firefox-snap>`_, +is currently is no up-to-date and it is not usable from ``mach`` (work is being +`tracked in <https://bugzilla.mozilla.org/show_bug.cgi?id=1841370>`_ for this), +so unfortunately the only way to work right now is a full rebuild using +upstream tooling. + +The following steps should be enough, assuming you have properly setup: + + - ``snapcraft`` (see `quickstart doc <https://snapcraft.io/docs/snapcraft-quickstart>`_) + - ``LXD`` (see `providers doc <https://snapcraft.io/docs/build-providers>`_) + +While the documentation still refers to `Multipass`, the Firefox Snap and its +dependency had some requirements that made it better suited to use `LXD`. + +When performing the checkout, please keep in mind the branch mapping: + + - `edge` is our `nightly` + - `beta` is our `beta` + - `stable` is our `release` + - `esr` is our `esr` + +.. code-block:: shell + + $ git clone https://github.com/canonical/firefox-snap --branch BRANCH + $ snap run snapcraft + +You should end up after some time with two files: ``firefox-XXX.snap`` and +``firefox-XXX.debug``. The first one is the package you will want to ``snap +install`` while the second one holds your debugging symbols. + +You can then install the package: + +.. code-block:: shell + + $ sudo snap install --name firefox --dangerous ./path/to/firefox-XXX.snap + +If you want to have parallel installs, then you can change the `--name firefox` +to something else. This will be the name you use for ``snap run +installed-name``, e.g., ``--name firefox_nightly`` will require you to run +``snap run firefox_nightly``. + +`Snap` has a notion of plugs and slots, and some gets automatically connected +in various ways, including depending on the ``Snap Sore`` itself, and if you +manually install as ``firefox`` it should reuse them (but you might do bad +things with your profile). If you install using another name, then the ``Snap +Store`` automatic connection will not happen and this can result in a broken +state. Inspecting ``snap connections firefox`` using a store-installed snap +should get your an accurate list that you can replicate. + +What CI coverage +================ + +Currently, there are upstream-like builds on treeherder. They are scheduled as +a cron task daily and includes: + + - building opt/debug versions of the snap + - building them on all branches + - running a few selenium-based tests + +The build definitions `are based on docker <https://searchfox.org/mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8/taskcluster/docker/snap-coreXX-build/Dockerfile>`_. + +It should be noted that for the moment, all tasks needs to run under docker. +However, this setup is not working for `Snap` since it interacts with `SystemD` +which does not work under `Docker`. This is why the installation is handled by +`the install-snap script +<https://searchfox.org/mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8/taskcluster/docker/snap-coreXX-build/install-snap.sh>`_ +rather than plain `sudo snap install`, and also why we need to run `snap` in +`destructive mode` (which is fine since we are within a docker container). This +does not apply to the tests case which relies on newly-available wayland +virtual machines. + +Outside the build oddities because of the setup, it should be noted that those +builds are as close as possible to upstream. This means: + + - the mozilla-central hash they run against is not matching the source code it + builds from, and one should inspect the build log to see the mercurial clone + step + - it builds using the clang build within the snap definition + +The tests are defined `within the docker subdirectory +<https://searchfox.org/mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8/taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh>`_. +They are using Selenium because this is what was used by pre-existing tests ran +on GitHub Actions from upstream. + +Their coverage is ensuring that we get a basic working browser out of builds. +It includes some tests that previously were manually ran by QA. + +How to hack on try +================== + +Build and test tasks can be explored via ``mach try fuzzy --full`` by searching +for ``'snap 'upstream``. There is a bit of hacking for try to make sure we +actually don't re-download the mercurial repo and directly reuse the clone +generated by `run-task`, handled in the `run.sh script +<https://searchfox.org/mozilla-central/rev/3c72de9280ec57dc55c24886c6334d9e340500e8/taskcluster/docker/snap-coreXX-build/run.sh#61-72>`_. + +So pushing to try is basically just: + +.. code-block:: shell + + $ mach try fuzzy --full -q "'snap 'upstream 'try" + +Because of the build process, a full opt build will take around 1h45-2h while a +debug build will be around 60 minutes, the difference coming from the use of +PGO on opt builds. diff --git a/build/docs/sparse.rst b/build/docs/sparse.rst new file mode 100644 index 0000000000..6dcf548334 --- /dev/null +++ b/build/docs/sparse.rst @@ -0,0 +1,157 @@ +.. _build_sparse: + +================ +Sparse Checkouts +================ + +The Firefox repository is large: over 230,000 files. That many files +can put a lot of strain on machines, tools, and processes. + +Some version control tools have the ability to only populate a +working directory / checkout with a subset of files in the repository. +This is called *sparse checkout*. + +Various tools in the Firefox repository are configured to work +when a sparse checkout is being used. + +Sparse Checkouts in Mercurial +============================= + +Mercurial 4.3 introduced **experimental** support for sparse checkouts +in the official distribution (a Facebook-authored extension has +implemented the feature as a 3rd party extension for years). + +To enable sparse checkout support in Mercurial, enable the ``sparse`` +extension:: + + [extensions] + sparse = + +The *sparseness* of the working directory is managed using +``hg debugsparse``. Run ``hg help debugsparse`` and ``hg help -e sparse`` +for more info on the feature. + +When a *sparse config* is enabled, the working directory only contains +files matching that config. You cannot ``hg add`` or ``hg remove`` files +outside the *sparse config*. + +.. warning:: + + Sparse support in Mercurial 4.3 does not have any backwards + compatibility guarantees. Expect things to change. Scripting against + commands or relying on behavior is strongly discouraged. + +In-Tree Sparse Profiles +======================= + +Mercurial supports defining the sparse config using files under version +control. These are called *sparse profiles*. + +Essentially, the sparse profiles are managed just like any other file in +the repository. When you ``hg update``, the sparse configuration is +evaluated against the sparse profile at the revision being updated to. +From an end-user perspective, you just need to *activate* a profile once +and files will be added or removed as appropriate whenever the versioned +profile file updates. + +In the Firefox repository, the ``build/sparse-profiles`` directory +contains Mercurial *sparse profiles* files. + +Each *sparse profile* essentially defines a list of file patterns +(see ``hg help patterns``) to include or exclude. See +``hg help -e sparse`` for more. + +Mach Support for Sparse Checkouts +================================= + +``mach`` detects when a sparse checkout is being used and its +behavior may vary to accommodate this. + +By default it is a fatal error if ``mach`` can't load one of the +``mach_commands.py`` files it was told to. But if a sparse checkout +is being used, ``mach`` assumes that file isn't part of the sparse +checkout and to ignore missing file errors. This means that +running ``mach`` inside a sparse checkout will only have access +to the commands defined in files in the sparse checkout. + +Sparse Checkouts in Automation +============================== + +``hg robustcheckout`` (the extension/command used to perform clones +and working directory operations in automation) supports sparse checkout. +However, it has a number of limitations over Mercurial's default sparse +checkout implementation: + +* Only supports 1 profile at a time +* Does not support non-profile sparse configs +* Does not allow transitioning from a non-sparse to sparse checkout or + vice-versa + +These restrictions ensure that any sparse working directory populated by +``hg robustcheckout`` is as consistent and robust as possible. + +``run-task`` (the low-level script for *bootstrapping* tasks in +automation) has support for sparse checkouts. + +TaskGraph tasks using ``run-task`` can specify a ``sparse-profile`` +attribute in YAML (or in code) to denote the sparse profile file to +use. e.g.:: + + run: + using: run-command + command: <command> + sparse-profile: taskgraph + +This automagically results in ``run-task`` and ``hg robustcheckout`` +using the sparse profile defined in ``build/sparse-profiles/<value>``. + +Pros and Cons of Sparse Checkouts +================================= + +The benefits of sparse checkout are that it makes the repository appear +to be smaller. This means: + +* Less time performing working directory operations -> faster version + control operations +* Fewer files to consult -> faster operations +* Working directories only contain what is needed -> easier to understand + what everything does + +Fewer files in the working directory also contributes to disadvantages: + +* Searching may not yield hits because a file isn't in the sparse + checkout. e.g. a *global* search and replace may not actually be + *global* after all. +* Tools performing filesystem walking or path globbing (e.g. + ``**/*.js``) may fail to find files because they don't exist. +* Various tools and processes make assumptions that all files in the + repository are always available. + +There can also be problems caused by mixing sparse and non-sparse +checkouts. For example, if a process in automation is using sparse +and a local developer is not using sparse, things may work for the +local developer but fail in automation (because a file isn't included +in the sparse configuration and not available to automation. +Furthermore, if environments aren't using exactly the same sparse +configuration, differences can contribute to varying behavior. + +When Should Sparse Checkouts Be Used? +===================================== + +Developers are discouraged from using sparse checkouts for local work +until tools for handling sparse checkouts have improved. In particular, +Mercurial's support for sparse is still experimental and various Firefox +tools make assumptions that all files are available. Developers should +use sparse checkout at their own risk. + +The use of sparse checkouts in automation is a performance versus +robustness trade-off. Use of sparse checkouts will make automation +faster because machines will only have to manage a few thousand files +in a checkout instead of a few hundred thousand. This can potentially +translate to minutes saved per machine day. At the scale of thousands +of machines, the savings can be significant. But adopting sparse +checkouts will open up new avenues for failures. (See section above.) +If a process is isolated (in terms of file access) and well-understood, +sparse checkout can likely be leveraged with little risk. But if a +process is doing things like walking the filesystem and performing +lots of wildcard matching, the dangers are higher. diff --git a/build/docs/supported-configurations.rst b/build/docs/supported-configurations.rst new file mode 100644 index 0000000000..4d6bbb1f79 --- /dev/null +++ b/build/docs/supported-configurations.rst @@ -0,0 +1,166 @@ +Supported Build Hosts and Targets +================================= + + .. role:: strikethrough + +There are three tiers of supported Firefox build hosts and targets. +These tiers represent the shared engineering priorities of the Mozilla project. + +The "build host" is the machine that is performing the build of Firefox, and +the "build target" is the machine that will run the built Firefox application. +For example, if you were building Firefox for Android on your Linux computer, then the +Linux computer would be the "build host". + +.. note:: + + Sheriffs are in charge of monitoring the tree. Their definition for tiers + is for automation jobs, which tells a developer what is expected of them when + they land code. This document is about the tiers of supported build hosts and targets, + which tells a person compiling/using Firefox what they can expect from Mozilla. + See the `job tier definition <https://wiki.mozilla.org/Sheriffing/Job_Visibility_Policy#Overview_of_the_Job_Visibility_Tiers>`__ for more information. + + +.. _build_hosts: + +Supported Build Hosts +--------------------- + +While we want to help users resolve build-related issues on their systems, we +are unable to help resolve build system issues on all possible operating +systems and versions. + +.. _tier_1_hosts: + +Tier-1 Hosts and Toolchains +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Support is available for the following **host operating systems** and versions +when building for a :ref:`Tier-1 Firefox build target<tier_1_targets>`, including +cross-compilation where available: + +* Ubuntu Linux x86_64 + * Current stable release + * Previous stable release + * Current LTS release +* Debian Linux x86_64 + * Current stable release + * Current testing release +* Fedora Linux x86_64 + * Current stable release + * Previous stable release +* macOS Intel and M1 + * Current major macOS release + * Previous major macOS release +* Windows x86_64 + * Windows 10 with MozillaBuild Environment + * Windows 11 with MozillaBuild Environment + +Tier-2 Hosts and Toolchains +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In addition to the limitations outlined above in the Tier-1 list, our ability +to provide assistance with build issues using/targeting Tier-2 +hosts/targets/compilers is not unbounded. + +While we will endeavour to make a best effort to help resolve issues, you may +be referred to the relevant community maintainers for further support. + +The Tier-2 hosts are: + +* Other Linux x86_64 distributions and/or versions +* Older macOS versions +* Older Windows x86_64 versions + +Tier-3 Hosts and Toolchains +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We cannot provide any guarantees of assistance in resolving build issues using +or targeting Tier-3 platforms. + + +Supported Build Targets +----------------------- + +.. _tier_1_targets: + +Tier-1 Targets +^^^^^^^^^^^^^^ + +The term **"Tier-1 platform"** refers to those platforms - CPU +architectures and operating systems - that are the primary focus of +Firefox development efforts. Tier-1 platforms are fully supported by +Mozilla's `continuous integration processes <https://treeherder.mozilla.org/>`__ and the +:ref:`Pushing to Try`. Any proposed change to Firefox on these +platforms that results in build failures, test failures, performance +regressions or other major problems **will be reverted immediately**. + + +The **Tier-1 Firefox platforms** and their supported compilers are: + +- Android on Linux x86, x86-64, ARMv7 and ARMv8-A (clang) +- Linux/x86 and x86-64 (gcc and clang) +- macOS 10.15 and later on x86-64 and AArch64 (clang) +- Windows/x86, x86-64 and AArch64 (clang-cl) + +Prior to Firefox 63, Windows/x86 and Windows/x86-64 relied on the MSVC +compiler; from **Firefox 63 onward MSVC is not supported**. Older 32-bit +x86 CPUs without SSE2 instructions such as the Pentium III and Athlon XP +are also **not considered Tier-1 platforms, and are not supported**. +Note also that while Windows/x86 and ARM/AArch64 are supported *as build +targets*, it is not possible to build Firefox *on* Windows/x86 or +Windows/AArch64 systems. + +Tier-2 Targets +^^^^^^^^^^^^^^ + +**Tier-2 platforms** are actively maintained by the Mozilla community, +though with less rigorous requirements. Proposed changes resulting in +breakage or regressions limited to these platforms **may not immediately +result in reversion**. However, developers who break these platforms are +expected to work with platform maintainers to fix problems, and **may be +required to revert their changes** if a fix cannot be found. + +The **Tier-2 Firefox platforms** and their supported compilers are: + +- Linux/AArch64 (clang) +- Windows/x86 (mingw-clang) - maintained by Tom Ritter and Jacek Caban + - + + - *Note that some features of this platform are disabled, as they + require MS COM or the w32api project doesn't expose the necessary + Windows APIs.* + +Tier-3 Targets +^^^^^^^^^^^^^^ + +**Tier-3 platforms** have a maintainer or community which attempt to +keep the platform working. These platforms are **not supported by our +continuous integration processes**, and **Mozilla does not routinely +test on these platforms**, nor do we block further development on the +outcomes of those tests. + +At any given time a Firefox built from mozilla-central for these +platforms may or may not work correctly or build at all. + +**Tier-3 Firefox platforms** include: + +- Linux on various CPU architectures including ARM variants not listed + above, PowerPC, and x86 CPUs without SSE2 support - maintained by + various Linux distributions +- FreeBSD/x86, x86-64, Aarch64 (clang) - `maintained by gecko@FreeBSD.org <https://www.freshports.org/www/firefox/>`__ +- OpenBSD/x86, x86-64 (clang) - maintained by Landry Breuil +- NetBSD/x86-64 (gcc) - maintained by David Laight +- Solaris/x86-64, sparc64 (gcc) - maintained by Petr Sumbera +- :strikethrough:`Windows/x86-64 (mingw-gcc)` - Unsupported due to + requirements for clang-bindgen + +If you're filing a bug against Firefox on a Tier-3 platform (or any +combination of OS, CPU and compiler not listed above) please bear in +mind that Mozilla developers do not reliably have access to non-Tier-1 +platforms or build environments. To be actionable bug reports against +non-Tier-1 platforms should include as much information as possible to +help the owner of the bug determine the cause of the problem and the +proper solution. If you can provide a patch, a regression range or +assist in verifying that the developer's patches work for your platform, +that would help a lot towards getting your bugs fixed and checked into +the tree. diff --git a/build/docs/telemetry.rst b/build/docs/telemetry.rst new file mode 100644 index 0000000000..7dd24d7df2 --- /dev/null +++ b/build/docs/telemetry.rst @@ -0,0 +1,49 @@ +.. _buildtelemetry: + +=============== +Build Telemetry +=============== + +The build system (specifically, all the build tooling hooked +up to ``./mach``) has been configured to collect metrics data +points and errors for various build system actions. This data +helps drive team planning for the build team and ensure that +resources are applied to build processes that need them most. +You can adjust your telemetry settings by editing your +``~/.mozbuild/machrc`` file. + +Glean Telemetry +=============== + +Mozbuild reports data using `Glean <https://mozilla.github.io/glean/>`_ via +:ref:`mach_telemetry`. The metrics collected are documented :ref:`here<metrics>`. + +Error Reporting +=============== + +``./mach`` uses `Sentry <https://sentry.io/welcome/>`_ +to automatically report errors to `our issue-tracking dashboard +<https://sentry.prod.mozaws.net/operations/mach/>`_. + +Information captured +++++++++++++++++++++ + +Sentry automatically collects useful information surrounding +the error to help the build team discover what caused the +issue and how to reproduce it. This information includes: + +* Environmental information, such as the computer name, timestamp, Python runtime and Python module versions +* Process arguments +* The stack trace of the error, including contextual information: + + * The data contained in the exception + * Functions and their respective source file names, line numbers + * Variables in each frame +* `Sentry "Breadcrumbs" <https://docs.sentry.io/platforms/python/default-integrations/>`_, + which are important events that have happened which help contextualize the error, such as: + + * An HTTP request has occurred + * A subprocess has been spawned + * Logging has occurred + +Note that file paths may be captured, which include absolute paths (potentially including usernames). diff --git a/build/docs/test_certificates.rst b/build/docs/test_certificates.rst new file mode 100644 index 0000000000..ff31f172d4 --- /dev/null +++ b/build/docs/test_certificates.rst @@ -0,0 +1,40 @@ +.. _test_certificates: + +=============================== +Adding Certificates for Testing +=============================== + +Sometimes we need to write tests for scenarios that require custom client, server or certificate authority (CA) certificates. For that purpose, you can generate such certificates using ``build/pgo/genpgocert.py``. + +The certificate specifications (and key specifications) are located in ``build/pgo/certs/``. + +To add a new **server certificate**, add a ``${cert_name}.certspec`` file to that folder. +If it needs a non-default private key, add a corresponding ``${cert_name}.server.keyspec``. + +For a new **client certificate**, add a ``${cert_name}.client.keyspec`` and corresponding ``${cert_name}.certspec``. + +To add a new **CA**, add a ``${cert_name}.ca.keyspec`` as well as a corresponding ``${cert_name}.certspec`` to that folder. + +.. hint:: + + * The full syntax for .certspec files is documented at https://searchfox.org/mozilla-central/source/security/manager/tools/pycert.py + + * The full syntax for .keyspec files is documented at https://searchfox.org/mozilla-central/source/security/manager/tools/pykey.py + +Then regenerate the certificates by running::: + + ./mach python build/pgo/genpgocert.py + +These commands will modify cert9.db and key4.db, and if you have added a .keyspec file will generate a ``{$cert_name}.client`` or ``{$cert_name}.ca`` file. + +**These files need to be committed.** + +If you've created a new server certificate, you probably want to modify ``build/pgo/server-locations.txt`` to add a location with your specified certificate::: + + https://my-test.example.com:443 cert=${cert_name} + +You will need to run ``./mach build`` again afterwards. + +.. important:: + + Make sure to exactly follow the naming conventions and use the same ``cert_name`` in all places diff --git a/build/docs/test_manifests.rst b/build/docs/test_manifests.rst new file mode 100644 index 0000000000..d58cb9090f --- /dev/null +++ b/build/docs/test_manifests.rst @@ -0,0 +1,230 @@ +.. _test_manifests: + +============== +Test Manifests +============== + +Many test suites have their test metadata defined in files called +**test manifests**. + +Test manifests are divided into two flavors: :ref:`manifestparser_manifests` +and :ref:`reftest_manifests`. + +Naming Convention +================= + +The build system does not enforce file naming for test manifest files. +However, the following convention is used. + +mochitest.toml + For the *plain* flavor of mochitests. + +chrome.toml + For the *chrome* flavor of mochitests. + +browser.toml + For the *browser chrome* flavor of mochitests. + +a11y.toml + For the *a11y* flavor of mochitests. + +xpcshell.toml + For *xpcshell* tests. + +.. _manifestparser_manifests: + +ManifestParser Manifests +========================== + +ManifestParser manifests are essentially toml files that conform to a basic +set of assumptions. + +The :doc:`reference documentation </mozbase/manifestparser>` +for manifestparser manifests describes the basic format of test manifests. + +In summary, manifests are toml files with section names describing test files:: + + ["test_foo.js"] + ["test_bar.js"] + +Keys under sections can hold metadata about each test:: + + ["test_foo.js"] + skip-if = ["os == 'win'"] + ["test_foo.js"] + skip-if = ["os == 'linux' && debug"] + ["test_baz.js"] + fail-if = [ + "os == 'mac'", + "os == 'android'", + ] + +There is a special **DEFAULT** section whose keys/metadata apply to all +sections/tests:: + + [DEFAULT] + property = value + + ["test_foo.js"] + +In the above example, **test_foo.js** inherits the metadata **property = value** +from the **DEFAULT** section. + +Recognized Metadata +------------------- + +Test manifests can define some common keys/metadata to influence behavior. +Those keys are as follows: + +head + List of files that will be executed before the test file. (Used in + xpcshell tests.) + +tail + List of files that will be executed after the test file. (Used in + xpcshell tests.) + +support-files + List of additional files required to run tests. This is typically + defined in the **DEFAULT** section. + + Unlike other file lists, *support-files* supports a globbing mechanism + to facilitate pulling in many files with minimal typing. This globbing + mechanism is activated if an entry in this value contains a ``*`` + character. A single ``*`` will wildcard match all files in a directory. + A double ``**`` will descend into child directories. For example, + ``data/*`` will match ``data/foo`` but not ``data/subdir/bar`` where + ``data/**`` will match ``data/foo`` and ``data/subdir/bar``. + + Support files starting with ``/`` are placed in a root directory, rather + than a location determined by the manifest location. For mochitests, + this allows for the placement of files at the server root. The source + file is selected from the base name (e.g., ``foo`` for ``/path/foo``). + Files starting with ``/`` cannot be selected using globbing. + + Some support files are used by tests across multiple directories. In + this case, a test depending on a support file from another directory + must note that dependency with the path to the required support file + in its own **support-files** entry. These use a syntax where paths + starting with ``!/`` will indicate the beginning of the path to a + shared support file starting from the root of the srcdir. For example, + if a manifest at ``dom/base/test/mochitest.toml`` has a support file, + ``dom/base/test/server-script.sjs``, and a mochitest in + ``dom/workers/test`` depends on that support file, the test manifest + at ``dom/workers/test/mochitest.toml`` must include + ``!/dom/base/test/server-script.sjs`` in its **support-files** entry. + +generated-files + List of files that are generated as part of the build and don't exist in + the source tree. + + The build system assumes that each manifest file, test file, and file + listed in **head**, **tail**, and **support-files** is static and + provided by the source tree (and not automatically generated as part + of the build). This variable tells the build system not to make this + assumption. + + This variable will likely go away sometime once all generated files are + accounted for in the build config. + + If a generated file is not listed in this key, a clobber build will + likely fail. + +dupe-manifest + Record that this manifest duplicates another manifest. + + The common scenario is two manifest files will include a shared + manifest file via the ``["include:file"]`` special section. The build + system enforces that each test file is only provided by a single + manifest. Having this key present bypasses that check. + + The value of this key is ignored. + +skip-if + Skip this test if the specified condition is true. + See :ref:`manifest_filter_language`. + + Conditions can be specified on multiple lines, where each line is implicitly + joined by a logical OR (``||``). This makes it easier to add comments to + distinct failures. For example: + + .. parsed-literal:: + + ["test_foo.js"] + skip-if = [ + "os == 'mac' && fission", # bug 123 - fails on fission + "os == 'windows' && debug", # bug 456 - hits an assertion + ] + +fail-if + Expect test failure if the specified condition is true. + See :ref:`manifest_filter_language`. + + Conditions can be specified on multiple lines (see ``skip-if``). + +run-sequentially + If present, the test should not be run in parallel with other tests. + + Some test harnesses support parallel test execution on separate processes + and/or threads (behavior varies by test harness). If this key is present, + the test harness should not attempt to run this test in parallel with any + other test. + + By convention, the value of this key is a string describing why the test + can't be run in parallel. + +scheme + Changes the scheme and domain from which the test runs. (Only used in mochitest suites) + + There are two possible values: + - ``http`` (default): The test will run from http://mochi.test:8888 + - ``https``: The test will run from https://example.com:443 + +.. _manifest_filter_language: + +Manifest Filter Language +------------------------ + +Some manifest keys accept a special filter syntax as their values. These +values are essentially boolean expressions that are evaluated at test +execution time. + +The expressions can reference a well-defined set of variables, such as +``os`` and ``debug``. These variables are populated from the +``mozinfo.json`` file. For the full list of available variables, see +the :ref:`mozinfo documentation <mozinfo_attributes>`. + +See +`the source <https://hg.mozilla.org/mozilla-central/file/default/testing/mozbase/manifestparser/manifestparser/manifestparser.py>`_ for the full documentation of the +expression syntax until it is documented here. + +.. todo:: + + Document manifest filter language. + +.. _manifest_file_installation: + +File Installation +----------------- + +Files referenced by manifests are automatically installed into the object +directory into paths defined in +:py:func:`mozbuild.frontend.emitter.TreeMetadataEmitter._process_test_manifest`. + +Relative paths resolving to parent directory (e.g. +``support-files = ../foo.txt`` have special behavior. + +For ``support-files``, the file will be installed to the default destination +for that manifest. Only the file's base name is used to construct the final +path: directories are irrelevant. Files starting with ``/`` are an exception, +these are installed relative to the root of the destination; the base name is +instead used to select the file.. + +For all other entry types, the file installation is skipped. + +.. _reftest_manifests: + +Reftest Manifests +================= + +See `MDN <https://developer.mozilla.org/en-US/docs/Creating_reftest-based_unit_tests>`_. diff --git a/build/docs/toolchains.rst b/build/docs/toolchains.rst new file mode 100644 index 0000000000..f43972b8f3 --- /dev/null +++ b/build/docs/toolchains.rst @@ -0,0 +1,272 @@ +.. _build_toolchains: + +=========================== +Creating Toolchain Archives +=========================== + +There are various scripts in the repository for producing archives +of the build tools (e.g. compilers and linkers) required to build. + +Clang and Rust +============== + +To modify the toolchains used for a particular task, you may need several +things: + +1. A `build task`_ + +2. Which uses a toolchain task + + - `clang toolchain`_ + - `rust toolchain`_ + +3. Which uses a git fetch + + - `clang fetch`_ + - (from-source ``dev`` builds only) `rust fetch`_ + +4. (clang only) Which uses a `config json`_ + +5. Which takes patches_ you may want to apply. + +For the most part, you should be able to accomplish what you want by +copying/editing the existing examples in those files. + +.. _build task: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/build/linux.yml#5-45 +.. _clang toolchain: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/toolchain/clang.yml#51-72 +.. _rust toolchain: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/toolchain/rust.yml#57-74 +.. _clang fetch: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/fetch/toolchains.yml#413-418 +.. _rust fetch: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/fetch/toolchains.yml#434-439 +.. _config json: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/build/build-clang/clang-linux64.json +.. _patches: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/build/build-clang/static-llvm-symbolizer.patch + +Clang +----- + +Building clang is handled by `build-clang.py`_, which uses several resources +in the `build-clang`_ directory. Read the `build-clang README`_ for more +details. + +Note for local builds: build-clang.py can be run on developer machines but its +lengthy multi-stage build process is unnecessary for most local development. The +upstream `LLVM Getting Started Guide`_ has instructions on how to build +clang more directly. + +.. _build-clang.py: https://searchfox.org/mozilla-central/source/build/build-clang/build-clang.py +.. _build-clang README: https://searchfox.org/mozilla-central/source/build/build-clang/README +.. _build-clang: https://searchfox.org/mozilla-central/source/build/build-clang/ +.. _LLVM Getting Started Guide: https://llvm.org/docs/GettingStarted.html + +Rust +---- + +Rust builds are handled by `repack_rust.py`_. The primary purpose of +that script is to download prebuilt tarballs from the Rust project. + +It uses the same basic format as `rustup` for specifying the toolchain +(via ``--channel``): + +- request a stable build with ``1.xx.y`` (e.g. ``1.47.0``) +- request a beta build with ``beta-yyyy-mm-dd`` (e.g. ``beta-2020-08-26``) +- request a nightly build with ``nightly-yyyy-mm-dd`` (e.g. ``nightly-2020-08-26``) +- request a build from `Rust's ci`_ with ``bors-$sha`` (e.g. ``bors-796a2a9bbe7614610bd67d4cd0cf0dfff0468778``) +- request a from-source build with ``dev`` + +Rust From Source +---------------- + +As of this writing, from-source builds for Rust are a new feature, and not +used anywhere by default. The feature was added so that we can test patches +to rustc against the tree. Expect things to be a bit hacky and limited. + +Most importantly, building from source requires your toolchain to have a +`fetch of the rust tree`_ as well as `clang and binutils toolchains`_. It is also +recommended to upgrade the worker-type to e.g. ``b-linux-large``. + +Rust's build dependencies are fairly minimal, and it has a sanity check +that should catch any missing or too-old dependencies. See the `Rust README`_ +for more details. + +Patches are set via `the --patch flag`_ (passed via ``toolchain/rust.yml``). +Patch paths are assumed to be relative to ``/build/build-rust/``, and may be +optionally prefixed with ``module-path:`` to specify they apply to that git +submodule in the Rust source. e.g. ``--patch src/llvm-project:mypatch.diff`` +patches rust's llvm with ``/build/build-rust/mypatch.diff``. There are no +currently checked in rust patches to use as an example, but they should be +the same format as `the clang ones`_. + +Rust builds are not currently configurable, and uses a `hardcoded config.toml`_, +which you may need to edit for your purposes. See Rust's `example config`_ for +details/defaults. Note that these options do occasionally change, so be sure +you're using options for the version you're targeting. For instance, there was +a large change around Rust ~1.48, and the currently checked in config was for +1.47, so it may not work properly when building the latest version of Rust. + +Rust builds are currently limited to targeting only the host platform. +Although the machinery is in place to request additional targets, the +cross-compilation fails for some unknown reason. We have not yet investigated +what needs to be done to get this working. + +While Rust generally maintains a clean tree for building ``rustc`` and +``cargo``, other tools like ``rustfmt`` or ``miri`` are allowed to be +transiently broken. This means not every commit in the Rust tree will be +able to build the `tools we require`_. + +Although ``repack_rust`` considers ``rustfmt`` an optional package, Rust builds +do not currently implement this and will fail if ``rustfmt`` is busted. Some +attempt was made to work around it, but `more work is needed`_. + +.. _Rust's ci: https://github.com/rust-lang/rust/pull/77875#issuecomment-736092083 +.. _repack_rust.py: https://searchfox.org/mozilla-central/source/taskcluster/scripts/misc/repack_rust.py +.. _fetch of the rust tree: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/toolchain/rust.yml#69-71 +.. _clang and binutils toolchains: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/ci/toolchain/rust.yml#72-74 +.. _the --patch flag: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/scripts/misc/repack_rust.py#667-675 +.. _the clang ones: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/build/build-clang/static-llvm-symbolizer.patch +.. _Rust README: https://github.com/rust-lang/rust/#building-on-a-unix-like-system +.. _hardcoded config.toml: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/scripts/misc/repack_rust.py#384-421 +.. _example config: https://github.com/rust-lang/rust/blob/b7ebc6b0c1ba3c27ebb17c0b496ece778ef11e18/config.toml.example +.. _tools we require: https://searchfox.org/mozilla-central/rev/168c45a7acc44e9904cfd4eebcb9eb080e05699c/taskcluster/scripts/misc/repack_rust.py#398 +.. _more work is needed: https://github.com/rust-lang/rust/issues/79249 + +Python +------ + +Python is built from source by ``taskcluster/scripts/misc/build-cpython.sh`` on +Linux and OSX. We use the upstream installer on Windows, through +``taskcluster/scripts/misc/pack-cpython.sh``. In order to ensure consistency, we +use the same version for both approaches. Note however that the Windows installer is +not packaged for all patch versions, so there might be a slight delta there. + +Windows +======= + +The ``build/vs/generate_yaml.py`` and ``taskcluster/scripts/misc/get_vs.py`` +scripts are used to manage and get Windows toolchains containing Visual +Studio executables, SDKs, etc. + +The ``build/vs/generate_yaml.py`` script is used to generate one of the +YAML files used in the relevant toolchain task. The exact command line +used to generate the file is stored in the header of the YAML file itself. +Each YAML file records the necessary downloads from Microsoft servers to +install the required Visual Studio components given on the command line. + +The ``taskcluster/scripts/misc/get_vs.py`` script takes a YAML file as +input and fills a directory with the corresponding Visual Studio components. + +Both scripts should be run via ``mach python --virtualenv build``. The +latter is automatically invoked by the bootstrapping mechanism. + + +MacOS +===== + +The ``build/macosx/catalog.py`` and ``taskcluster/scripts/misc/unpack-sdk.py`` +scripts are used to manage and get macOS SDKs. + +The ``build/macosx/catalog.py`` script is used to explore the Apple +software update catalog. Running the script with no argument will show +a complete list of "products". You probably don't want that, but rather +start with a filter: + +.. code-block:: shell + + $ ./mach python build/macosx/catalog.py --filter SDK + 061-44071 Beats Updater 1.0 + 071-29699 Command Line Tools for Xcode 12.5 + 001-89745 Command Line Tools for Xcode 12.4 + 071-54303 Command Line Tools for Xcode 12.5 + 002-41708 Command Line Tools for Xcode 13.2 + 002-83793 Command Line Tools for Xcode 13.4 + 012-92431 Command Line Tools for Xcode 14.2 + 032-64167 Command Line Tools for Xcode 14.3 + +From there, pick the id of the product you're interested in, and run the +script again with that id: + +.. code-block:: shell + + $ ./mach python build/macosx/catalog.py 032-64167 + com.apple.pkg.CLTools_Executables https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_Executables.pkg + com.apple.pkg.CLTools_SDK_macOS13 https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_macOSNMOS_SDK.pkg + com.apple.pkg.CLTools_SDK_macOS12 https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_macOSLMOS_SDK.pkg + com.apple.pkg.CLTools_macOS_SDK https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_macOS_SDK.pkg + com.apple.pkg.CLTools_SwiftBackDeploy https://swcdn.apple.com/content/downloads/38/61/032-64167-A_F8LL7XSTW6/k3kg0uip4kxd3qupgy6y8fzp27mnxdpt6y/CLTools_SwiftBackDeploy.pkg + +From there, pick the id of the package you're interested in, and run the +script again with a combination of both product and package ids to inspect +its content and ensure that's what you're looking for. + +.. code-block:: shell + + $ ./mach python build/macosx/catalog.py 032-64167/com.apple.pkg.CLTools_SDK_macOS13 + Library + Library/Developer + Library/Developer/CommandLineTools + Library/Developer/CommandLineTools/SDKs + Library/Developer/CommandLineTools/SDKs/MacOSX13.sdk + Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk + Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr + (...) + +Once you have found the SDK you want, you can create or update toolchain tasks +in ``taskcluster/ci/toolchain/macosx-sdk.yml``. + +The ``taskcluster/scripts/misc/unpack-sdk.py`` script takes the url of a SDK +package, the sha512 hash for its content, the path to the SDK in the package, +and an output directory, and extracts the package in that directory. + +Both scripts should be run via ``mach python``. The latter is automatically +invoked by the bootstrapping mechanism. + +On automation, the script will download the file from tooltool instead of the +original url, so the file should also be uploaded to tooltool with `internal` +visibility. +See https://github.com/mozilla-releng/tooltool. + +Firefox for Android with Gradle +=============================== + +To build Firefox for Android with Gradle in automation, archives +containing both the Gradle executable and a Maven repository +comprising the exact build dependencies are produced and uploaded to +an internal Mozilla server. The build automation will download, +verify, and extract these archive before building. These archives +provide a self-contained Gradle and Maven repository so that machines +don't need to fetch additional Maven dependencies at build time. +(Gradle and the downloaded Maven dependencies can be both +redistributed publicly.) + +Archiving the Gradle executable is straight-forward, but archiving a +local Maven repository is not. Therefore a toolchain job exists for +producing the required archives, `android-gradle-dependencies`. The +job runs in a container based on a custom Docker image and spawns a +Sonatype Nexus proxying Maven repository process in the background. +The job builds Firefox for Android using Gradle and the in-tree Gradle +configuration rooted at ``build.gradle``. The spawned proxying Maven +repository downloads external dependencies and collects them. After +the Gradle build completes, the job archives the Gradle version used +to build, and the downloaded Maven repository, and exposes them as +Task Cluster artifacts. + +To update the version of Gradle in the archive produced, update +``gradle/wrapper/gradle-wrapper.properties``. Be sure to also update +the SHA256 checksum to prevent poisoning the build machines! + +To update the versions of Gradle dependencies used, update +``dependencies`` sections in the in-tree Gradle configuration rooted +at ``build.gradle``. Once you are confident your changes build +locally, push a fresh build to try. The `android-gradle-dependencies` +toolchain should run automatically, fetching your new dependencies and +wiring them into the appropriate try build jobs. + +To update the version of Sonatype Nexus, update the `sonatype-nexus` +`fetch` task definition. + +To modify the Sonatype Nexus configuration, typically to proxy a new +remote Maven repository, modify +`taskcluster/scripts/misc/android-gradle-dependencies/nexus.xml`. + +There is also a toolchain job that fetches the Android SDK and related +packages. To update the versions of packaged fetched, modify +`python/mozboot/mozboot/android-packages.txt` and update the various +in-tree versions accordingly. diff --git a/build/docs/unified-builds.rst b/build/docs/unified-builds.rst new file mode 100644 index 0000000000..b0e93b9e68 --- /dev/null +++ b/build/docs/unified-builds.rst @@ -0,0 +1,55 @@ +.. _unified-builds: + +============== +Unified Builds +============== + +The Firefox build system uses the technique of "unified builds" (or elsewhere +called "`unity builds <https://en.wikipedia.org/wiki/Unity_build>`_") to +improve compilation performance. Rather than compiling source files individually, +groups of files in the same directory are concatenated together, then compiled once +in a single batch. + +Unified builds can be configured using the ``UNIFIED_SOURCES`` variable in ``moz.build`` files. + +.. _unified_build_compilation_failures: + +Why are there unrelated compilation failures when I change files? +================================================================= + +Since multiple files are concatenated together in a unified build, it's possible for a change +in one file to cause the compilation of a seemingly unrelated file to fail. +This is usually because source files become implicitly dependent on each other for: + +* ``#include`` statements +* ``using namespace ...;`` statements +* Other symbol imports or definitions + +One of the more common cases of unexpected failures are when source code files are added or +removed, and the "chunking" is changed. There's a limit on the number of files that are combined +together for a single compilation, so sometimes the addition of a new file will cause another one +to be bumped into a different chunk. If that other chunk doesn't meet the implicit requirements +of the bumped file, there will be a tough-to-debug compilation failure. + +Building outside of the unified environment +=========================================== + +As described above, unified builds can cause source files to implicitly depend on each other, which +not only causes unexpected build failures but also can cause issues when using source-analysis tools. +To combat this, we'll use a "non-unified" build that attempts to perform a build with as many files compiled +individually as possible. + +To build in the non unified mode, set the following flag in your ``mozconfig``: + +``ac_add_options --disable-unified-build`` + +Other notes: +============ + +* Some IDEs (such as VSCode with ``clangd``) build files in standalone mode, so they may show + more failures than a ``mach build``. +* The amount of files per chunk can be adjusted in ``moz.build`` files with the + ``FILES_PER_UNIFIED_FILE`` variable. Note that changing the chunk size can introduce + compilation failures as described :ref:`above<unified_build_compilation_failures>`. +* We are happy to accept patches that fix problematic unified build chunks (such as by adding + includes or namespace annotations). diff --git a/build/docs/visualstudio.rst b/build/docs/visualstudio.rst new file mode 100644 index 0000000000..7fbab3b87d --- /dev/null +++ b/build/docs/visualstudio.rst @@ -0,0 +1,82 @@ +.. _build_visualstudio: + +====================== +Visual Studio Projects +====================== + +The build system automatically generates Visual Studio project files to aid +with development, as part of a normal ``mach build`` from the command line. + +You can find the solution file at ``$OBJDIR/msvc/mozilla.sln``. + +If you want to generate the project files before/without doing a full build, +running ``./mach configure && ./mach build-backend -b VisualStudio`` will do +so. + + +Structure of Solution +===================== + +The Visual Studio solution consists of hundreds of projects spanning thousands +of files. To help with organization, the solution is divided into the following +trees/folders: + +Build Targets + This folder contains common build targets. The *full* project is used to + perform a full build. The *binaries* project is used to build just binaries. + The *visual-studio* project can be built to regenerate the Visual Studio + project files. + + Performing the *clean* action on any of these targets will clean the + *entire* build output. + +Binaries + This folder contains common binaries that can be executed from within + Visual Studio. If you are building the Firefox desktop application, + the *firefox* project will launch firefox.exe. You probably want one of + these set to your startup project. + +Libraries + This folder contains entries for each static library that is produced as + part of the build. These roughly correspond to each directory in the tree + containing C/C++. e.g. code from ``dom/base`` will be contained in the + ``dom_base`` project. + + These projects don't do anything when built. If you build a project here, + the *binaries* build target project is built. + +Updating Project Files +====================== + +Either re-running ``./mach build`` or ``./mach build-backend -b VisualStudio`` +will update the Visual Studio files after the tree changes. + +Moving Project Files Around +=========================== + +The produced Visual Studio solution and project files should be portable. +If you want to move them to a non-default directory, they should continue +to work from wherever they are. If they don't, please file a bug. + +Invoking mach through Visual Studio +=================================== + +It's possible to run mach commands via Visual Studio. There is some light magic +involved here. + +Alongside the Visual Studio project files is a batch script named ``mach.bat``. +This batch script sets the environment variables present in your *MozillaBuild* +development environment at the time of Visual Studio project generation +and invokes *mach* inside an msys shell with the arguments specified to the +batch script. This script essentially allows you to invoke mach commands +inside the MozillaBuild environment without having to load MozillaBuild. + +Projects currently utilize the ``mach build`` and ``mach clobber`` commands +for building and cleaning the tree respectively. Note that running ``clobber`` +deletes the Visual Studio project files, and running ``build`` recreates them. +This might cause issues while Visual Studio is running. Thus a full rebuild is +currently neither recommended, nor supported, but incremental builds should work. + +The batch script does not limit its use: any mach command can be invoked. +Developers may use this fact to add custom projects and commands that invoke +other mach commands. diff --git a/build/dumbmake-dependencies b/build/dumbmake-dependencies new file mode 100644 index 0000000000..880877637a --- /dev/null +++ b/build/dumbmake-dependencies @@ -0,0 +1,72 @@ +toolkit/library + dom + ipc + security/sandbox + ipc + netwerk/build + netwerk + storage/build + storage + xpcom + chrome + extensions + docshell/build + docshell + uriloader + modules + widget + gfx + toolkit/components/build + toolkit/components + security/manager + security/certverifier + security/build + accessible + dom + content + layout + editor + parser + js/src + mfbt + js/xpconnect + js/xpconnect/loader + view + caps + xpfe/appshell + xpfe/components + js + toolkit + rdf/build + embedding + hal + image/build + image + intl/build + intl + media + profile + services + startupcache + devtools/platform + devtools/server + devtools/shared +browser/app + browser/base + browser/components + devtools/client + browser/locales + browser/modules + browser/themes + toolkit + toolkit/components + toolkit/components/downloads + toolkit/content + toolkit/crashreporter + toolkit/forgetaboutsite + toolkit/identity + toolkit/modules + toolkit/mozapps/extensions + toolkit/profile + toolkit/themes + toolkit/webapps diff --git a/build/gecko_templates.mozbuild b/build/gecko_templates.mozbuild new file mode 100644 index 0000000000..e4c781ce04 --- /dev/null +++ b/build/gecko_templates.mozbuild @@ -0,0 +1,125 @@ +# -*- 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 GeckoBinary(linkage="dependent", mozglue=None): + """Template for Gecko-related binaries. + + This template is meant to be used in other templates. + + `linkage` indicates the wanted xpcom linkage type. Valid values are + 'dependent', 'standalone' or None. 'dependent' is the default. It is + used for e.g. XPCOM components and executables with direct dependencies + on libxul. Most executables should use the 'standalone' linkage, which + uses the standalone XPCOM glue to load libxul. None means no XPCOM glue + or libxul linkage at all. + + `mozglue` indicates whether to link against the mozglue library, and if + so, what linkage to apply. Valid values are None (mozglue not linked), + 'program' (mozglue linked to an executable program), or 'library' (mozglue + linked to a shared library). + """ + if linkage == "dependent": + USE_LIBS += [ + "nspr", + "xul-real", + ] + elif linkage == "standalone": + DEFINES["XPCOM_GLUE"] = True + + USE_LIBS += [ + "xpcomglue", + ] + elif linkage != None: + error('`linkage` must be "dependent", "standalone" or None') + + if mozglue: + if mozglue == "program": + USE_LIBS += ["mozglue"] + DEFINES["MOZ_HAS_MOZGLUE"] = True + if CONFIG["MOZ_GLUE_IN_PROGRAM"] and CONFIG["CC_TYPE"] in ("clang", "gcc"): + LDFLAGS += ["-rdynamic"] + elif mozglue == "library": + LIBRARY_DEFINES["MOZ_HAS_MOZGLUE"] = True + if not CONFIG["MOZ_GLUE_IN_PROGRAM"]: + USE_LIBS += ["mozglue"] + else: + error('`mozglue` must be "program" or "library"') + + +@template +def GeckoProgram(name, linkage="standalone", **kwargs): + """Template for program executables related to Gecko. + + `name` identifies the executable base name. + + See the documentation for `GeckoBinary` for other possible arguments, + with the notable difference that the default for `linkage` is 'standalone'. + """ + Program(name) + + kwargs.setdefault("mozglue", "program") + + GeckoBinary(linkage=linkage, **kwargs) + + +@template +def GeckoSimplePrograms(names, **kwargs): + """Template for simple program executables related to Gecko. + + `names` identifies the executable base names for each executable. + + See the documentation for `GeckoBinary` for other possible arguments. + """ + SimplePrograms(names) + + kwargs.setdefault("mozglue", "program") + + GeckoBinary(**kwargs) + + +@template +def GeckoCppUnitTests(names, **kwargs): + """Template for C++ unit tests related to Gecko. + + `names` identifies the executable base names for each executable. + + See the documentation for `GeckoBinary` for other possible arguments. + """ + CppUnitTests(names) + + kwargs.setdefault("mozglue", "program") + + GeckoBinary(**kwargs) + + +@template +def GeckoSharedLibrary(name, output_category=None, **kwargs): + """Template for shared libraries related to Gecko. + + `name` identifies the library base name. + See the documentation for `GeckoBinary` for other possible arguments. + """ + SharedLibrary(name, output_category) + + kwargs.setdefault("mozglue", "library") + + GeckoBinary(**kwargs) + + +@template +def GeckoFramework(name, output_category=None, **kwargs): + """Template for OSX frameworks related to Gecko. + + `name` identifies the library base name. + See the documentation for `GeckoBinary` for other possible arguments. + """ + Framework(name, output_category) + + kwargs.setdefault("mozglue", "library") + + GeckoBinary(**kwargs) diff --git a/build/gen_symverscript.py b/build/gen_symverscript.py new file mode 100644 index 0000000000..d1a5abd07d --- /dev/null +++ b/build/gen_symverscript.py @@ -0,0 +1,24 @@ +# -*- 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 sys + +from mozbuild.preprocessor import Preprocessor + + +def main(output, input_file, version): + pp = Preprocessor() + pp.context.update( + { + "VERSION": version, + } + ) + pp.out = output + pp.do_include(input_file) + + +if __name__ == "__main__": + main(*sys.agv[1:]) diff --git a/build/gen_test_packages_manifest.py b/build/gen_test_packages_manifest.py new file mode 100644 index 0000000000..162f4e8420 --- /dev/null +++ b/build/gen_test_packages_manifest.py @@ -0,0 +1,125 @@ +#!/usr/bin/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/. + +import json +from argparse import ArgumentParser + +ALL_HARNESSES = [ + "common", # Harnesses without a specific package will look here. + "condprof", + "mochitest", + "reftest", + "xpcshell", + "cppunittest", + "jittest", + "mozbase", + "web-platform", + "talos", + "raptor", + "awsy", + "gtest", + "updater-dep", + "jsreftest", + "perftests", + "fuzztest", +] + +PACKAGE_SPECIFIED_HARNESSES = [ + "condprof", + "cppunittest", + "mochitest", + "reftest", + "xpcshell", + "web-platform", + "talos", + "raptor", + "awsy", + "updater-dep", + "jittest", + "jsreftest", + "perftests", + "fuzztest", +] + +# These packages are not present for every build configuration. +OPTIONAL_PACKAGES = [ + "gtest", +] + + +def parse_args(): + parser = ArgumentParser( + description="Generate a test_packages.json file to tell automation which harnesses " + "require which test packages." + ) + parser.add_argument( + "--common", + required=True, + action="store", + dest="tests_common", + help='Name of the "common" archive, a package to be used by all ' "harnesses.", + ) + parser.add_argument( + "--jsshell", + required=True, + action="store", + dest="jsshell", + help="Name of the jsshell zip.", + ) + for harness in PACKAGE_SPECIFIED_HARNESSES: + parser.add_argument( + "--%s" % harness, + required=True, + action="store", + dest=harness, + help="Name of the %s zip." % harness, + ) + for harness in OPTIONAL_PACKAGES: + parser.add_argument( + "--%s" % harness, + required=False, + action="store", + dest=harness, + help="Name of the %s zip." % harness, + ) + parser.add_argument( + "--dest-file", + required=True, + action="store", + dest="destfile", + help="Path to the output file to be written.", + ) + return parser.parse_args() + + +def generate_package_data(args): + # Generate a dictionary mapping test harness names (exactly as they're known to + # mozharness and testsuite-targets.mk, ideally) to the set of archive names that + # harness depends on to run. + # mozharness will use this file to determine what test zips to download, + # which will be an optimization once parts of the main zip are split to harness + # specific zips. + tests_common = args.tests_common + jsshell = args.jsshell + + harness_requirements = dict([(k, [tests_common]) for k in ALL_HARNESSES]) + harness_requirements["jittest"].append(jsshell) + harness_requirements["jsreftest"].append(args.reftest) + harness_requirements["common"].append("target.condprof.tests.tar.gz") + for harness in PACKAGE_SPECIFIED_HARNESSES + OPTIONAL_PACKAGES: + pkg_name = getattr(args, harness, None) + if pkg_name is None: + continue + harness_requirements[harness].append(pkg_name) + harness_requirements[harness].append("target.condprof.tests.tar.gz") + return harness_requirements + + +if __name__ == "__main__": + args = parse_args() + packages_data = generate_package_data(args) + with open(args.destfile, "w") as of: + json.dump(packages_data, of, indent=4) diff --git a/build/gyp.mozbuild b/build/gyp.mozbuild new file mode 100644 index 0000000000..4337ac473b --- /dev/null +++ b/build/gyp.mozbuild @@ -0,0 +1,109 @@ +# -*- 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/. + +include("gyp_base.mozbuild") + +gyp_vars.update( + { + "lsan": 0, + "asan": 0, + "tsan": 1 if CONFIG["MOZ_TSAN"] else 0, + "ubsan": 0, + "fuzzing": 1 if CONFIG["FUZZING"] else 0, + "libfuzzer": 1 if CONFIG["LIBFUZZER"] else 0, + "libfuzzer_fuzzer_no_link_flag": 1 + if CONFIG["HAVE_LIBFUZZER_FLAG_FUZZER_NO_LINK"] + else 0, + "build_with_mozilla": 1, + "build_with_chromium": 0, + # 10.9 once we move to TC cross-compiles - bug 1270217 + "mac_sdk_min": "10.9", + "mac_deployment_target": "10.9", + "use_official_google_api_keys": 0, + "have_clock_monotonic": 1 if CONFIG["HAVE_CLOCK_MONOTONIC"] else 0, + "have_ethtool_cmd_speed_hi": 1 + if CONFIG["MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI"] + else 0, + "include_alsa_audio": 1 if CONFIG["MOZ_ALSA"] else 0, + "include_pulse_audio": 1 if CONFIG["MOZ_PULSEAUDIO"] else 0, + # basic stuff for everything + "include_internal_video_render": 0, + "clang": 1 if CONFIG["CC_TYPE"] == "clang" else 0, + "clang_cl": 1 if CONFIG["CC_TYPE"] == "clang-cl" else 0, + "clang_use_chrome_plugins": 0, + "enable_protobuf": 0, + "include_tests": 0, + "enable_android_opensl": 1, + "enable_android_opensl_output": 0, + # use_system_lib* still seems to be in use in trunk/build + "use_system_libjpeg": 0, + "use_system_libvpx": 0, + "build_json": 0, + "build_libjpeg": 0, + "build_libyuv": 0, + "build_libvpx": 0, + "build_libevent": 0, + "build_ssl": 0, + "build_json": 0, + "build_icu": 0, + "build_opus": 0, + "libyuv_dir": "/media/libyuv/libyuv", + # don't use openssl + "use_openssl": 0, + # Must match build/gyp.mozbuild WEBRTC_BUILD_LIBEVENT + #'enable_libevent': 0, default according to OS + "debug": 1 if CONFIG["DEBUG"] else 0, + "use_x11": 1 if CONFIG["MOZ_X11"] else 0, + "use_glib": 1 if CONFIG["GLIB_LIBS"] else 0, + # bug 1373485 - avoid pkg-config for gtk2 in webrtc + "use_gtk": 0, + # turn off mandatory use of NEON and instead use NEON detection + "arm_neon": 0, + "arm_neon_optional": 1, + # (for vp8) chromium sets to 0 also + "use_temporal_layers": 0, + # Creates AEC internal sample dump files in current directory + "aec_debug_dump": 1, + # codec enable/disables: + "include_g711": 1, + "include_opus": 1, + "include_g722": 1, + "include_ilbc": 0, + # We turn on ISAC because the AGC uses parts of it, and depend on the + # linker to throw away uneeded bits. + "include_isac": 1, + "include_pcm16b": 1, + #'rtc_opus_variable_complexity': 1, + "apm_debug_dump": 1, + } +) + +if os == "Android": + gyp_vars.update(gtest_target_type="executable") + +if CONFIG["ARM_ARCH"]: + if int(CONFIG["ARM_ARCH"]) < 7: + gyp_vars["armv7"] = 0 + gyp_vars["arm_neon_optional"] = 0 + elif os == "Android": + gyp_vars["armv7"] = 1 + gyp_vars["arm_neon"] = 1 + gyp_vars["build_with_neon"] = 1 + else: + # CPU detection for ARM works on Android only. armv7 always uses CPU + # detection, so we have to set armv7=0 for non-Android target + gyp_vars["armv7"] = 0 + # For libyuv + gyp_vars["arm_version"] = int(CONFIG["ARM_ARCH"]) + +if CONFIG["MACOS_SDK_DIR"]: + gyp_vars["mac_sdk_path"] = CONFIG["MACOS_SDK_DIR"] + +if not CONFIG["MOZ_SYSTEM_LIBVPX"]: + gyp_vars["libvpx_dir"] = "/media/libvpx/libvpx" + +if not CONFIG["MOZ_SYSTEM_LIBEVENT"]: + gyp_vars["libevent_dir"] = "/ipc/chromium/src/third_party/libevent" diff --git a/build/gyp_base.mozbuild b/build/gyp_base.mozbuild new file mode 100644 index 0000000000..17b649be4e --- /dev/null +++ b/build/gyp_base.mozbuild @@ -0,0 +1,39 @@ +# -*- 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/. + +gyp_vars = {} + +os = CONFIG["OS_TARGET"] + +if os == "WINNT": + gyp_vars.update( + MSVS_VERSION=CONFIG["MSVS_VERSION"], + MSVS_OS_BITS=64 if CONFIG["HAVE_64BIT_BUILD"] else 32, + ) + +flavors = { + "WINNT": "win", + "Android": "android", + "Linux": "linux", + "Darwin": "mac" if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa" else "ios", + "SunOS": "solaris", + "GNU/kFreeBSD": "freebsd", + "DragonFly": "dragonfly", + "FreeBSD": "freebsd", + "NetBSD": "netbsd", + "OpenBSD": "openbsd", +} +gyp_vars["OS"] = flavors.get(os) + +arches = { + "x86_64": "x64", + "x86": "ia32", + "aarch64": "arm64", + "ppc64": "ppc64le" if CONFIG["TARGET_ENDIANNESS"] == "little" else "ppc64", +} + +gyp_vars["host_arch"] = arches.get(CONFIG["HOST_CPU_ARCH"], CONFIG["HOST_CPU_ARCH"]) +gyp_vars["target_arch"] = arches.get(CONFIG["TARGET_CPU"], CONFIG["TARGET_CPU"]) diff --git a/build/gyp_includes/common.gypi b/build/gyp_includes/common.gypi new file mode 100644 index 0000000000..457059e446 --- /dev/null +++ b/build/gyp_includes/common.gypi @@ -0,0 +1,3589 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# IMPORTANT: +# Please don't directly include this file if you are building via gyp_chromium, +# since gyp_chromium is automatically forcing its inclusion. +{ + # Variables expected to be overriden on the GYP command line (-D) or by + # ~/.gyp/include.gypi. + 'variables': { + # Putting a variables dict inside another variables dict looks kind of + # weird. This is done so that 'host_arch', 'chromeos', etc are defined as + # variables within the outer variables dict here. This is necessary + # to get these variables defined for the conditions within this variables + # dict that operate on these variables. + 'variables': { + 'variables': { + 'variables': { + 'variables': { + # Whether we're building a ChromeOS build. + 'chromeos%': 0, + + # Whether or not we are using the Aura windowing framework. + 'use_aura%': 0, + + # Whether or not we are building the Ash shell. + 'use_ash%': 0, + }, + # Copy conditionally-set variables out one scope. + 'chromeos%': '<(chromeos)', + 'use_aura%': '<(use_aura)', + 'use_ash%': '<(use_ash)', + + # Whether we are using Views Toolkit + 'toolkit_views%': 0, + + # Use OpenSSL instead of NSS. Under development: see http://crbug.com/62803 + 'use_openssl%': 0, + + 'use_ibus%': 0, + + # Disable viewport meta tag by default. + 'enable_viewport%': 0, + + # Enable HiDPI support. + 'enable_hidpi%': 0, + + # Enable touch optimized art assets and metrics. + 'enable_touch_ui%': 0, + + # Is this change part of the android upstream bringup? + # Allows us to *temporarily* disable certain things for + # staging. Only set to 1 in a GYP_DEFINES. + 'android_upstream_bringup%': 0, + + # Override buildtype to select the desired build flavor. + # Dev - everyday build for development/testing + # Official - release build (generally implies additional processing) + # TODO(mmoss) Once 'buildtype' is fully supported (e.g. Windows gyp + # conversion is done), some of the things which are now controlled by + # 'branding', such as symbol generation, will need to be refactored + # based on 'buildtype' (i.e. we don't care about saving symbols for + # non-Official # builds). + 'buildtype%': 'Dev', + + 'conditions': [ + # ChromeOS implies ash. + ['chromeos==1', { + 'use_ash%': 1, + 'use_aura%': 1, + }], + + # For now, Windows builds that |use_aura| should also imply using + # ash. This rule should be removed for the future when Windows is + # using the aura windows without the ash interface. + ['use_aura==1 and OS=="win"', { + 'use_ash%': 1, + }], + ['use_ash==1', { + 'use_aura%': 1, + }], + + # A flag for BSD platforms + ['OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or \ + OS=="openbsd"', { + 'os_bsd%': 1, + }, { + 'os_bsd%': 0, + }], + ], + }, + # Copy conditionally-set variables out one scope. + 'chromeos%': '<(chromeos)', + 'use_aura%': '<(use_aura)', + 'use_ash%': '<(use_ash)', + 'os_bsd%': '<(os_bsd)', + 'use_openssl%': '<(use_openssl)', + 'use_ibus%': '<(use_ibus)', + 'enable_viewport%': '<(enable_viewport)', + 'enable_hidpi%': '<(enable_hidpi)', + 'enable_touch_ui%': '<(enable_touch_ui)', + 'android_upstream_bringup%': '<(android_upstream_bringup)', + 'buildtype%': '<(buildtype)', + + # Sets whether we're building with the Android SDK/NDK (and hence with + # Ant, value 0), or as part of the Android system (and hence with the + # Android build system, value 1). + 'android_build_type%': 0, + + # Compute the architecture that we're building on. + 'conditions': [ + ['OS=="win" or OS=="ios"', { + 'host_arch%': 'ia32', + }, { + # This handles the Unix platforms for which there is some support. + # Anything else gets passed through, which probably won't work very + # well; such hosts should pass an explicit target_arch to gyp. + 'host_arch%': + '<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/;s/i86pc/ia32/")', + }], + + # Set default value of toolkit_views based on OS. + ['OS=="win" or chromeos==1 or use_aura==1', { + 'toolkit_views%': 1, + }, { + 'toolkit_views%': 0, + }], + + # Set toolkit_uses_gtk for the Chromium browser on Linux. + ['(OS=="linux" or OS=="solaris" or os_bsd==1) and use_aura==0', { + 'toolkit_uses_gtk%': 1, + }, { + 'toolkit_uses_gtk%': 0, + }], + + # Enable HiDPI on Mac OS and Chrome OS. + ['OS=="mac" or chromeos==1', { + 'enable_hidpi%': 1, + }], + + # Enable touch UI on Metro. + ['OS=="win"', { + 'enable_touch_ui%': 1, + }], + ], + }, + + # Copy conditionally-set variables out one scope. + 'chromeos%': '<(chromeos)', + 'host_arch%': '<(host_arch)', + 'toolkit_views%': '<(toolkit_views)', + 'toolkit_uses_gtk%': '<(toolkit_uses_gtk)', + 'use_aura%': '<(use_aura)', + 'use_ash%': '<(use_ash)', + 'os_bsd%': '<(os_bsd)', + 'use_openssl%': '<(use_openssl)', + 'use_ibus%': '<(use_ibus)', + 'enable_viewport%': '<(enable_viewport)', + 'enable_hidpi%': '<(enable_hidpi)', + 'enable_touch_ui%': '<(enable_touch_ui)', + 'android_upstream_bringup%': '<(android_upstream_bringup)', + 'android_build_type%': '<(android_build_type)', + + # We used to provide a variable for changing how libraries were built. + # This variable remains until we can clean up all the users. + # This needs to be one nested variables dict in so that dependent + # gyp files can make use of it in their outer variables. (Yikes!) + # http://code.google.com/p/chromium/issues/detail?id=83308 + 'library%': 'static_library', + + # Override branding to select the desired branding flavor. + 'branding%': 'Chromium', + + 'buildtype%': '<(buildtype)', + + # Default architecture we're building for is the architecture we're + # building on. + 'target_arch%': '<(host_arch)', + + # This variable tells WebCore.gyp and JavaScriptCore.gyp whether they are + # are built under a chromium full build (1) or a webkit.org chromium + # build (0). + 'inside_chromium_build%': 1, + + # Set to 1 to enable fast builds. It disables debug info for fastest + # compilation. + 'fastbuild%': 0, + + # Set to 1 to enable dcheck in release without having to use the flag. + 'dcheck_always_on%': 0, + + # Disable file manager component extension by default. + 'file_manager_extension%': 0, + + # Python version. + 'python_ver%': '2.6', + + # Set ARM version (for libyuv) + 'arm_version%': 6, + + # Set ARM-v7 compilation flags + 'armv7%': 0, + + # Set Neon compilation flags (only meaningful if armv7==1). + 'arm_neon%': 1, + 'arm_neon_optional%': 0, + + # The system root for cross-compiles. Default: none. + 'sysroot%': '', + + # The system libdir used for this ABI. + 'system_libdir%': 'lib', + + # On Linux, we build with sse2 for Chromium builds. + 'disable_sse2%': 0, + + # Use libjpeg-turbo as the JPEG codec used by Chromium. + 'use_libjpeg_turbo%': 1, + + # Use system libjpeg. Note that the system's libjepg will be used even if + # use_libjpeg_turbo is set. + 'use_system_libjpeg%': 0, + + # Use system libvpx + 'use_system_libvpx%': 0, + + # Variable 'component' is for cases where we would like to build some + # components as dynamic shared libraries but still need variable + # 'library' for static libraries. + # By default, component is set to whatever library is set to and + # it can be overriden by the GYP command line or by ~/.gyp/include.gypi. + 'component%': 'static_library', + + # Set to select the Title Case versions of strings in GRD files. + 'use_titlecase_in_grd_files%': 0, + + # Use translations provided by volunteers at launchpad.net. This + # currently only works on Linux. + 'use_third_party_translations%': 0, + + # Remoting compilation is enabled by default. Set to 0 to disable. + 'remoting%': 1, + + # Configuration policy is enabled by default. Set to 0 to disable. + 'configuration_policy%': 1, + + # Safe browsing is compiled in by default. Set to 0 to disable. + 'safe_browsing%': 1, + + # Speech input is compiled in by default. Set to 0 to disable. + 'input_speech%': 1, + + # Notifications are compiled in by default. Set to 0 to disable. + 'notifications%' : 1, + + # If this is set, the clang plugins used on the buildbot will be used. + # Run tools/clang/scripts/update.sh to make sure they are compiled. + # This causes 'clang_chrome_plugins_flags' to be set. + # Has no effect if 'clang' is not set as well. + 'clang_use_chrome_plugins%': 1, + + # Enable building with ASAN (Clang's -faddress-sanitizer option). + # -faddress-sanitizer only works with clang, but asan=1 implies clang=1 + # See https://sites.google.com/a/chromium.org/dev/developers/testing/addresssanitizer + 'asan%': 0, + + # Enable building with TSAN (Clang's -fthread-sanitizer option). + # -fthread-sanitizer only works with clang, but tsan=1 implies clang=1 + # See http://clang.llvm.org/docs/ThreadSanitizer.html + 'tsan%': 0, + + # Use a modified version of Clang to intercept allocated types and sizes + # for allocated objects. clang_type_profiler=1 implies clang=1. + # See http://dev.chromium.org/developers/deep-memory-profiler/cpp-object-type-identifier + # TODO(dmikurube): Support mac. See http://crbug.com/123758#c11 + 'clang_type_profiler%': 0, + + # Set to true to instrument the code with function call logger. + # See src/third_party/cygprofile/cyg-profile.cc for details. + 'order_profiling%': 0, + + # Use the provided profiled order file to link Chrome image with it. + # This makes Chrome faster by better using CPU cache when executing code. + # This is known as PGO (profile guided optimization). + # See https://sites.google.com/a/google.com/chrome-msk/dev/boot-speed-up-effort + 'order_text_section%' : "", + + # Set to 1 compile with -fPIC cflag on linux. This is a must for shared + # libraries on linux x86-64 and arm, plus ASLR. + 'linux_fpic%': 1, + + # Whether one-click signin is enabled or not. + 'enable_one_click_signin%': 0, + + # Enable Web Intents support in WebKit. + 'enable_web_intents%': 1, + + # Enable Chrome browser extensions + 'enable_extensions%': 1, + + # Enable browser automation. + 'enable_automation%': 1, + + # Enable printing support and UI. + 'enable_printing%': 1, + + # Enable Web Intents web content registration via HTML element + # and WebUI managing such registrations. + 'enable_web_intents_tag%': 0, + + # Webrtc compilation is enabled by default. Set to 0 to disable. + 'enable_webrtc%': 1, + + # PPAPI by default does not support plugins making calls off the main + # thread. Set to 1 to turn on experimental support for out-of-process + # plugins to make call of the main thread. + 'enable_pepper_threading%': 0, + + # Enables use of the session service, which is enabled by default. + # Support for disabling depends on the platform. + 'enable_session_service%': 1, + + # Enables theme support, which is enabled by default. Support for + # disabling depends on the platform. + 'enable_themes%': 1, + + # Uses OEM-specific wallpaper resources on Chrome OS. + 'use_oem_wallpaper%': 0, + + # Enables support for background apps. + 'enable_background%': 1, + + # Enable the task manager by default. + 'enable_task_manager%': 1, + + # Enable FTP support by default. + 'disable_ftp_support%': 0, + + # XInput2 multitouch support is disabled by default (use_xi2_mt=0). + # Setting to non-zero value enables XI2 MT. When XI2 MT is enabled, + # the input value also defines the required XI2 minor minimum version. + # For example, use_xi2_mt=2 means XI2.2 or above version is required. + 'use_xi2_mt%': 0, + + # Use of precompiled headers on Windows. + # + # This is on by default in VS 2010, but off by default for VS + # 2008 because of complications that it can cause with our + # trybots etc. + # + # This variable may be explicitly set to 1 (enabled) or 0 + # (disabled) in ~/.gyp/include.gypi or via the GYP command line. + # This setting will override the default. + # + # Note that a setting of 1 is probably suitable for most or all + # Windows developers using VS 2008, since precompiled headers + # provide a build speedup of 20-25%. There are a couple of + # small workarounds you may need to use when using VS 2008 (but + # not 2010), see + # http://code.google.com/p/chromium/wiki/WindowsPrecompiledHeaders + # for details. + 'chromium_win_pch%': 0, + + # Set this to true when building with Clang. + # See http://code.google.com/p/chromium/wiki/Clang for details. + 'clang%': 0, + + # Enable plug-in installation by default. + 'enable_plugin_installation%': 1, + + # Enable protector service by default. + 'enable_protector_service%': 1, + + # Specifies whether to use canvas_skia.cc in place of platform + # specific implementations of gfx::Canvas. Affects text drawing in the + # Chrome UI. + # TODO(asvitkine): Enable this on all platforms and delete this flag. + # http://crbug.com/105550 + 'use_canvas_skia%': 0, + + # Set to "tsan", "memcheck", or "drmemory" to configure the build to work + # with one of those tools. + 'build_for_tool%': '', + + # Whether tests targets should be run, archived or just have the + # dependencies verified. All the tests targets have the '_run' suffix, + # e.g. base_unittests_run runs the target base_unittests. The test target + # always calls tools/swarm_client/isolate.py. See the script's --help for + # more information and the valid --mode values. Meant to be overriden with + # GYP_DEFINES. + # TODO(maruel): Converted the default from 'check' to 'noop' so work can + # be done while the builders are being reconfigured to check out test data + # files. + 'test_isolation_mode%': 'noop', + # It must not be '<(PRODUCT_DIR)' alone, the '/' is necessary otherwise + # gyp will remove duplicate flags, causing isolate.py to be confused. + 'test_isolation_outdir%': '<(PRODUCT_DIR)/isolate', + + # Force rlz to use chrome's networking stack. + 'force_rlz_use_chrome_net%': 1, + + 'sas_dll_path%': '<(DEPTH)/third_party/platformsdk_win7/files/redist/x86', + 'wix_path%': '<(DEPTH)/third_party/wix', + + 'conditions': [ + # TODO(epoger): Figure out how to set use_skia=1 for Mac outside of + # the 'conditions' clause. Initial attempts resulted in chromium and + # webkit disagreeing on its setting. + ['OS=="mac"', { + 'use_skia%': 1, + }, { + 'use_skia%': 1, + }], + + # A flag for POSIX platforms + ['OS=="win"', { + 'os_posix%': 0, + }, { + 'os_posix%': 1, + }], + + # NSS usage. + ['(OS=="linux" or OS=="solaris" or os_bsd==1) and use_openssl==0', { + 'use_nss%': 1, + }, { + 'use_nss%': 0, + }], + + # Flags to use X11 on non-Mac POSIX platforms + ['OS=="win" or OS=="mac" or OS=="ios" or OS=="android"', { + 'use_glib%': 0, + 'use_x11%': 0, + }, { + 'use_glib%': 1, + 'use_x11%': 1, + }], + + # We always use skia text rendering in Aura on Windows, since GDI + # doesn't agree with our BackingStore. + # TODO(beng): remove once skia text rendering is on by default. + ['use_aura==1 and OS=="win"', { + 'enable_skia_text%': 1, + }], + + # A flag to enable or disable our compile-time dependency + # on gnome-keyring. If that dependency is disabled, no gnome-keyring + # support will be available. This option is useful + # for Linux distributions and for Aura. + ['chromeos==1 or use_aura==1', { + 'use_gnome_keyring%': 0, + }, { + 'use_gnome_keyring%': 1, + }], + + ['toolkit_uses_gtk==1 or OS=="mac" or OS=="ios"', { + # GTK+, Mac and iOS want Title Case strings + 'use_titlecase_in_grd_files%': 1, + }], + + # Enable file manager extension on Chrome OS. + ['chromeos==1', { + 'file_manager_extension%': 1, + }, { + 'file_manager_extension%': 0, + }], + + ['OS=="win" or OS=="mac" or (OS=="linux" and use_aura==0)', { + 'enable_one_click_signin%': 1, + }], + + ['OS=="android"', { + 'enable_extensions%': 0, + 'enable_printing%': 0, + 'enable_themes%': 0, + 'enable_webrtc%': 0, + 'proprietary_codecs%': 1, + 'remoting%': 0, + }], + + ['OS=="ios"', { + 'configuration_policy%': 0, + 'disable_ftp_support%': 1, + 'enable_automation%': 0, + 'enable_extensions%': 0, + 'enable_printing%': 0, + 'enable_themes%': 0, + 'enable_webrtc%': 0, + 'notifications%': 0, + 'remoting%': 0, + }], + + # Use GPU accelerated cross process image transport by default + # on linux builds with the Aura window manager + ['use_aura==1 and OS=="linux"', { + 'ui_compositor_image_transport%': 1, + }, { + 'ui_compositor_image_transport%': 0, + }], + + # Turn precompiled headers on by default for VS 2010. + ['OS=="win" and MSVS_VERSION=="2010" and buildtype!="Official"', { + 'chromium_win_pch%': 1 + }], + + ['use_aura==1 or chromeos==1 or OS=="android"', { + 'enable_plugin_installation%': 0, + }, { + 'enable_plugin_installation%': 1, + }], + + ['OS=="android" or OS=="ios"', { + 'enable_protector_service%': 0, + }, { + 'enable_protector_service%': 1, + }], + + # linux_use_gold_binary: whether to use the binary checked into + # third_party/gold. + ['OS=="linux"', { + 'linux_use_gold_binary%': 1, + }, { + 'linux_use_gold_binary%': 0, + }], + + # linux_use_gold_flags: whether to use build flags that rely on gold. + # On by default for x64 Linux. Temporarily off for ChromeOS as + # it failed on a buildbot. + ['OS=="linux" and chromeos==0', { + 'linux_use_gold_flags%': 1, + }, { + 'linux_use_gold_flags%': 0, + }], + + ['OS=="android"', { + 'enable_captive_portal_detection%': 0, + }, { + 'enable_captive_portal_detection%': 1, + }], + + # Enable Skia UI text drawing incrementally on different platforms. + # http://crbug.com/105550 + # + # On Aura, this allows per-tile painting to be used in the browser + # compositor. + ['OS!="mac" and OS!="android"', { + 'use_canvas_skia%': 1, + }], + + ['chromeos==1', { + # When building for ChromeOS we dont want Chromium to use libjpeg_turbo. + 'use_libjpeg_turbo%': 0, + }], + + ['OS=="android"', { + # When building as part of the Android system, use system libraries + # where possible to reduce ROM size. + 'use_system_libjpeg%': '<(android_build_type)', + }], + ], + + # Set this to 1 to use the Google-internal file containing + # official API keys for Google Chrome even in a developer build. + # Setting this variable explicitly to 1 will cause your build to + # fail if the internal file is missing. + # + # Set this to 0 to not use the internal file, even when it + # exists in your checkout. + # + # Leave set to 2 to have this variable implicitly set to 1 if + # you have src/google_apis/internal/google_chrome_api_keys.h in + # your checkout, and implicitly set to 0 if not. + # + # Note that official builds always behave as if this variable + # was explicitly set to 1, i.e. they always use official keys, + # and will fail to build if the internal file is missing. + 'use_official_google_api_keys%': 2, + + # Set these to bake the specified API keys and OAuth client + # IDs/secrets into your build. + # + # If you create a build without values baked in, you can instead + # set environment variables to provide the keys at runtime (see + # src/google_apis/google_api_keys.h for details). Features that + # require server-side APIs may fail to work if no keys are + # provided. + # + # Note that if you are building an official build or if + # use_official_google_api_keys has been set to 1 (explicitly or + # implicitly), these values will be ignored and the official + # keys will be used instead. + 'google_api_key%': '', + 'google_default_client_id%': '', + 'google_default_client_secret%': '', + }, + + # Copy conditionally-set variables out one scope. + 'branding%': '<(branding)', + 'buildtype%': '<(buildtype)', + 'target_arch%': '<(target_arch)', + 'host_arch%': '<(host_arch)', + 'library%': 'static_library', + 'toolkit_views%': '<(toolkit_views)', + 'ui_compositor_image_transport%': '<(ui_compositor_image_transport)', + 'use_aura%': '<(use_aura)', + 'use_ash%': '<(use_ash)', + 'use_openssl%': '<(use_openssl)', + 'use_ibus%': '<(use_ibus)', + 'use_nss%': '<(use_nss)', + 'os_bsd%': '<(os_bsd)', + 'os_posix%': '<(os_posix)', + 'use_glib%': '<(use_glib)', + 'toolkit_uses_gtk%': '<(toolkit_uses_gtk)', + 'use_skia%': '<(use_skia)', + 'use_x11%': '<(use_x11)', + 'use_gnome_keyring%': '<(use_gnome_keyring)', + 'linux_fpic%': '<(linux_fpic)', + 'enable_pepper_threading%': '<(enable_pepper_threading)', + 'chromeos%': '<(chromeos)', + 'enable_viewport%': '<(enable_viewport)', + 'enable_hidpi%': '<(enable_hidpi)', + 'enable_touch_ui%': '<(enable_touch_ui)', + 'use_xi2_mt%':'<(use_xi2_mt)', + 'file_manager_extension%': '<(file_manager_extension)', + 'inside_chromium_build%': '<(inside_chromium_build)', + 'fastbuild%': '<(fastbuild)', + 'dcheck_always_on%': '<(dcheck_always_on)', + 'python_ver%': '<(python_ver)', + 'arm_version%': '<(arm_version)', + 'armv7%': '<(armv7)', + 'arm_neon%': '<(arm_neon)', + 'arm_neon_optional%': '<(arm_neon_optional)', + 'sysroot%': '<(sysroot)', + 'system_libdir%': '<(system_libdir)', + 'component%': '<(component)', + 'use_titlecase_in_grd_files%': '<(use_titlecase_in_grd_files)', + 'use_third_party_translations%': '<(use_third_party_translations)', + 'remoting%': '<(remoting)', + 'enable_one_click_signin%': '<(enable_one_click_signin)', + 'enable_webrtc%': '<(enable_webrtc)', + 'chromium_win_pch%': '<(chromium_win_pch)', + 'configuration_policy%': '<(configuration_policy)', + 'safe_browsing%': '<(safe_browsing)', + 'input_speech%': '<(input_speech)', + 'notifications%': '<(notifications)', + 'clang_use_chrome_plugins%': '<(clang_use_chrome_plugins)', + 'asan%': '<(asan)', + 'tsan%': '<(tsan)', + 'clang_type_profiler%': '<(clang_type_profiler)', + 'order_profiling%': '<(order_profiling)', + 'order_text_section%': '<(order_text_section)', + 'enable_extensions%': '<(enable_extensions)', + 'enable_web_intents%': '<(enable_web_intents)', + 'enable_web_intents_tag%': '<(enable_web_intents_tag)', + 'enable_plugin_installation%': '<(enable_plugin_installation)', + 'enable_protector_service%': '<(enable_protector_service)', + 'enable_session_service%': '<(enable_session_service)', + 'enable_themes%': '<(enable_themes)', + 'use_oem_wallpaper%': '<(use_oem_wallpaper)', + 'enable_background%': '<(enable_background)', + 'linux_use_gold_binary%': '<(linux_use_gold_binary)', + 'linux_use_gold_flags%': '<(linux_use_gold_flags)', + 'use_canvas_skia%': '<(use_canvas_skia)', + 'test_isolation_mode%': '<(test_isolation_mode)', + 'test_isolation_outdir%': '<(test_isolation_outdir)', + 'enable_automation%': '<(enable_automation)', + 'enable_printing%': '<(enable_printing)', + 'enable_captive_portal_detection%': '<(enable_captive_portal_detection)', + 'disable_ftp_support%': '<(disable_ftp_support)', + 'force_rlz_use_chrome_net%': '<(force_rlz_use_chrome_net)', + 'enable_task_manager%': '<(enable_task_manager)', + 'sas_dll_path%': '<(sas_dll_path)', + 'wix_path%': '<(wix_path)', + 'android_upstream_bringup%': '<(android_upstream_bringup)', + 'use_libjpeg_turbo%': '<(use_libjpeg_turbo)', + 'use_system_libjpeg%': '<(use_system_libjpeg)', + 'android_build_type%': '<(android_build_type)', + 'use_official_google_api_keys%': '<(use_official_google_api_keys)', + 'google_api_key%': '<(google_api_key)', + 'google_default_client_id%': '<(google_default_client_id)', + 'google_default_client_secret%': '<(google_default_client_secret)', + + # Use system yasm instead of bundled one. + 'use_system_yasm%': 0, + + # Default to enabled PIE; this is important for ASLR but we may need to be + # able to turn it off for various reasons. + 'linux_disable_pie%': 0, + + # The release channel that this build targets. This is used to restrict + # channel-specific build options, like which installer packages to create. + # The default is 'all', which does no channel-specific filtering. + 'channel%': 'all', + + # Override chromium_mac_pch and set it to 0 to suppress the use of + # precompiled headers on the Mac. Prefix header injection may still be + # used, but prefix headers will not be precompiled. This is useful when + # using distcc to distribute a build to compile slaves that don't + # share the same compiler executable as the system driving the compilation, + # because precompiled headers rely on pointers into a specific compiler + # executable's image. Setting this to 0 is needed to use an experimental + # Linux-Mac cross compiler distcc farm. + 'chromium_mac_pch%': 1, + + # The default value for mac_strip in target_defaults. This cannot be + # set there, per the comment about variable% in a target_defaults. + 'mac_strip_release%': 1, + + # Set to 1 to enable code coverage. In addition to build changes + # (e.g. extra CFLAGS), also creates a new target in the src/chrome + # project file called "coverage". + # Currently ignored on Windows. + 'coverage%': 0, + + # Set to 1 to force Visual C++ to use legacy debug information format /Z7. + # This is useful for parallel compilation tools which can't support /Zi. + # Only used on Windows. + 'win_z7%' : 0, + + # Although base/allocator lets you select a heap library via an + # environment variable, the libcmt shim it uses sometimes gets in + # the way. To disable it entirely, and switch to normal msvcrt, do e.g. + # 'win_use_allocator_shim': 0, + # 'win_release_RuntimeLibrary': 2 + # to ~/.gyp/include.gypi, gclient runhooks --force, and do a release build. + 'win_use_allocator_shim%': 1, # 1 = shim allocator via libcmt; 0 = msvcrt + + # Whether usage of OpenMAX is enabled. + 'enable_openmax%': 0, + + # Whether proprietary audio/video codecs are assumed to be included with + # this build (only meaningful if branding!=Chrome). + 'proprietary_codecs%': 0, + + # TODO(bradnelson): eliminate this when possible. + # To allow local gyp files to prevent release.vsprops from being included. + # Yes(1) means include release.vsprops. + # Once all vsprops settings are migrated into gyp, this can go away. + 'msvs_use_common_release%': 1, + + # TODO(bradnelson): eliminate this when possible. + # To allow local gyp files to override additional linker options for msvs. + # Yes(1) means set use the common linker options. + 'msvs_use_common_linker_extras%': 1, + + # TODO(sgk): eliminate this if possible. + # It would be nicer to support this via a setting in 'target_defaults' + # in chrome/app/locales/locales.gypi overriding the setting in the + # 'Debug' configuration in the 'target_defaults' dict below, + # but that doesn't work as we'd like. + 'msvs_debug_link_incremental%': '2', + + # Needed for some of the largest modules. + 'msvs_debug_link_nonincremental%': '1', + + # Turns on Use Library Dependency Inputs for linking chrome.dll on Windows + # to get incremental linking to be faster in debug builds. + 'incremental_chrome_dll%': '0', + + # The default settings for third party code for treating + # warnings-as-errors. Ideally, this would not be required, however there + # is some third party code that takes a long time to fix/roll. So, this + # flag allows us to have warnings as errors in general to prevent + # regressions in most modules, while working on the bits that are + # remaining. + 'win_third_party_warn_as_error%': 'true', + + # This is the location of the sandbox binary. Chrome looks for this before + # running the zygote process. If found, and SUID, it will be used to + # sandbox the zygote process and, thus, all renderer processes. + 'linux_sandbox_path%': '', + + # Set this to true to enable SELinux support. + 'selinux%': 0, + + # Clang stuff. + 'clang%': '<(clang)', + 'make_clang_dir%': 'third_party/llvm-build/Release+Asserts', + + # These two variables can be set in GYP_DEFINES while running + # |gclient runhooks| to let clang run a plugin in every compilation. + # Only has an effect if 'clang=1' is in GYP_DEFINES as well. + # Example: + # GYP_DEFINES='clang=1 clang_load=/abs/path/to/libPrintFunctionNames.dylib clang_add_plugin=print-fns' gclient runhooks + + 'clang_load%': '', + 'clang_add_plugin%': '', + + # The default type of gtest. + 'gtest_target_type%': 'executable', + + # Enable sampling based profiler. + # See http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html + 'profiling%': '0', + + # Enable strict glibc debug mode. + 'glibcxx_debug%': 0, + + # Override whether we should use Breakpad on Linux. I.e. for Chrome bot. + 'linux_breakpad%': 0, + # And if we want to dump symbols for Breakpad-enabled builds. + 'linux_dump_symbols%': 0, + # And if we want to strip the binary after dumping symbols. + 'linux_strip_binary%': 0, + # Strip the test binaries needed for Linux reliability tests. + 'linux_strip_reliability_tests%': 0, + + # Enable TCMalloc. + 'linux_use_tcmalloc%': 1, + + # Disable TCMalloc's debugallocation. + 'linux_use_debugallocation%': 0, + + # Disable TCMalloc's heapchecker. + 'linux_use_heapchecker%': 0, + + # Disable shadow stack keeping used by heapcheck to unwind the stacks + # better. + 'linux_keep_shadow_stacks%': 0, + + # Set to 1 to link against libgnome-keyring instead of using dlopen(). + 'linux_link_gnome_keyring%': 0, + # Set to 1 to link against gsettings APIs instead of using dlopen(). + 'linux_link_gsettings%': 0, + + # Set Thumb compilation flags. + 'arm_thumb%': 0, + + # Set ARM fpu compilation flags (only meaningful if armv7==1 and + # arm_neon==0). + 'arm_fpu%': 'vfpv3', + + # Set ARM float abi compilation flag. + 'arm_float_abi%': 'softfp', + + # Enable new NPDevice API. + 'enable_new_npdevice_api%': 0, + + # Enable EGLImage support in OpenMAX + 'enable_eglimage%': 1, + + # Enable a variable used elsewhere throughout the GYP files to determine + # whether to compile in the sources for the GPU plugin / process. + 'enable_gpu%': 1, + + # .gyp files or targets should set chromium_code to 1 if they build + # Chromium-specific code, as opposed to external code. This variable is + # used to control such things as the set of warnings to enable, and + # whether warnings are treated as errors. + 'chromium_code%': 0, + + 'release_valgrind_build%': 0, + + # TODO(thakis): Make this a blacklist instead, http://crbug.com/101600 + 'enable_wexit_time_destructors%': 0, + + # Set to 1 to compile with the built in pdf viewer. + 'internal_pdf%': 0, + + # Set to 1 to compile with the OpenGL ES 2.0 conformance tests. + 'internal_gles2_conform_tests%': 0, + + # NOTE: When these end up in the Mac bundle, we need to replace '-' for '_' + # so Cocoa is happy (http://crbug.com/20441). + 'locales': [ + 'am', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', + 'en-US', 'es-419', 'es', 'et', 'fa', 'fi', 'fil', 'fr', 'gu', 'he', + 'hi', 'hr', 'hu', 'id', 'it', 'ja', 'kn', 'ko', 'lt', 'lv', + 'ml', 'mr', 'ms', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', + 'sk', 'sl', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tr', 'uk', + 'vi', 'zh-CN', 'zh-TW', + ], + + # Pseudo locales are special locales which are used for testing and + # debugging. They don't get copied to the final app. For more info, + # check out https://sites.google.com/a/chromium.org/dev/Home/fake-bidi + 'pseudo_locales': [ + 'fake-bidi', + ], + + 'grit_defines': [], + + # If debug_devtools is set to 1, JavaScript files for DevTools are + # stored as is and loaded from disk. Otherwise, a concatenated file + # is stored in resources.pak. It is still possible to load JS files + # from disk by passing --debug-devtools cmdline switch. + 'debug_devtools%': 0, + + # The Java Bridge is not compiled in by default. + 'java_bridge%': 0, + + # Code signing for iOS binaries. The bots need to be able to disable this. + 'chromium_ios_signing%': 1, + + # This flag is only used when disable_nacl==0 and disables all those + # subcomponents which would require the installation of a native_client + # untrusted toolchain. + 'disable_nacl_untrusted%': 0, + + # Disable Dart by default. + 'enable_dart%': 0, + + # The desired version of Windows SDK can be set in ~/.gyp/include.gypi. + 'msbuild_toolset%': '', + + # Native Client is enabled by default. + 'disable_nacl%': 0, + + # Whether to build full debug version for Debug configuration on Android. + # Compared to full debug version, the default Debug configuration on Android + # has no full v8 debug, has size optimization and linker gc section, so that + # we can build a debug version with acceptable size and performance. + 'android_full_debug%': 0, + + # Sets the default version name and code for Android app, by default we + # do a developer build. + 'android_app_version_name%': 'Developer Build', + 'android_app_version_code%': 0, + + 'sas_dll_exists': 0, # '<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(sas_dll_path))', + 'wix_exists': 0, # '<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(wix_path))', + + 'windows_sdk_default_path': '<(DEPTH)/third_party/platformsdk_win8/files', +# 'directx_sdk_default_path': '<(DEPTH)/third_party/directxsdk/files', + 'windows_sdk_path%': '<(windows_sdk_default_path)', + + 'conditions': [ + #['"<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(windows_sdk_default_path))"=="True"', { + # 'windows_sdk_path%': '<(windows_sdk_default_path)', + #}, { + # 'windows_sdk_path%': 'C:/Program Files (x86)/Windows Kits/8.0', + #}], + #['OS=="win" and "<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(directx_sdk_default_path))"=="True"', { + # 'directx_sdk_path%': '<(directx_sdk_default_path)', + #}, { + # 'directx_sdk_path%': '$(DXSDK_DIR)', + #}], + # If use_official_google_api_keys is already set (to 0 or 1), we + # do none of the implicit checking. If it is set to 1 and the + # internal keys file is missing, the build will fail at compile + # time. If it is set to 0 and keys are not provided by other + # means, a warning will be printed at compile time. + ['use_official_google_api_keys==2', { + 'use_official_google_api_keys%': + '<!(<(PYTHON) <(DEPTH)/google_apis/build/check_internal.py <(DEPTH)/google_apis/internal/google_chrome_api_keys.h)', + }], + ['os_posix==1 and OS!="mac" and OS!="ios"', { + # Figure out the python architecture to decide if we build pyauto. + # disabled for mozilla because windows != mac and this runs a shell script + # 'python_arch%': '<!(<(DEPTH)/build/linux/python_arch.sh <(sysroot)/usr/<(system_libdir)/libpython<(python_ver).so.1.0)', + 'conditions': [ + # TODO(glider): set clang to 1 earlier for ASan and TSan builds so + # that it takes effect here. + # disabled for Mozilla since it doesn't use this, and 'msys' messes $(CXX) up + ['build_with_mozilla==0 and clang==0 and asan==0 and tsan==0', { + # This will set gcc_version to XY if you are running gcc X.Y.*. + 'gcc_version%': '<!(<(PYTHON) <(DEPTH)/build/compiler_version.py)', + }, { + 'gcc_version%': 0, + }], + ['branding=="Chrome"', { + 'linux_breakpad%': 1, + }], + # All Chrome builds have breakpad symbols, but only process the + # symbols from official builds. + ['(branding=="Chrome" and buildtype=="Official")', { + 'linux_dump_symbols%': 1, + }], + ], + }], # os_posix==1 and OS!="mac" and OS!="ios" + ['OS=="ios"', { + 'disable_nacl%': 1, + 'enable_gpu%': 0, + 'icu_use_data_file_flag%': 1, + 'use_system_bzip2%': 1, + 'use_system_libxml%': 1, + 'use_system_sqlite%': 1, + + # The Mac SDK is set for iOS builds and passed through to Mac + # sub-builds. This allows the Mac sub-build SDK in an iOS build to be + # overridden from the command line the same way it is for a Mac build. + 'mac_sdk%': '<!(<(PYTHON) <(DEPTH)/build/mac/find_sdk.py 10.6)', + + # iOS SDK and deployment target support. The iOS 5.0 SDK is actually + # what is required, but the value is left blank so when it is set in + # the project files it will be the "current" iOS SDK. Forcing 5.0 + # even though it is "current" causes Xcode to spit out a warning for + # every single project file for not using the "current" SDK. + 'ios_sdk%': '', + 'ios_sdk_path%': '', + 'ios_deployment_target%': '4.3', + + 'conditions': [ + # ios_product_name is set to the name of the .app bundle as it should + # appear on disk. + ['branding=="Chrome"', { + 'ios_product_name%': 'Chrome', + }, { # else: branding!="Chrome" + 'ios_product_name%': 'Chromium', + }], + ['branding=="Chrome" and buildtype=="Official"', { + 'ios_breakpad%': 1, + }, { # else: branding!="Chrome" or buildtype!="Official" + 'ios_breakpad%': 0, + }], + ], + }], # OS=="ios" + ['OS=="android"', { + # Provides an absolute path to PRODUCT_DIR (e.g. out/Release). Used + # to specify the output directory for Ant in the Android build. + 'ant_build_out': '`cd <(PRODUCT_DIR) && pwd -P`', + + # Uses Android's crash report system + 'linux_breakpad%': 0, + + # Always uses openssl. + 'use_openssl%': 1, + + 'proprietary_codecs%': '<(proprietary_codecs)', + 'enable_task_manager%': 0, + 'safe_browsing%': 0, + 'configuration_policy%': 0, + 'input_speech%': 0, + 'enable_web_intents%': 0, + 'enable_automation%': 0, + 'java_bridge%': 1, + 'build_ffmpegsumo%': 0, + 'linux_use_tcmalloc%': 0, + + # Disable Native Client. + 'disable_nacl%': 1, + + # Android does not support background apps. + 'enable_background%': 0, + + # Sessions are store separately in the Java side. + 'enable_session_service%': 0, + + # Set to 1 once we have a notification system for Android. + # http://crbug.com/115320 + 'notifications%': 0, + + 'p2p_apis%' : 0, + + # TODO(jrg): when 'gtest_target_type'=='shared_library' and + # OS==android, make all gtest_targets depend on + # testing/android/native_test.gyp:native_test_apk. + 'gtest_target_type%': 'shared_library', + + # Uses system APIs for decoding audio and video. + 'use_libffmpeg%': '0', + + # Always use the chromium skia. The use_system_harfbuzz needs to + # match use_system_skia. + 'use_system_skia%': '0', + 'use_system_harfbuzz%': '0', + + # Configure crash reporting and build options based on release type. + 'conditions': [ + ['buildtype=="Official"', { + # Only report crash dumps for Official builds. + 'linux_breakpad%': 1, + }, { + 'linux_breakpad%': 0, + }], + ], + + # When building as part of the Android system, use system libraries + # where possible to reduce ROM size. + # TODO(steveblock): Investigate using the system version of sqlite. + 'use_system_sqlite%': 0, # '<(android_build_type)', + 'use_system_expat%': '<(android_build_type)', + 'use_system_icu%': '<(android_build_type)', + 'use_system_stlport%': '<(android_build_type)', + + # Copy it out one scope. + 'android_build_type%': '<(android_build_type)', + }], # OS=="android" + ['OS=="mac"', { + 'variables': { + # Mac OS X SDK and deployment target support. The SDK identifies + # the version of the system headers that will be used, and + # corresponds to the MAC_OS_X_VERSION_MAX_ALLOWED compile-time + # macro. "Maximum allowed" refers to the operating system version + # whose APIs are available in the headers. The deployment target + # identifies the minimum system version that the built products are + # expected to function on. It corresponds to the + # MAC_OS_X_VERSION_MIN_REQUIRED compile-time macro. To ensure these + # macros are available, #include <AvailabilityMacros.h>. Additional + # documentation on these macros is available at + # http://developer.apple.com/mac/library/technotes/tn2002/tn2064.html#SECTION3 + # Chrome normally builds with the Mac OS X 10.6 SDK and sets the + # deployment target to 10.6. Other projects, such as O3D, may + # override these defaults. + + # Normally, mac_sdk_min is used to find an SDK that Xcode knows + # about that is at least the specified version. In official builds, + # the SDK must match mac_sdk_min exactly. If the SDK is installed + # someplace that Xcode doesn't know about, set mac_sdk_path to the + # path to the SDK; when set to a non-empty string, SDK detection + # based on mac_sdk_min will be bypassed entirely. + 'mac_sdk_min%': '10.6', + 'mac_sdk_path%': '', + + 'mac_deployment_target%': '10.6', + }, + + 'mac_sdk_min': '<(mac_sdk_min)', + 'mac_sdk_path': '<(mac_sdk_path)', + 'mac_deployment_target': '<(mac_deployment_target)', + + # Enable clang on mac by default! + 'clang%': 1, + + # Compile in Breakpad support by default so that it can be + # tested, even if it is not enabled by default at runtime. + 'mac_breakpad_compiled_in%': 1, + 'conditions': [ + # mac_product_name is set to the name of the .app bundle as it should + # appear on disk. This duplicates data from + # chrome/app/theme/chromium/BRANDING and + # chrome/app/theme/google_chrome/BRANDING, but is necessary to get + # these names into the build system. + ['branding=="Chrome"', { + 'mac_product_name%': 'Google Chrome', + }, { # else: branding!="Chrome" + 'mac_product_name%': 'Chromium', + }], + + ['branding=="Chrome" and buildtype=="Official"', { + 'mac_sdk%': '<!(<(PYTHON) <(DEPTH)/build/mac/find_sdk.py --verify <(mac_sdk_min) --sdk_path=<(mac_sdk_path))', + # Enable uploading crash dumps. + 'mac_breakpad_uploads%': 1, + # Enable dumping symbols at build time for use by Mac Breakpad. + 'mac_breakpad%': 1, + # Enable Keystone auto-update support. + 'mac_keystone%': 1, + }, { # else: branding!="Chrome" or buildtype!="Official" + 'mac_sdk%': '', #'<!(<(PYTHON) <(DEPTH)/build/mac/find_sdk.py <(mac_sdk_min))', + 'mac_breakpad_uploads%': 0, + 'mac_breakpad%': 0, + 'mac_keystone%': 0, + }], + ], + }], # OS=="mac" + + ['OS=="win"', { + 'conditions': [ + ['component=="shared_library"', { + 'win_use_allocator_shim%': 0, + }], + ['component=="shared_library" and "<(GENERATOR)"=="ninja"', { + # Only enabled by default for ninja because it's buggy in VS. + # Not enabled for component=static_library because some targets + # are too large and the toolchain fails due to the size of the + # .obj files. + 'incremental_chrome_dll%': 1, + }], + # Don't do incremental linking for large modules on 32-bit. + ['MSVS_OS_BITS==32', { + 'msvs_large_module_debug_link_mode%': '1', # No + },{ + 'msvs_large_module_debug_link_mode%': '2', # Yes + }], + ['MSVS_VERSION=="2010e" or MSVS_VERSION=="2008e" or MSVS_VERSION=="2005e"', { + 'msvs_express%': 1, + 'secure_atl%': 0, + },{ + 'msvs_express%': 0, + 'secure_atl%': 1, + }], + ], + 'nacl_win64_defines': [ + # This flag is used to minimize dependencies when building + # Native Client loader for 64-bit Windows. + 'NACL_WIN64', + ], + }], + + ['os_posix==1 and chromeos==0 and OS!="android"', { + 'use_cups%': 1, + }, { + 'use_cups%': 0, + }], + + # Native Client glibc toolchain is enabled by default except on arm. + ['target_arch=="arm"', { + 'disable_glibc%': 1, + }, { + 'disable_glibc%': 0, + }], + + # Disable SSE2 when building for ARM or MIPS. + ['target_arch=="arm" or target_arch=="mipsel"', { + 'disable_sse2%': 1, + }, { + 'disable_sse2%': '<(disable_sse2)', + }], + + # Set the relative path from this file to the GYP file of the JPEG + # library used by Chromium. + ['use_system_libjpeg==1 or use_libjpeg_turbo==0', { + # Configuration for using the system libjeg is here. + 'libjpeg_gyp_path': '../third_party/libjpeg/libjpeg.gyp', + }, { + 'libjpeg_gyp_path': '../third_party/libjpeg_turbo/libjpeg.gyp', + }], + + # Options controlling the use of GConf (the classic GNOME configuration + # system) and GIO, which contains GSettings (the new GNOME config system). + ['chromeos==1', { + 'use_gconf%': 0, + 'use_gio%': 0, + }, { + 'use_gconf%': 1, + 'use_gio%': 1, + }], + + # Set up -D and -E flags passed into grit. + ['branding=="Chrome"', { + # TODO(mmoss) The .grd files look for _google_chrome, but for + # consistency they should look for google_chrome_build like C++. + 'grit_defines': ['-D', '_google_chrome', + '-E', 'CHROMIUM_BUILD=google_chrome'], + }, { + 'grit_defines': ['-D', '_chromium', + '-E', 'CHROMIUM_BUILD=chromium'], + }], + ['chromeos==1', { + 'grit_defines': ['-D', 'chromeos', '-D', 'scale_factors=2x'], + }], + ['toolkit_views==1', { + 'grit_defines': ['-D', 'toolkit_views'], + }], + ['use_aura==1', { + 'grit_defines': ['-D', 'use_aura'], + }], + ['use_ash==1', { + 'grit_defines': ['-D', 'use_ash'], + }], + ['use_nss==1', { + 'grit_defines': ['-D', 'use_nss'], + }], + ['file_manager_extension==1', { + 'grit_defines': ['-D', 'file_manager_extension'], + }], + ['remoting==1', { + 'grit_defines': ['-D', 'remoting'], + }], + ['use_titlecase_in_grd_files==1', { + 'grit_defines': ['-D', 'use_titlecase'], + }], + ['use_third_party_translations==1', { + 'grit_defines': ['-D', 'use_third_party_translations'], + 'locales': [ + 'ast', 'bs', 'ca@valencia', 'en-AU', 'eo', 'eu', 'gl', 'hy', 'ia', + 'ka', 'ku', 'kw', 'ms', 'ug' + ], + }], + ['OS=="android"', { + 'grit_defines': ['-D', 'android'], + }], + ['OS=="mac"', { + 'grit_defines': ['-D', 'scale_factors=2x'], + }], + ['OS == "ios"', { + 'grit_defines': [ + # define for iOS specific resources. + '-D', 'ios', + # iOS uses a whitelist to filter resources. + '-w', '<(DEPTH)/build/ios/grit_whitelist.txt' + ], + }], + ['enable_extensions==1', { + 'grit_defines': ['-D', 'enable_extensions'], + }], + ['enable_printing==1', { + 'grit_defines': ['-D', 'enable_printing'], + }], + ['enable_themes==1', { + 'grit_defines': ['-D', 'enable_themes'], + }], + ['use_oem_wallpaper==1', { + 'grit_defines': ['-D', 'use_oem_wallpaper'], + }], + ['clang_use_chrome_plugins==1 and OS!="win"', { + 'clang_chrome_plugins_flags': [ + '<!@(<(DEPTH)/tools/clang/scripts/plugin_flags.sh)' + ], + }], + + ['enable_web_intents_tag==1', { + 'grit_defines': ['-D', 'enable_web_intents_tag'], + }], + + ['asan==1', { + 'clang%': 1, + }], + ['asan==1 and OS=="mac"', { + # See http://crbug.com/145503. + 'component': "static_library", + }], + ['tsan==1', { + 'clang%': 1, + }], + + ['OS=="linux" and clang_type_profiler==1', { + 'clang%': 1, + 'clang_use_chrome_plugins%': 0, + 'make_clang_dir%': 'third_party/llvm-allocated-type/Linux_x64', + }], + + # On valgrind bots, override the optimizer settings so we don't inline too + # much and make the stacks harder to figure out. + # + # TODO(rnk): Kill off variables that no one else uses and just implement + # them under a build_for_tool== condition. + ['build_for_tool=="memcheck" or build_for_tool=="tsan"', { + # gcc flags + 'mac_debug_optimization': '1', + 'mac_release_optimization': '1', + 'release_optimize': '1', + 'no_gc_sections': 1, + 'debug_extra_cflags': '-g -fno-inline -fno-omit-frame-pointer ' + '-fno-builtin -fno-optimize-sibling-calls', + 'release_extra_cflags': '-g -fno-inline -fno-omit-frame-pointer ' + '-fno-builtin -fno-optimize-sibling-calls', + + # MSVS flags for TSan on Pin and Windows. + 'win_debug_RuntimeChecks': '0', + 'win_debug_disable_iterator_debugging': '1', + 'win_debug_Optimization': '1', + 'win_debug_InlineFunctionExpansion': '0', + 'win_release_InlineFunctionExpansion': '0', + 'win_release_OmitFramePointers': '0', + + 'linux_use_tcmalloc': 1, + 'release_valgrind_build': 1, + 'werror': '', + 'component': 'static_library', + 'use_system_zlib': 0, + }], + + # Build tweaks for DrMemory. + # TODO(rnk): Combine with tsan config to share the builder. + # http://crbug.com/108155 + ['build_for_tool=="drmemory"', { + # These runtime checks force initialization of stack vars which blocks + # DrMemory's uninit detection. + 'win_debug_RuntimeChecks': '0', + # Iterator debugging is slow. + 'win_debug_disable_iterator_debugging': '1', + # Try to disable optimizations that mess up stacks in a release build. + 'win_release_InlineFunctionExpansion': '0', + 'win_release_OmitFramePointers': '0', + # Ditto for debug, to support bumping win_debug_Optimization. + 'win_debug_InlineFunctionExpansion': 0, + 'win_debug_OmitFramePointers': 0, + # Keep the code under #ifndef NVALGRIND. + 'release_valgrind_build': 1, + }], + ], + + # List of default apps to install in new profiles. The first list contains + # the source files as found in svn. The second list, used only for linux, + # contains the destination location for each of the files. When a crx + # is added or removed from the list, the chrome/browser/resources/ + # default_apps/external_extensions.json file must also be updated. + 'default_apps_list': [ + 'browser/resources/default_apps/external_extensions.json', + 'browser/resources/default_apps/gmail.crx', + 'browser/resources/default_apps/search.crx', + 'browser/resources/default_apps/youtube.crx', + 'browser/resources/default_apps/drive.crx', + 'browser/resources/default_apps/docs.crx', + ], + 'default_apps_list_linux_dest': [ + '<(PRODUCT_DIR)/default_apps/external_extensions.json', + '<(PRODUCT_DIR)/default_apps/gmail.crx', + '<(PRODUCT_DIR)/default_apps/search.crx', + '<(PRODUCT_DIR)/default_apps/youtube.crx', + '<(PRODUCT_DIR)/default_apps/drive.crx', + '<(PRODUCT_DIR)/default_apps/docs.crx', + ], + }, + 'target_defaults': { + 'variables': { + # The condition that operates on chromium_code is in a target_conditions + # section, and will not have access to the default fallback value of + # chromium_code at the top of this file, or to the chromium_code + # variable placed at the root variables scope of .gyp files, because + # those variables are not set at target scope. As a workaround, + # if chromium_code is not set at target scope, define it in target scope + # to contain whatever value it has during early variable expansion. + # That's enough to make it available during target conditional + # processing. + 'chromium_code%': '<(chromium_code)', + + # See http://msdn.microsoft.com/en-us/library/aa652360(VS.71).aspx + 'win_release_Optimization%': '2', # 2 = /Os + 'win_debug_Optimization%': '0', # 0 = /Od + + # See http://msdn.microsoft.com/en-us/library/2kxx5t2c(v=vs.80).aspx + # Tri-state: blank is default, 1 on, 0 off + 'win_release_OmitFramePointers%': '0', + # Tri-state: blank is default, 1 on, 0 off + 'win_debug_OmitFramePointers%': '', + + # See http://msdn.microsoft.com/en-us/library/8wtf2dfz(VS.71).aspx + 'win_debug_RuntimeChecks%': '3', # 3 = all checks enabled, 0 = off + + # See http://msdn.microsoft.com/en-us/library/47238hez(VS.71).aspx + 'win_debug_InlineFunctionExpansion%': '', # empty = default, 0 = off, + 'win_release_InlineFunctionExpansion%': '2', # 1 = only __inline, 2 = max + + # VS inserts quite a lot of extra checks to algorithms like + # std::partial_sort in Debug build which make them O(N^2) + # instead of O(N*logN). This is particularly slow under memory + # tools like ThreadSanitizer so we want it to be disablable. + # See http://msdn.microsoft.com/en-us/library/aa985982(v=VS.80).aspx + 'win_debug_disable_iterator_debugging%': '0', + + 'release_extra_cflags%': '', + 'debug_extra_cflags%': '', + + 'release_valgrind_build%': '<(release_valgrind_build)', + + # the non-qualified versions are widely assumed to be *nix-only + 'win_release_extra_cflags%': '', + 'win_debug_extra_cflags%': '', + + # TODO(thakis): Make this a blacklist instead, http://crbug.com/101600 + 'enable_wexit_time_destructors%': '<(enable_wexit_time_destructors)', + + # Only used by Windows build for now. Can be used to build into a + # differet output directory, e.g., a build_dir_prefix of VS2010_ would + # output files in src/build/VS2010_{Debug,Release}. + 'build_dir_prefix%': '', + + # Targets are by default not nacl untrusted code. + 'nacl_untrusted_build%': 0, + + 'conditions': [ + ['OS=="win" and component=="shared_library"', { + # See http://msdn.microsoft.com/en-us/library/aa652367.aspx + 'win_release_RuntimeLibrary%': '2', # 2 = /MD (nondebug DLL) + 'win_debug_RuntimeLibrary%': '3', # 3 = /MDd (debug DLL) + }, { + # See http://msdn.microsoft.com/en-us/library/aa652367.aspx + 'win_release_RuntimeLibrary%': '0', # 0 = /MT (nondebug static) + 'win_debug_RuntimeLibrary%': '1', # 1 = /MTd (debug static) + }], + ['OS=="ios"', { + # See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Optimize-Options.html + 'mac_release_optimization%': 's', # Use -Os unless overridden + 'mac_debug_optimization%': '0', # Use -O0 unless overridden + }, { + # See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Optimize-Options.html + 'mac_release_optimization%': '3', # Use -O3 unless overridden + 'mac_debug_optimization%': '0', # Use -O0 unless overridden + }], + ], + }, + 'conditions': [ + ['OS=="linux" and linux_use_tcmalloc==1 and clang_type_profiler==1', { + 'cflags_cc!': ['-fno-rtti'], + 'cflags_cc+': [ + '-frtti', + '-gline-tables-only', + '-fintercept-allocation-functions', + ], + 'defines': ['TYPE_PROFILING'], + 'dependencies': [ + '<(DEPTH)/base/allocator/allocator.gyp:type_profiler', + ], + }], + ['OS=="win" and "<(msbuild_toolset)"!=""', { + 'msbuild_toolset': '<(msbuild_toolset)', + }], + ['branding=="Chrome"', { + 'defines': ['GOOGLE_CHROME_BUILD'], + }, { # else: branding!="Chrome" + 'defines': ['CHROMIUM_BUILD'], + }], + ['OS=="mac" and component=="shared_library"', { + 'xcode_settings': { + 'DYLIB_INSTALL_NAME_BASE': '@rpath', + 'LD_RUNPATH_SEARCH_PATHS': [ + # For unbundled binaries. + '@loader_path/.', + # For bundled binaries, to get back from Binary.app/Contents/MacOS. + '@loader_path/../../..', + ], + }, + }], + ['branding=="Chrome" and (OS=="win" or OS=="mac")', { + 'defines': ['ENABLE_RLZ'], + }], + ['component=="shared_library"', { + 'defines': ['COMPONENT_BUILD'], + }], + ['toolkit_views==1', { + 'defines': ['TOOLKIT_VIEWS=1'], + }], + ['ui_compositor_image_transport==1', { + 'defines': ['UI_COMPOSITOR_IMAGE_TRANSPORT'], + }], + ['use_aura==1', { + 'defines': ['USE_AURA=1'], + }], + ['use_ash==1', { + 'defines': ['USE_ASH=1'], + }], + ['use_libjpeg_turbo==1', { + 'defines': ['USE_LIBJPEG_TURBO=1'], + }], + ['use_nss==1', { + 'defines': ['USE_NSS=1'], + }], + ['enable_one_click_signin==1', { + 'defines': ['ENABLE_ONE_CLICK_SIGNIN'], + }], + ['toolkit_uses_gtk==1 and toolkit_views==0', { + # TODO(erg): We are progressively sealing up use of deprecated features + # in gtk in preparation for an eventual porting to gtk3. + 'defines': ['GTK_DISABLE_SINGLE_INCLUDES=1'], + }], + ['chromeos==1', { + 'defines': ['OS_CHROMEOS=1'], + }], + ['use_xi2_mt!=0', { + 'defines': ['USE_XI2_MT=<(use_xi2_mt)'], + }], + ['file_manager_extension==1', { + 'defines': ['FILE_MANAGER_EXTENSION=1'], + }], + ['profiling==1', { + 'defines': ['ENABLE_PROFILING=1'], + }], + ['OS=="linux" and glibcxx_debug==1', { + 'defines': ['_GLIBCXX_DEBUG=1',], + 'cflags_cc!': ['-fno-rtti'], + 'cflags_cc+': ['-frtti', '-g'], + }], + ['OS=="linux"', { + # we need lrint(), which is ISOC99, and Xcode + # already forces -std=c99 for mac below + 'defines': ['_ISOC99_SOURCE=1'], + }], + ['remoting==1', { + 'defines': ['ENABLE_REMOTING=1'], + }], + ['enable_webrtc==1', { + 'defines': ['ENABLE_WEBRTC=1'], + }], + ['proprietary_codecs==1', { + 'defines': ['USE_PROPRIETARY_CODECS'], + }], + ['enable_pepper_threading==1', { + 'defines': ['ENABLE_PEPPER_THREADING'], + }], + ['enable_viewport==1', { + 'defines': ['ENABLE_VIEWPORT'], + }], + ['configuration_policy==1', { + 'defines': ['ENABLE_CONFIGURATION_POLICY'], + }], + ['input_speech==1', { + 'defines': ['ENABLE_INPUT_SPEECH'], + }], + ['notifications==1', { + 'defines': ['ENABLE_NOTIFICATIONS'], + }], + ['enable_hidpi==1', { + 'defines': ['ENABLE_HIDPI=1'], + }], + ['fastbuild!=0', { + + 'conditions': [ + # For Windows and Mac, we don't genererate debug information. + ['OS=="win" or OS=="mac"', { + 'msvs_settings': { + 'VCLinkerTool': { + 'GenerateDebugInformation': 'false', + }, + 'VCCLCompilerTool': { + 'DebugInformationFormat': '0', + } + }, + 'xcode_settings': { + 'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO', + }, + }, { # else: OS != "win", generate less debug information. + 'variables': { + 'debug_extra_cflags': '-g1', + }, + }], + # Clang creates chubby debug information, which makes linking very + # slow. For now, don't create debug information with clang. See + # http://crbug.com/70000 + ['(OS=="linux" or OS=="android") and clang==1', { + 'variables': { + 'debug_extra_cflags': '-g0', + }, + }], + ], # conditions for fastbuild. + }], # fastbuild!=0 + ['dcheck_always_on!=0', { + 'defines': ['DCHECK_ALWAYS_ON=1'], + }], # dcheck_always_on!=0 + ['selinux==1', { + 'defines': ['CHROMIUM_SELINUX=1'], + }], + ['win_use_allocator_shim==0', { + 'conditions': [ + ['OS=="win"', { + 'defines': ['NO_TCMALLOC'], + }], + ], + }], + ['enable_gpu==1', { + 'defines': [ + 'ENABLE_GPU=1', + ], + }], + ['use_openssl==1', { + 'defines': [ + 'USE_OPENSSL=1', + ], + }], + ['enable_eglimage==1', { + 'defines': [ + 'ENABLE_EGLIMAGE=1', + ], + }], + ['use_skia==1', { + 'defines': [ + 'USE_SKIA=1', + ], + }], + ['coverage!=0', { + 'conditions': [ + ['OS=="mac" or OS=="ios"', { + 'xcode_settings': { + 'GCC_INSTRUMENT_PROGRAM_FLOW_ARCS': 'YES', # -fprofile-arcs + 'GCC_GENERATE_TEST_COVERAGE_FILES': 'YES', # -ftest-coverage + }, + }], + ['OS=="mac"', { + # Add -lgcov for types executable, shared_library, and + # loadable_module; not for static_library. + # This is a delayed conditional. + 'target_conditions': [ + ['_type!="static_library"', { + 'xcode_settings': { 'OTHER_LDFLAGS': [ '-lgcov' ] }, + }], + ], + }], + ['OS=="linux" or OS=="android"', { + 'cflags': [ '-ftest-coverage', + '-fprofile-arcs' ], + 'link_settings': { 'libraries': [ '-lgcov' ] }, + }], + # Finally, for Windows, we simply turn on profiling. + ['OS=="win"', { + 'msvs_settings': { + 'VCLinkerTool': { + 'Profile': 'true', + }, + 'VCCLCompilerTool': { + # /Z7, not /Zi, so coverage is happyb + 'DebugInformationFormat': '1', + 'AdditionalOptions': ['/Yd'], + } + } + }], # OS==win + ], # conditions for coverage + }], # coverage!=0 + ['OS=="win"', { + 'defines': [ + '__STD_C', + '_CRT_SECURE_NO_DEPRECATE', + '_SCL_SECURE_NO_DEPRECATE', + ], + 'include_dirs': [ + '<(DEPTH)/third_party/wtl/include', + ], + 'conditions': [ + ['win_z7!=0', { + 'msvs_settings': { + # Generates debug info when win_z7=1 + # even if fastbuild=1 (that makes GenerateDebugInformation false). + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + 'VCCLCompilerTool': { + 'DebugInformationFormat': '1', + } + } + }], + ], # win_z7!=0 + }], # OS==win + ['enable_task_manager==1', { + 'defines': [ + 'ENABLE_TASK_MANAGER=1', + ], + }], + ['enable_web_intents==1', { + 'defines': [ + 'ENABLE_WEB_INTENTS=1', + ], + }], + ['enable_extensions==1', { + 'defines': [ + 'ENABLE_EXTENSIONS=1', + ], + }], + ['OS=="win" and branding=="Chrome"', { + 'defines': ['ENABLE_SWIFTSHADER'], + }], + ['enable_dart==1', { + 'defines': ['WEBKIT_USING_DART=1'], + }], + ['enable_plugin_installation==1', { + 'defines': ['ENABLE_PLUGIN_INSTALLATION=1'], + }], + ['enable_protector_service==1', { + 'defines': ['ENABLE_PROTECTOR_SERVICE=1'], + }], + ['enable_session_service==1', { + 'defines': ['ENABLE_SESSION_SERVICE=1'], + }], + ['enable_themes==1', { + 'defines': ['ENABLE_THEMES=1'], + }], + ['enable_background==1', { + 'defines': ['ENABLE_BACKGROUND=1'], + }], + ['enable_automation==1', { + 'defines': ['ENABLE_AUTOMATION=1'], + }], + ['enable_printing==1', { + 'defines': ['ENABLE_PRINTING=1'], + }], + ['enable_captive_portal_detection==1', { + 'defines': ['ENABLE_CAPTIVE_PORTAL_DETECTION=1'], + }], + ['disable_ftp_support==1', { + 'defines': ['DISABLE_FTP_SUPPORT=1'], + }], + ], # conditions for 'target_defaults' + 'target_conditions': [ + ['enable_wexit_time_destructors==1', { + 'conditions': [ + [ 'clang==1', { + 'cflags': [ + '-Wexit-time-destructors', + ], + 'xcode_settings': { + 'WARNING_CFLAGS': [ + '-Wexit-time-destructors', + ], + }, + }], + ], + }], + ['chromium_code==0', { + 'conditions': [ + [ 'os_posix==1 and OS!="mac" and OS!="ios"', { + # We don't want to get warnings from third-party code, + # so remove any existing warning-enabling flags like -Wall. + 'cflags!': [ + '-Wall', + '-Wextra', + ], + 'cflags_cc': [ + # Don't warn about hash_map in third-party code. + '-Wno-deprecated', + ], + 'cflags': [ + # Don't warn about printf format problems. + # This is off by default in gcc but on in Ubuntu's gcc(!). + '-Wno-format', + ], + 'cflags_cc!': [ + # TODO(fischman): remove this. + # http://code.google.com/p/chromium/issues/detail?id=90453 + '-Wsign-compare', + ] + }], + # TODO: Fix all warnings on chromeos too. + [ 'os_posix==1 and OS!="mac" and OS!="ios" and (clang!=1 or chromeos==1)', { + 'cflags!': [ + '-Werror', + ], + }], + [ 'os_posix==1 and os_bsd!=1 and OS!="mac" and OS!="android"', { + 'cflags': [ + # Don't warn about ignoring the return value from e.g. close(). + # This is off by default in some gccs but on by default in others. + # BSD systems do not support this option, since they are usually + # using gcc 4.2.1, which does not have this flag yet. + '-Wno-unused-result', + ], + }], + [ 'OS=="win"', { + 'defines': [ + '_CRT_SECURE_NO_DEPRECATE', + '_CRT_NONSTDC_NO_WARNINGS', + '_CRT_NONSTDC_NO_DEPRECATE', + '_SCL_SECURE_NO_DEPRECATE', + ], + 'msvs_disabled_warnings': [4800], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '3', + 'WarnAsError': '<(win_third_party_warn_as_error)', + 'Detect64BitPortabilityProblems': 'false', + }, + }, + 'conditions': [ + ['buildtype=="Official"', { + 'msvs_settings': { + 'VCCLCompilerTool': { 'WarnAsError': 'false' }, + } + }], + ], + }], + # TODO(darin): Unfortunately, some third_party code depends on base/ + [ 'OS=="win" and component=="shared_library"', { + 'msvs_disabled_warnings': [ + 4251, # class 'std::xx' needs to have dll-interface. + ], + }], + [ 'OS=="mac" or OS=="ios"', { + 'xcode_settings': { + 'WARNING_CFLAGS!': ['-Wall', '-Wextra'], + }, + 'conditions': [ + ['buildtype=="Official"', { + 'xcode_settings': { + 'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO', # -Werror + }, + }], + ], + }], + [ 'OS=="ios"', { + 'xcode_settings': { + # TODO(ios): Fix remaining warnings in third-party code, then + # remove this; the Mac cleanup didn't get everything that's + # flagged in an iOS build. + 'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO', + 'RUN_CLANG_STATIC_ANALYZER': 'NO', + }, + }], + ], + }, { + 'includes': [ + # Rules for excluding e.g. foo_win.cc from the build on non-Windows. + 'filename_rules.gypi', + ], + # In Chromium code, we define __STDC_FORMAT_MACROS in order to get the + # C99 macros on Mac and Linux. + 'defines': [ + '__STDC_FORMAT_MACROS', + ], + 'conditions': [ + ['OS=="win"', { + # turn on warnings for signed/unsigned mismatch on chromium code. + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalOptions': ['/we4389'], + }, + }, + }], + ['OS=="win" and component=="shared_library"', { + 'msvs_disabled_warnings': [ + 4251, # class 'std::xx' needs to have dll-interface. + ], + }], + ], + }], + ], # target_conditions for 'target_defaults' + 'default_configuration': 'Debug', + 'configurations': { + # VCLinkerTool LinkIncremental values below: + # 0 == default + # 1 == /INCREMENTAL:NO + # 2 == /INCREMENTAL + # Debug links incremental, Release does not. + # + # Abstract base configurations to cover common attributes. + # + 'Common_Base': { + 'abstract': 1, + 'msvs_configuration_attributes': { + 'OutputDirectory': '<(DEPTH)\\build\\<(build_dir_prefix)$(ConfigurationName)', + 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)', + 'CharacterSet': '1', + }, + }, + 'x86_Base': { + 'abstract': 1, + 'msvs_settings': { + 'VCLinkerTool': { + 'TargetMachine': '1', + }, + }, + 'msvs_configuration_platform': 'Win32', + }, + 'x64_Base': { + 'abstract': 1, + 'msvs_configuration_platform': 'x64', + 'msvs_settings': { + 'VCLinkerTool': { + 'TargetMachine': '17', # x86 - 64 + 'AdditionalLibraryDirectories!': + ['<(windows_sdk_path)/Lib/win8/um/x86'], + 'AdditionalLibraryDirectories': + ['<(windows_sdk_path)/Lib/win8/um/x64'], + }, + 'VCLibrarianTool': { + 'AdditionalLibraryDirectories!': + ['<(windows_sdk_path)/Lib/win8/um/x86'], + 'AdditionalLibraryDirectories': + ['<(windows_sdk_path)/Lib/win8/um/x64'], + }, + }, + 'defines': [ + # Not sure if tcmalloc works on 64-bit Windows. + 'NO_TCMALLOC', + ], + }, + 'Debug_Base': { + 'abstract': 1, + 'defines': [ + 'DYNAMIC_ANNOTATIONS_ENABLED=1', + 'WTF_USE_DYNAMIC_ANNOTATIONS=1', + ], + 'xcode_settings': { + 'COPY_PHASE_STRIP': 'NO', + 'GCC_OPTIMIZATION_LEVEL': '<(mac_debug_optimization)', + 'OTHER_CFLAGS': [ + '<@(debug_extra_cflags)', + ], + }, + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '<(win_debug_Optimization)', + 'PreprocessorDefinitions': ['_DEBUG'], + 'BasicRuntimeChecks': '<(win_debug_RuntimeChecks)', + 'RuntimeLibrary': '<(win_debug_RuntimeLibrary)', + 'conditions': [ + # According to MSVS, InlineFunctionExpansion=0 means + # "default inlining", not "/Ob0". + # Thus, we have to handle InlineFunctionExpansion==0 separately. + ['win_debug_InlineFunctionExpansion==0', { + 'AdditionalOptions': ['/Ob0'], + }], + ['win_debug_InlineFunctionExpansion!=""', { + 'InlineFunctionExpansion': + '<(win_debug_InlineFunctionExpansion)', + }], + ['win_debug_disable_iterator_debugging==1', { + 'PreprocessorDefinitions': ['_HAS_ITERATOR_DEBUGGING=0'], + }], + + # if win_debug_OmitFramePointers is blank, leave as default + ['win_debug_OmitFramePointers==1', { + 'OmitFramePointers': 'true', + }], + ['win_debug_OmitFramePointers==0', { + 'OmitFramePointers': 'false', + # The above is not sufficient (http://crbug.com/106711): it + # simply eliminates an explicit "/Oy", but both /O2 and /Ox + # perform FPO regardless, so we must explicitly disable. + # We still want the false setting above to avoid having + # "/Oy /Oy-" and warnings about overriding. + 'AdditionalOptions': ['/Oy-'], + }], + ], + 'AdditionalOptions': [ '<@(win_debug_extra_cflags)', ], + }, + 'VCLinkerTool': { + 'LinkIncremental': '<(msvs_debug_link_incremental)', + # ASLR makes debugging with windbg difficult because Chrome.exe and + # Chrome.dll share the same base name. As result, windbg will + # name the Chrome.dll module like chrome_<base address>, where + # <base address> typically changes with each launch. This in turn + # means that breakpoints in Chrome.dll don't stick from one launch + # to the next. For this reason, we turn ASLR off in debug builds. + # Note that this is a three-way bool, where 0 means to pick up + # the default setting, 1 is off and 2 is on. + 'RandomizedBaseAddress': 1, + }, + 'VCResourceCompilerTool': { + 'PreprocessorDefinitions': ['_DEBUG'], + }, + }, + 'conditions': [ + ['OS=="linux" or OS=="android"', { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '<@(debug_extra_cflags)', + ], + }], + ], + }], + # Disabled on iOS because it was causing a crash on startup. + # TODO(michelea): investigate, create a reduced test and possibly + # submit a radar. + ['release_valgrind_build==0 and OS!="ios"', { + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fstack-protector-all', # Implies -fstack-protector + ], + }, + }], + ], + }, + 'Release_Base': { + 'abstract': 1, + 'defines': [ + 'NDEBUG', + ], + 'xcode_settings': { + 'DEAD_CODE_STRIPPING': 'YES', # -Wl,-dead_strip + 'GCC_OPTIMIZATION_LEVEL': '<(mac_release_optimization)', + 'OTHER_CFLAGS': [ '<@(release_extra_cflags)', ], + }, + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': '<(win_release_RuntimeLibrary)', + 'conditions': [ + # In official builds, each target will self-select + # an optimization level. + ['buildtype!="Official"', { + 'Optimization': '<(win_release_Optimization)', + }, + ], + # According to MSVS, InlineFunctionExpansion=0 means + # "default inlining", not "/Ob0". + # Thus, we have to handle InlineFunctionExpansion==0 separately. + ['win_release_InlineFunctionExpansion==0', { + 'AdditionalOptions': ['/Ob0'], + }], + ['win_release_InlineFunctionExpansion!=""', { + 'InlineFunctionExpansion': + '<(win_release_InlineFunctionExpansion)', + }], + + # if win_release_OmitFramePointers is blank, leave as default + ['win_release_OmitFramePointers==1', { + 'OmitFramePointers': 'true', + }], + ['win_release_OmitFramePointers==0', { + 'OmitFramePointers': 'false', + # The above is not sufficient (http://crbug.com/106711): it + # simply eliminates an explicit "/Oy", but both /O2 and /Ox + # perform FPO regardless, so we must explicitly disable. + # We still want the false setting above to avoid having + # "/Oy /Oy-" and warnings about overriding. + 'AdditionalOptions': ['/Oy-'], + }], + ], + 'AdditionalOptions': [ '<@(win_release_extra_cflags)', ], + }, + 'VCLinkerTool': { + # LinkIncremental is a tri-state boolean, where 0 means default + # (i.e., inherit from parent solution), 1 means false, and + # 2 means true. + 'LinkIncremental': '1', + # This corresponds to the /PROFILE flag which ensures the PDB + # file contains FIXUP information (growing the PDB file by about + # 5%) but does not otherwise alter the output binary. This + # information is used by the Syzygy optimization tool when + # decomposing the release image. + 'Profile': 'true', + }, + }, + 'conditions': [ + ['msvs_use_common_release', { + 'includes': ['release.gypi'], + }], + ['release_valgrind_build==0', { + 'defines': [ + 'NVALGRIND', + 'DYNAMIC_ANNOTATIONS_ENABLED=0', + ], + }, { + 'defines': [ + 'DYNAMIC_ANNOTATIONS_ENABLED=1', + 'WTF_USE_DYNAMIC_ANNOTATIONS=1', + ], + }], + ['win_use_allocator_shim==0', { + 'defines': ['NO_TCMALLOC'], + }], + ['OS=="linux"', { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '<@(release_extra_cflags)', + ], + }], + ], + }], + ], + }, + # + # Concrete configurations + # + 'Debug': { + 'inherit_from': ['Common_Base', 'x86_Base', 'Debug_Base'], + }, + 'Release': { + 'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base'], + }, + 'conditions': [ + [ 'OS=="win"', { + # TODO(bradnelson): add a gyp mechanism to make this more graceful. + 'Debug_x64': { + 'inherit_from': ['Common_Base', 'x64_Base', 'Debug_Base'], + }, + 'Release_x64': { + 'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base'], + }, + }], + ], + }, + }, + 'conditions': [ + ['os_posix==1 and OS!="mac" and OS!="ios"', { + 'target_defaults': { + # Enable -Werror by default, but put it in a variable so it can + # be disabled in ~/.gyp/include.gypi on the valgrind builders. + 'variables': { + 'werror%': '-Werror', + 'libraries_for_target%': '', + }, + 'defines': [ + '_FILE_OFFSET_BITS=64', + ], + 'cflags': [ + '<(werror)', # See note above about the werror variable. + '-pthread', + '-fno-exceptions', + '-fno-strict-aliasing', # See http://crbug.com/32204 + '-Wall', + # TODO(evan): turn this back on once all the builds work. + # '-Wextra', + # Don't warn about unused function params. We use those everywhere. + '-Wno-unused-parameter', + # Don't warn about the "struct foo f = {0};" initialization pattern. + '-Wno-missing-field-initializers', + # Don't export any symbols (for example, to plugins we dlopen()). + # Note: this is *required* to make some plugins work. + '-fvisibility=hidden', + '-pipe', + ], + 'cflags_cc': [ + '-fno-rtti', + '-fno-threadsafe-statics', + # Make inline functions have hidden visiblity by default. + # Surprisingly, not covered by -fvisibility=hidden. + '-fvisibility-inlines-hidden', + # GCC turns on -Wsign-compare for C++ under -Wall, but clang doesn't, + # so we specify it explicitly. + # TODO(fischman): remove this if http://llvm.org/PR10448 obsoletes it. + # http://code.google.com/p/chromium/issues/detail?id=90453 + '-Wsign-compare', + ], + 'ldflags': [ + '-pthread', '-Wl,-z,noexecstack', + ], + 'libraries' : [ + '<(libraries_for_target)', + ], + 'configurations': { + 'Debug_Base': { + 'variables': { + 'debug_optimize%': '0', + }, + 'defines': [ + '_DEBUG', + ], + 'cflags': [ + '-O>(debug_optimize)', + '-g', + ], + 'conditions' : [ + ['OS=="android" and android_full_debug==0', { + # Some configurations are copied from Release_Base to reduce + # the binary size. + 'variables': { + 'debug_optimize%': 's', + }, + 'cflags': [ + '-fomit-frame-pointer', + '-fdata-sections', + '-ffunction-sections', + ], + 'ldflags': [ + '-Wl,-O1', + '-Wl,--as-needed', + '-Wl,--gc-sections', + ], + }], + ], + }, + 'Release_Base': { + 'variables': { + 'release_optimize%': '2', + # Binaries become big and gold is unable to perform GC + # and remove unused sections for some of test targets + # on 32 bit platform. + # (This is currently observed only in chromeos valgrind bots) + # The following flag is to disable --gc-sections linker + # option for these bots. + 'no_gc_sections%': 0, + + # TODO(bradnelson): reexamine how this is done if we change the + # expansion of configurations + 'release_valgrind_build%': 0, + }, + 'cflags': [ + '-O<(release_optimize)', + # Don't emit the GCC version ident directives, they just end up + # in the .comment section taking up binary size. + '-fno-ident', + # Put data and code in their own sections, so that unused symbols + # can be removed at link time with --gc-sections. + '-fdata-sections', + '-ffunction-sections', + ], + 'ldflags': [ + # Specifically tell the linker to perform optimizations. + # See http://lwn.net/Articles/192624/ . + '-Wl,-O1', + '-Wl,--as-needed', + ], + 'conditions' : [ + ['no_gc_sections==0', { + 'ldflags': [ + '-Wl,--gc-sections', + ], + }], + ['OS=="android"', { + 'variables': { + 'release_optimize%': 's', + }, + 'cflags': [ + '-fomit-frame-pointer', + ], + }], + ['clang==1', { + 'cflags!': [ + '-fno-ident', + ], + }], + ['profiling==1', { + 'cflags': [ + '-fno-omit-frame-pointer', + '-g', + ], + }], + ], + }, + }, + 'variants': { + 'coverage': { + 'cflags': ['-fprofile-arcs', '-ftest-coverage'], + 'ldflags': ['-fprofile-arcs'], + }, + 'profile': { + 'cflags': ['-pg', '-g'], + 'ldflags': ['-pg'], + }, + 'symbols': { + 'cflags': ['-g'], + }, + }, + 'conditions': [ + ['target_arch=="ia32"', { + 'target_conditions': [ + ['_toolset=="target"', { + 'asflags': [ + # Needed so that libs with .s files (e.g. libicudata.a) + # are compatible with the general 32-bit-ness. + '-32', + ], + # All floating-point computations on x87 happens in 80-bit + # precision. Because the C and C++ language standards allow + # the compiler to keep the floating-point values in higher + # precision than what's specified in the source and doing so + # is more efficient than constantly rounding up to 64-bit or + # 32-bit precision as specified in the source, the compiler, + # especially in the optimized mode, tries very hard to keep + # values in x87 floating-point stack (in 80-bit precision) + # as long as possible. This has important side effects, that + # the real value used in computation may change depending on + # how the compiler did the optimization - that is, the value + # kept in 80-bit is different than the value rounded down to + # 64-bit or 32-bit. There are possible compiler options to + # make this behavior consistent (e.g. -ffloat-store would keep + # all floating-values in the memory, thus force them to be + # rounded to its original precision) but they have significant + # runtime performance penalty. + # + # -mfpmath=sse -msse2 makes the compiler use SSE instructions + # which keep floating-point values in SSE registers in its + # native precision (32-bit for single precision, and 64-bit + # for double precision values). This means the floating-point + # value used during computation does not change depending on + # how the compiler optimized the code, since the value is + # always kept in its specified precision. + 'conditions': [ + ['branding=="Chromium" and disable_sse2==0', { + 'cflags': [ + '-march=pentium4', + '-msse2', + '-mfpmath=sse', + ], + }], + # ChromeOS targets Pinetrail, which is sse3, but most of the + # benefit comes from sse2 so this setting allows ChromeOS + # to build on other CPUs. In the future -march=atom would + # help but requires a newer compiler. + ['chromeos==1 and disable_sse2==0', { + 'cflags': [ + '-msse2', + ], + }], + # Install packages have started cropping up with + # different headers between the 32-bit and 64-bit + # versions, so we have to shadow those differences off + # and make sure a 32-bit-on-64-bit build picks up the + # right files. + # For android build, use NDK headers instead of host headers + ['host_arch!="ia32" and OS!="android"', { + 'include_dirs+': [ + '/usr/include32', + ], + }], + ], + 'target_conditions': [ + ['_toolset=="target" and OS!="android"', { + # -mmmx allows mmintrin.h to be used for mmx intrinsics. + # video playback is mmx and sse2 optimized. + 'cflags': [ + '-m32', + '-mmmx', + ], + 'ldflags': [ + '-m32', + ], + 'cflags_mozilla': [ + '-m32', + '-mmmx', + ], + }], + ], + }], + ], + }], + ['target_arch=="arm"', { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags_cc': [ + # The codesourcery arm-2009q3 toolchain warns at that the ABI + # has changed whenever it encounters a varargs function. This + # silences those warnings, as they are not helpful and + # clutter legitimate warnings. + '-Wno-abi', + ], + 'conditions': [ + ['arm_thumb==1', { + 'cflags': [ + '-mthumb', + ] + }], + ['armv7==1', { + 'cflags': [ + '-march=armv7-a', + '-mtune=cortex-a8', + '-mfloat-abi=<(arm_float_abi)', + ], + 'conditions': [ + ['arm_neon==1', { + 'cflags': [ '-mfpu=neon', ], + }, { + 'cflags': [ '-mfpu=<(arm_fpu)', ], + }], + ], + }], + ['OS=="android"', { + # Most of the following flags are derived from what Android + # uses by default when building for arm, reference for which + # can be found in the following file in the Android NDK: + # toolchains/arm-linux-androideabi-4.4.3/setup.mk + 'cflags': [ + # The tree-sra optimization (scalar replacement for + # aggregates enabling subsequent optimizations) leads to + # invalid code generation when using the Android NDK's + # compiler (r5-r7). This can be verified using + # TestWebKitAPI's WTF.Checked_int8_t test. + '-fno-tree-sra', + '-fuse-ld=gold', + '-Wno-psabi', + ], + # Android now supports .relro sections properly. + # NOTE: While these flags enable the generation of .relro + # sections, the generated libraries can still be loaded on + # older Android platform versions. + 'ldflags': [ + '-Wl,-z,relro', + '-Wl,-z,now', + '-fuse-ld=gold', + ], + 'conditions': [ + ['arm_thumb == 1', { + # Android toolchain doesn't support -mimplicit-it=thumb + 'cflags!': [ '-Wa,-mimplicit-it=thumb', ], + 'cflags': [ '-mthumb-interwork', ], + }], + ['armv7==0', { + # Flags suitable for Android emulator + 'cflags': [ + '-march=armv5te', + '-mtune=xscale', + '-msoft-float', + ], + 'defines': [ + '__ARM_ARCH_5__', + '__ARM_ARCH_5T__', + '__ARM_ARCH_5E__', + '__ARM_ARCH_5TE__', + ], + }], + ['clang==1', { + 'cflags!': [ + # Clang does not support the following options. + '-mthumb-interwork', + '-finline-limit=64', + '-fno-tree-sra', + '-fuse-ld=gold', + '-Wno-psabi', + ], + }], + ], + }], + ], + }], + ], + }], + ['linux_fpic==1', { + 'cflags': [ + '-fPIC', + ], + 'ldflags': [ + '-fPIC', + ], + }], + ['sysroot!=""', { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '--sysroot=<(sysroot)', + ], + 'ldflags': [ + '--sysroot=<(sysroot)', + ], + }]] + }], + ['clang==1', { + 'cflags': [ + '-Wheader-hygiene', + # Clang spots more unused functions. + '-Wno-unused-function', + # Don't die on dtoa code that uses a char as an array index. + '-Wno-char-subscripts', + # Especially needed for gtest macros using enum values from Mac + # system headers. + # TODO(pkasting): In C++11 this is legal, so this should be + # removed when we change to that. (This is also why we don't + # bother fixing all these cases today.) + '-Wno-unnamed-type-template-args', + # This (rightyfully) complains about 'override', which we use + # heavily. + '-Wno-c++11-extensions', + + # Warns on switches on enums that cover all enum values but + # also contain a default: branch. Chrome is full of that. + '-Wno-covered-switch-default', + + # TODO(thakis): Remove this. + '-Wno-implicit-conversion-floating-point-to-bool', + ], + 'cflags!': [ + # Clang doesn't seem to know know this flag. + '-mfpmath=sse', + ], + }], + ['clang==1 and clang_use_chrome_plugins==1', { + 'cflags': [ + '<@(clang_chrome_plugins_flags)', + ], + }], + ['clang==1 and clang_load!=""', { + 'cflags': [ + '-Xclang', '-load', '-Xclang', '<(clang_load)', + ], + }], + ['clang==1 and clang_add_plugin!=""', { + 'cflags': [ + '-Xclang', '-add-plugin', '-Xclang', '<(clang_add_plugin)', + ], + }], + ['clang==1 and "<(GENERATOR)"=="ninja"', { + 'cflags': [ + # See http://crbug.com/110262 + '-fcolor-diagnostics', + ], + }], + ['asan==1', { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '-faddress-sanitizer', + '-fno-omit-frame-pointer', + ], + 'ldflags': [ + '-faddress-sanitizer', + ], + 'defines': [ + 'ADDRESS_SANITIZER', + ], + }], + ], + }], + ['tsan==1', { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '-fthread-sanitizer', + '-fno-omit-frame-pointer', + '-fPIE', + ], + 'ldflags': [ + '-fthread-sanitizer', + ], + 'defines': [ + 'THREAD_SANITIZER', + 'DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1', + ], + 'target_conditions': [ + ['_type=="executable"', { + 'ldflags': [ + '-pie', + ], + }], + ], + }], + ], + }], + ['order_profiling!=0 and (chromeos==1 or OS=="linux")', { + 'target_conditions' : [ + ['_toolset=="target"', { + 'cflags': [ + '-finstrument-functions', + # Allow mmx intrinsics to inline, so that the + # compiler can expand the intrinsics. + '-finstrument-functions-exclude-file-list=mmintrin.h', + ], + }], + ], + }], + ['linux_breakpad==1', { + 'cflags': [ '-g' ], + 'defines': ['USE_LINUX_BREAKPAD'], + }], + ['linux_use_heapchecker==1', { + 'variables': {'linux_use_tcmalloc%': 1}, + 'defines': ['USE_HEAPCHECKER'], + }], + ['linux_use_tcmalloc==0', { + 'defines': ['NO_TCMALLOC'], + }], + ['linux_keep_shadow_stacks==1', { + 'defines': ['KEEP_SHADOW_STACKS'], + 'cflags': [ + '-finstrument-functions', + # Allow mmx intrinsics to inline, so that the compiler can expand + # the intrinsics. + '-finstrument-functions-exclude-file-list=mmintrin.h', + ], + }], + ['linux_use_gold_flags==1', { + 'ldflags': [ + # Experimentation found that using four linking threads + # saved ~20% of link time. + # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36 + '-Wl,--threads', + '-Wl,--thread-count=4', + ], + 'conditions': [ + ['release_valgrind_build==0', { + 'target_conditions': [ + ['_toolset=="target"', { + 'ldflags': [ + # There seems to be a conflict of --icf and -pie + # in gold which can generate crashy binaries. As + # a security measure, -pie takes precendence for + # now. + #'-Wl,--icf=safe', + '-Wl,--icf=none', + ], + }], + ], + }], + ], + }], + ['linux_use_gold_binary==1', { + 'variables': { + 'conditions': [ + ['inside_chromium_build==1', { + # We pass the path to gold to the compiler. gyp leaves + # unspecified what the cwd is when running the compiler, + # so the normal gyp path-munging fails us. This hack + # gets the right path. + 'gold_path': '<(PRODUCT_DIR)/../../third_party/gold', + }, { + 'gold_path': '<(PRODUCT_DIR)/../../Source/WebKit/chromium/third_party/gold', + }] + ] + }, + 'ldflags': [ + # Put our gold binary in the search path for the linker. + '-B<(gold_path)', + ], + }], + ], + }, + }], + # FreeBSD-specific options; note that most FreeBSD options are set above, + # with Linux. + ['OS=="freebsd"', { + 'target_defaults': { + 'ldflags': [ + '-Wl,--no-keep-memory', + ], + }, + }], + # Android-specific options; note that most are set above with Linux. + ['OS=="android"', { + 'variables': { + # This is the id for the archived chrome symbols. Each build that + # archives symbols is assigned an id which is then added to GYP_DEFINES. + # This is written to the device log on crashes just prior to dropping a + # tombstone. Tools can determine the location of the archived symbols + # from the id. + 'chrome_symbols_id%': '', + 'conditions': [ + # Use shared stlport library when system one used. + # Figure this out early since it needs symbols from libgcc.a, so it + # has to be before that in the set of libraries. + ['use_system_stlport==1', { + 'android_stlport_library': 'stlport', + }, { + 'android_stlport_library': 'stlport_static', + }], + ], + + # Placing this variable here prevents from forking libvpx, used + # by remoting. Remoting is off, so it needn't built, + # so forking it's deps seems like overkill. + # But this variable need defined to properly run gyp. + # A proper solution is to have an OS==android conditional + # in third_party/libvpx/libvpx.gyp to define it. + 'libvpx_path': 'lib/linux/arm', + }, + 'target_defaults': { + 'variables': { + 'release_extra_cflags%': '', + }, + + 'target_conditions': [ + # Settings for building device targets using Android's toolchain. + # These are based on the setup.mk file from the Android NDK. + # + # The NDK Android executable link step looks as follows: + # $LDFLAGS + # $(TARGET_CRTBEGIN_DYNAMIC_O) <-- crtbegin.o + # $(PRIVATE_OBJECTS) <-- The .o that we built + # $(PRIVATE_STATIC_LIBRARIES) <-- The .a that we built + # $(TARGET_LIBGCC) <-- libgcc.a + # $(PRIVATE_SHARED_LIBRARIES) <-- The .so that we built + # $(PRIVATE_LDLIBS) <-- System .so + # $(TARGET_CRTEND_O) <-- crtend.o + # + # For now the above are approximated for executables by adding + # crtbegin.o to the end of the ldflags and 'crtend.o' to the end + # of 'libraries'. + # + # The NDK Android shared library link step looks as follows: + # $LDFLAGS + # $(PRIVATE_OBJECTS) <-- The .o that we built + # -l,--whole-archive + # $(PRIVATE_WHOLE_STATIC_LIBRARIES) + # -l,--no-whole-archive + # $(PRIVATE_STATIC_LIBRARIES) <-- The .a that we built + # $(TARGET_LIBGCC) <-- libgcc.a + # $(PRIVATE_SHARED_LIBRARIES) <-- The .so that we built + # $(PRIVATE_LDLIBS) <-- System .so + # + # For now, assume that whole static libraries are not needed. + # + # For both executables and shared libraries, add the proper + # libgcc.a to the start of libraries which puts it in the + # proper spot after .o and .a files get linked in. + # + # TODO: The proper thing to do longer-tem would be proper gyp + # support for a custom link command line. + ['_toolset=="target"', { + 'conditions': [ + ['build_with_mozilla==0', { + 'cflags!': [ + '-pthread', # Not supported by Android toolchain. + ], + 'cflags': [ + '-ffunction-sections', + '-funwind-tables', + '-g', + '-fstack-protector', + '-fno-short-enums', + '-finline-limit=64', + '-Wa,--noexecstack', + '<@(release_extra_cflags)', + ], + 'ldflags!': [ + '-pthread', # Not supported by Android toolchain. + ], + 'ldflags': [ + '-nostdlib', + '-Wl,--no-undefined', + # Don't export symbols from statically linked libraries. + '-Wl,--exclude-libs=ALL', + ], + 'libraries': [ + '-l<(android_stlport_library)', + '-lc', + '-ldl', + '-lstdc++', + '-lm', + ], + 'conditions': [ + ['android_upstream_bringup==1', { + 'defines': ['ANDROID_UPSTREAM_BRINGUP=1',], + }], + ['clang==1', { + 'cflags': [ + # Work around incompatibilities between bionic and clang + # headers. + '-D__compiler_offsetof=__builtin_offsetof', + '-Dnan=__builtin_nan', + ], + 'conditions': [ + ['target_arch=="arm"', { + 'cflags': [ + '-target arm-linux-androideabi', + '-mllvm -arm-enable-ehabi', + ], + 'ldflags': [ + '-target arm-linux-androideabi', + ], + }], + ['target_arch=="ia32"', { + 'cflags': [ + '-target x86-linux-androideabi', + ], + 'ldflags': [ + '-target x86-linux-androideabi', + ], + }], + ], + }], + ['android_build_type==0', { + 'defines': [ + # The NDK has these things, but doesn't define the constants + # to say that it does. Define them here instead. + 'HAVE_SYS_UIO_H', + ], + 'cflags': [ + '--sysroot=<(android_ndk_sysroot)', + ], + 'ldflags': [ + '--sysroot=<(android_ndk_sysroot)', + ], + }], + ['android_build_type==1', { + 'include_dirs': [ + # OpenAL headers from the Android tree. + '<(android_src)/frameworks/wilhelm/include', + ], + 'cflags': [ + # Chromium builds its own (non-third-party) code with + # -Werror to make all warnings into errors. However, Android + # enables warnings that Chromium doesn't, so some of these + # extra warnings trip and break things. + # For now, we leave these warnings enabled but prevent them + # from being treated as errors. + # + # Things that are part of -Wextra: + '-Wno-error=extra', # Enabled by -Wextra, but no specific flag + '-Wno-error=ignored-qualifiers', + '-Wno-error=type-limits', + # Other things unrelated to -Wextra: + '-Wno-error=non-virtual-dtor', + '-Wno-error=sign-promo', + ], + 'cflags_cc': [ + # Disabling c++0x-compat should be handled in WebKit, but + # this currently doesn't work because gcc_version is not set + # correctly when building with the Android build system. + # TODO(torne): Fix this in WebKit. + '-Wno-error=c++0x-compat', + ], + }], + ['android_build_type==1 and chromium_code==0', { + 'cflags': [ + # There is a class of warning which: + # 1) Android always enables and also treats as errors + # 2) Chromium ignores in third party code + # For now, I am leaving these warnings enabled but preventing + # them from being treated as errors here. + '-Wno-error=address', + '-Wno-error=format-security', + '-Wno-error=non-virtual-dtor', + '-Wno-error=return-type', + '-Wno-error=sequence-point', + ], + }], + ['target_arch == "arm"', { + 'ldflags': [ + # Enable identical code folding to reduce size. + '-Wl,--icf=safe', + ], + }], + # NOTE: The stlport header include paths below are specified in + # cflags rather than include_dirs because they need to come + # after include_dirs. Think of them like system headers, but + # don't use '-isystem' because the arm-linux-androideabi-4.4.3 + # toolchain (circa Gingerbread) will exhibit strange errors. + # The include ordering here is important; change with caution. + ['use_system_stlport==1', { + 'cflags': [ + # For libstdc++/include, which is used by stlport. + '-I<(android_src)/bionic', + '-I<(android_src)/external/stlport/stlport', + ], + }, { # else: use_system_stlport!=1 + 'cflags': [ + '-I<(android_ndk_root)/sources/cxx-stl/stlport/stlport', + ], + 'conditions': [ + ['target_arch=="arm" and armv7==1', { + 'ldflags': [ + '-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/armeabi-v7a', + ], + }], + ['target_arch=="arm" and armv7==0', { + 'ldflags': [ + '-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/armeabi', + ], + }], + ['target_arch=="ia32"', { + 'ldflags': [ + '-L<(android_ndk_root)/sources/cxx-stl/stlport/libs/x86', + ], + }], + ], + }], + ['target_arch=="ia32"', { + # The x86 toolchain currently has problems with stack-protector. + 'cflags!': [ + '-fstack-protector', + ], + 'cflags': [ + '-fno-stack-protector', + ], + }], + ], + 'target_conditions': [ + ['_type=="executable"', { + 'ldflags': [ + '-Bdynamic', + '-Wl,-dynamic-linker,/system/bin/linker', + '-Wl,--gc-sections', + '-Wl,-z,nocopyreloc', + # crtbegin_dynamic.o should be the last item in ldflags. + '<(android_ndk_lib)/crtbegin_dynamic.o', + ], + 'libraries': [ + # crtend_android.o needs to be the last item in libraries. + # Do not add any libraries after this! + '<(android_ndk_lib)/crtend_android.o', + ], + }], + ['_type=="shared_library" or _type=="loadable_module"', { + 'ldflags': [ + '-Wl,-shared,-Bsymbolic', + # crtbegin_so.o should be the last item in ldflags. + '<(android_ndk_lib)/crtbegin_so.o', + ], + 'libraries': [ + # crtend_so.o needs to be the last item in libraries. + # Do not add any libraries after this! + '<(android_ndk_lib)/crtend_so.o', + ], + }], + ], + + }], # build_with_mozilla== 0 + + ], + 'defines': [ + 'ANDROID', + '__GNU_SOURCE=1', # Necessary for clone() + 'USE_STLPORT=1', + '_STLP_USE_PTR_SPECIALIZATIONS=1', + 'CHROME_SYMBOLS_ID="<(chrome_symbols_id)"', + ], + }], + # Settings for building host targets using the system toolchain. + ['_toolset=="host"', { + 'cflags!': [ + # Due to issues in Clang build system, using ASan on 32-bit + # binaries on x86_64 host is problematic. + # TODO(eugenis): re-enable. + '-faddress-sanitizer', + ], + 'ldflags!': [ + '-faddress-sanitizer', + '-Wl,-z,noexecstack', + '-Wl,--gc-sections', + '-Wl,-O1', + '-Wl,--as-needed', + ], + 'sources/': [ + ['exclude', '_android(_unittest)?\\.cc$'], + ['exclude', '(^|/)android/'] + ], + }], + ], + }, + }], + ['OS=="solaris"', { + 'cflags!': ['-fvisibility=hidden'], + 'cflags_cc!': ['-fvisibility-inlines-hidden'], + }], + ['OS=="mac" or OS=="ios"', { + 'target_defaults': { + 'mac_bundle': 0, + 'xcode_settings': { + 'ALWAYS_SEARCH_USER_PATHS': 'NO', + 'GCC_C_LANGUAGE_STANDARD': 'c99', # -std=c99 + 'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks + 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions + 'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti + 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings + # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden + 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES', + 'GCC_OBJC_CALL_CXX_CDTORS': 'YES', # -fobjc-call-cxx-cdtors + 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden + 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics + 'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES', # -Werror + 'GCC_VERSION': '4.2', + 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof + 'USE_HEADERMAP': 'NO', + 'WARNING_CFLAGS': [ + '-Wall', + '-Wendif-labels', + '-Wextra', + # Don't warn about unused function parameters. + '-Wno-unused-parameter', + # Don't warn about the "struct foo f = {0};" initialization + # pattern. + '-Wno-missing-field-initializers', + ], + 'conditions': [ + ['chromium_mac_pch', {'GCC_PRECOMPILE_PREFIX_HEADER': 'YES'}, + {'GCC_PRECOMPILE_PREFIX_HEADER': 'NO'} + ], + ], + }, + 'target_conditions': [ + ['_type!="static_library"', { + 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']}, + }], + ['_mac_bundle', { + 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, + }], + ], # target_conditions + }, # target_defaults + }], # OS=="mac" or OS=="ios" + ['OS=="mac"', { + 'target_defaults': { + 'variables': { + # These should end with %, but there seems to be a bug with % in + # variables that are intended to be set to different values in + # different targets, like these. + 'mac_pie': 1, # Most executables can be position-independent. + 'mac_real_dsym': 0, # Fake .dSYMs are fine in most cases. + # Strip debugging symbols from the target. + 'mac_strip': '<(mac_strip_release)', + }, + 'xcode_settings': { + 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic + # (Equivalent to -fPIC) + # MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min + 'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)', + # Keep pch files below xcodebuild/. + 'SHARED_PRECOMPS_DIR': '$(CONFIGURATION_BUILD_DIR)/SharedPrecompiledHeaders', + 'OTHER_CFLAGS': [ + '-fno-strict-aliasing', # See http://crbug.com/32204 + ], + 'conditions': [ + ['clang==1', { + 'CC': '$(SOURCE_ROOT)/<(clang_dir)/clang', + 'LDPLUSPLUS': '$(SOURCE_ROOT)/<(clang_dir)/clang++', + + # Don't use -Wc++0x-extensions, which Xcode 4 enables by default + # when buliding with clang. This warning is triggered when the + # override keyword is used via the OVERRIDE macro from + # base/compiler_specific.h. + 'CLANG_WARN_CXX0X_EXTENSIONS': 'NO', + + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + 'WARNING_CFLAGS': [ + '-Wheader-hygiene', + # Don't die on dtoa code that uses a char as an array index. + # This is required solely for base/third_party/dmg_fp/dtoa.cc. + '-Wno-char-subscripts', + # Clang spots more unused functions. + '-Wno-unused-function', + # See comments on this flag higher up in this file. + '-Wno-unnamed-type-template-args', + # This (rightyfully) complains about 'override', which we use + # heavily. + '-Wno-c++11-extensions', + + # Warns on switches on enums that cover all enum values but + # also contain a default: branch. Chrome is full of that. + '-Wno-covered-switch-default', + + # TODO(thakis): Remove this. + '-Wno-implicit-conversion-floating-point-to-bool', + ], + }], + ['clang==1 and clang_use_chrome_plugins==1', { + 'OTHER_CFLAGS': [ + '<@(clang_chrome_plugins_flags)', + ], + }], + ['clang==1 and clang_load!=""', { + 'OTHER_CFLAGS': [ + '-Xclang', '-load', '-Xclang', '<(clang_load)', + ], + }], + ['clang==1 and clang_add_plugin!=""', { + 'OTHER_CFLAGS': [ + '-Xclang', '-add-plugin', '-Xclang', '<(clang_add_plugin)', + ], + }], + ['clang==1 and "<(GENERATOR)"=="ninja"', { + 'OTHER_CFLAGS': [ + # See http://crbug.com/110262 + '-fcolor-diagnostics', + ], + }], + ], + }, + 'conditions': [ + ['clang==1', { + 'variables': { + 'clang_dir': '../third_party/llvm-build/Release+Asserts/bin', + }, + }], + ['asan==1', { + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-faddress-sanitizer', + ], + }, + 'defines': [ + 'ADDRESS_SANITIZER', + ], + }], + ], + 'target_conditions': [ + ['_type!="static_library"', { + 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']}, + 'conditions': [ + ['asan==1', { + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-faddress-sanitizer', + ], + }, + }], + ], + }], + ['_mac_bundle', { + 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, + }], + ['_type=="executable"', { + 'postbuilds': [ + { + # Arranges for data (heap) pages to be protected against + # code execution when running on Mac OS X 10.7 ("Lion"), and + # ensures that the position-independent executable (PIE) bit + # is set for ASLR when running on Mac OS X 10.5 ("Leopard"). + 'variables': { + # Define change_mach_o_flags in a variable ending in _path + # so that GYP understands it's a path and performs proper + # relativization during dict merging. + 'change_mach_o_flags': + 'mac/change_mach_o_flags_from_xcode.sh', + 'change_mach_o_flags_options%': [ + ], + 'target_conditions': [ + ['mac_pie==0 or release_valgrind_build==1', { + # Don't enable PIE if it's unwanted. It's unwanted if + # the target specifies mac_pie=0 or if building for + # Valgrind, because Valgrind doesn't understand slide. + # See the similar mac_pie/release_valgrind_build check + # below. + 'change_mach_o_flags_options': [ + '--no-pie', + ], + }], + ], + }, + 'postbuild_name': 'Change Mach-O Flags', + 'action': [ + '$(srcdir)$(os_sep)build$(os_sep)<(change_mach_o_flags)', + '>@(change_mach_o_flags_options)', + ], + }, + ], + 'conditions': [ + ['asan==1', { + 'variables': { + 'asan_saves_file': 'asan.saves', + }, + 'xcode_settings': { + 'CHROMIUM_STRIP_SAVE_FILE': '<(asan_saves_file)', + }, + }], + ], + 'target_conditions': [ + ['mac_pie==1 and release_valgrind_build==0', { + # Turn on position-independence (ASLR) for executables. When + # PIE is on for the Chrome executables, the framework will + # also be subject to ASLR. + # Don't do this when building for Valgrind, because Valgrind + # doesn't understand slide. TODO: Make Valgrind on Mac OS X + # understand slide, and get rid of the Valgrind check. + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-Wl,-pie', # Position-independent executable (MH_PIE) + ], + }, + }], + ], + }], + ['(_type=="executable" or _type=="shared_library" or \ + _type=="loadable_module") and mac_strip!=0', { + 'target_conditions': [ + ['mac_real_dsym == 1', { + # To get a real .dSYM bundle produced by dsymutil, set the + # debug information format to dwarf-with-dsym. Since + # strip_from_xcode will not be used, set Xcode to do the + # stripping as well. + 'configurations': { + 'Release_Base': { + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'target_conditions': [ + ['_type=="shared_library" or _type=="loadable_module"', { + # The Xcode default is to strip debugging symbols + # only (-S). Local symbols should be stripped as + # well, which will be handled by -x. Xcode will + # continue to insert -S when stripping even when + # additional flags are added with STRIPFLAGS. + 'STRIPFLAGS': '-x', + }], # _type=="shared_library" or _type=="loadable_module"' + ], # target_conditions + }, # xcode_settings + }, # configuration "Release" + }, # configurations + }, { # mac_real_dsym != 1 + # To get a fast fake .dSYM bundle, use a post-build step to + # produce the .dSYM and strip the executable. strip_from_xcode + # only operates in the Release configuration. + 'postbuilds': [ + { + 'variables': { + # Define strip_from_xcode in a variable ending in _path + # so that gyp understands it's a path and performs proper + # relativization during dict merging. + 'strip_from_xcode': 'mac/strip_from_xcode', + }, + 'postbuild_name': 'Strip If Needed', + 'action': ['$(srcdir)$(os_sep)build$(os_sep)<(strip_from_xcode)'], + }, + ], # postbuilds + }], # mac_real_dsym + ], # target_conditions + }], # (_type=="executable" or _type=="shared_library" or + # _type=="loadable_module") and mac_strip!=0 + ], # target_conditions + }, # target_defaults + }], # OS=="mac" + ['OS=="ios"', { + 'target_defaults': { + 'xcode_settings' : { + 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0', + + # This next block is mostly common with the 'mac' section above, + # but keying off (or setting) 'clang' isn't valid for iOS as it + # also seems to mean using the custom build of clang. + + # Don't use -Wc++0x-extensions, which Xcode 4 enables by default + # when buliding with clang. This warning is triggered when the + # override keyword is used via the OVERRIDE macro from + # base/compiler_specific.h. + 'CLANG_WARN_CXX0X_EXTENSIONS': 'NO', + 'WARNING_CFLAGS': [ + '-Wheader-hygiene', + # Don't die on dtoa code that uses a char as an array index. + # This is required solely for base/third_party/dmg_fp/dtoa.cc. + '-Wno-char-subscripts', + # Clang spots more unused functions. + '-Wno-unused-function', + # See comments on this flag higher up in this file. + '-Wno-unnamed-type-template-args', + # This (rightyfully) complains about 'override', which we use + # heavily. + '-Wno-c++11-extensions', + ], + }, + 'target_conditions': [ + ['_type=="executable"', { + 'configurations': { + 'Release_Base': { + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + }, + 'xcode_settings': { + 'conditions': [ + ['chromium_ios_signing', { + # iOS SDK wants everything for device signed. + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': 'iPhone Developer', + }, { + 'CODE_SIGNING_REQUIRED': 'NO', + 'CODE_SIGN_IDENTITY[sdk=iphoneos*]': '', + }], + ], + }, + }], + ], # target_conditions + }, # target_defaults + }], # OS=="ios" + ['OS=="win"', { + 'target_defaults': { + 'defines': [ + 'WIN32', + '_WINDOWS', + 'NOMINMAX', + '_CRT_RAND_S', + 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS', + 'WIN32_LEAN_AND_MEAN', + '_ATL_NO_OPENGL', + ], + 'conditions': [ + ['build_with_mozilla==0', { + 'defines': [ + '_WIN32_WINNT=0x0602', + 'WINVER=0x0602', + ], + }], + ['buildtype=="Official"', { + # In official builds, targets can self-select an optimization + # level by defining a variable named 'optimize', and setting it + # to one of + # - "size", optimizes for minimal code size - the default. + # - "speed", optimizes for speed over code size. + # - "max", whole program optimization and link-time code + # generation. This is very expensive and should be used + # sparingly. + 'variables': { + 'optimize%': 'size', + }, + 'target_conditions': [ + ['optimize=="size"', { + 'msvs_settings': { + 'VCCLCompilerTool': { + # 1, optimizeMinSpace, Minimize Size (/O1) + 'Optimization': '1', + # 2, favorSize - Favor small code (/Os) + 'FavorSizeOrSpeed': '2', + }, + }, + }, + ], + ['optimize=="speed"', { + 'msvs_settings': { + 'VCCLCompilerTool': { + # 2, optimizeMaxSpeed, Maximize Speed (/O2) + 'Optimization': '2', + # 1, favorSpeed - Favor fast code (/Ot) + 'FavorSizeOrSpeed': '1', + }, + }, + }, + ], + ['optimize=="max"', { + 'msvs_settings': { + 'VCCLCompilerTool': { + # 2, optimizeMaxSpeed, Maximize Speed (/O2) + 'Optimization': '2', + # 1, favorSpeed - Favor fast code (/Ot) + 'FavorSizeOrSpeed': '1', + # This implies link time code generation. + 'WholeProgramOptimization': 'true', + }, + }, + }, + ], + ], + }, + ], + ['component=="static_library"', { + 'defines': [ + '_HAS_EXCEPTIONS=0', + ], + }], + ['MSVS_VERSION=="2008"', { + 'defines': [ + '_HAS_TR1=0', + ], + }], + ['secure_atl', { + 'defines': [ + '_SECURE_ATL', + ], + }], + ], + 'msvs_system_include_dirs': [ + '<(windows_sdk_path)/Include/shared', + '<(windows_sdk_path)/Include/um', + '<(windows_sdk_path)/Include/winrt', +# '<(directx_sdk_path)/Include', + '$(VSInstallDir)/VC/atlmfc/include', + ], + 'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'], + 'msvs_disabled_warnings': [4351, 4396, 4503, 4819, + # TODO(maruel): These warnings are level 4. They will be slowly + # removed as code is fixed. + 4100, 4121, 4125, 4127, 4130, 4131, 4189, 4201, 4238, 4244, 4245, + 4310, 4355, 4428, 4481, 4505, 4510, 4512, 4530, 4610, 4611, 4701, + 4702, 4706, + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'AdditionalOptions': ['/MP'], + 'MinimalRebuild': 'false', + 'BufferSecurityCheck': 'true', + 'EnableFunctionLevelLinking': 'true', + 'RuntimeTypeInfo': 'false', + 'WarningLevel': '4', + 'WarnAsError': 'true', + 'DebugInformationFormat': '3', + 'conditions': [ + ['component=="shared_library"', { + 'ExceptionHandling': '1', # /EHsc + }, { + 'ExceptionHandling': '0', + }], + ], + }, + 'VCLibrarianTool': { + 'AdditionalOptions': ['/ignore:4221'], + 'AdditionalLibraryDirectories': [ +# '<(directx_sdk_path)/Lib/x86', + '<(windows_sdk_path)/Lib/win8/um/x86', + ], + }, + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'wininet.lib', + 'dnsapi.lib', + 'version.lib', + 'msimg32.lib', + 'ws2_32.lib', + 'usp10.lib', + 'dbghelp.lib', + 'winmm.lib', + 'shlwapi.lib', + ], + + 'conditions': [ + ['msvs_express', { + # Explicitly required when using the ATL with express + 'AdditionalDependencies': [ + 'atlthunk.lib', + ], + + # ATL 8.0 included in WDK 7.1 makes the linker to generate + # almost eight hundred LNK4254 and LNK4078 warnings: + # - warning LNK4254: section 'ATL' (50000040) merged into + # '.rdata' (40000040) with different attributes + # - warning LNK4078: multiple 'ATL' sections found with + # different attributes + 'AdditionalOptions': ['/ignore:4254', '/ignore:4078'], + }], + ['MSVS_VERSION=="2005e"', { + # Non-express versions link automatically to these + 'AdditionalDependencies': [ + 'advapi32.lib', + 'comdlg32.lib', + 'ole32.lib', + 'shell32.lib', + 'user32.lib', + 'winspool.lib', + ], + }], + ], + 'AdditionalLibraryDirectories': [ +# '<(directx_sdk_path)/Lib/x86', XXXX + '<(windows_sdk_path)/Lib/win8/um/x86', + ], + 'GenerateDebugInformation': 'true', + 'MapFileName': '$(OutDir)\\$(TargetName).map', + 'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib', + 'FixedBaseAddress': '1', + # SubSystem values: + # 0 == not set + # 1 == /SUBSYSTEM:CONSOLE + # 2 == /SUBSYSTEM:WINDOWS + # Most of the executables we'll ever create are tests + # and utilities with console output. + 'SubSystem': '1', + }, + 'VCMIDLTool': { + 'GenerateStublessProxies': 'true', + 'TypeLibraryName': '$(InputName).tlb', + 'OutputDirectory': '$(IntDir)', + 'HeaderFileName': '$(InputName).h', + 'DLLDataFileName': '$(InputName).dlldata.c', + 'InterfaceIdentifierFileName': '$(InputName)_i.c', + 'ProxyFileName': '$(InputName)_p.c', + }, + 'VCResourceCompilerTool': { + 'Culture' : '1033', + 'AdditionalIncludeDirectories': [ + '<(DEPTH)', + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + }, + }], + ['disable_nacl==1', { + 'target_defaults': { + 'defines': [ + 'DISABLE_NACL', + ], + }, + }], + ['OS=="win" and msvs_use_common_linker_extras', { + 'target_defaults': { + 'msvs_settings': { + 'VCLinkerTool': { + 'DelayLoadDLLs': [ + 'dbghelp.dll', + 'dwmapi.dll', + 'shell32.dll', + 'uxtheme.dll', + ], + }, + }, + 'configurations': { + 'x86_Base': { + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalOptions': [ + '/safeseh', + '/dynamicbase', + '/ignore:4199', + '/ignore:4221', + '/nxcompat', + ], + }, + }, + }, + 'x64_Base': { + 'msvs_settings': { + 'VCLinkerTool': { + 'AdditionalOptions': [ + # safeseh is not compatible with x64 + '/dynamicbase', + '/ignore:4199', + '/ignore:4221', + '/nxcompat', + ], + }, + }, + }, + }, + }, + }], + ['enable_new_npdevice_api==1', { + 'target_defaults': { + 'defines': [ + 'ENABLE_NEW_NPDEVICE_API', + ], + }, + }], + ], + 'xcode_settings': { + # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT! + # This block adds *project-wide* configuration settings to each project + # file. It's almost always wrong to put things here. Specify your + # custom xcode_settings in target_defaults to add them to targets instead. + + 'conditions': [ + # In an Xcode Project Info window, the "Base SDK for All Configurations" + # setting sets the SDK on a project-wide basis. In order to get the + # configured SDK to show properly in the Xcode UI, SDKROOT must be set + # here at the project level. + ['OS=="mac"', { + 'conditions': [ + ['mac_sdk_path==""', { + 'SDKROOT': 'macosx<(mac_sdk)', # -isysroot + }, { + 'SDKROOT': '<(mac_sdk_path)', # -isysroot + }], + ], + }], + ['OS=="ios"', { + 'conditions': [ + ['ios_sdk_path==""', { + 'SDKROOT': 'iphoneos<(ios_sdk)', # -isysroot + }, { + 'SDKROOT': '<(ios_sdk_path)', # -isysroot + }], + ], + }], + ['OS=="ios"', { + # Just build armv7 since iOS 4.3+ only supports armv7. + 'ARCHS': '$(ARCHS_UNIVERSAL_IPHONE_OS)', + 'IPHONEOS_DEPLOYMENT_TARGET': '<(ios_deployment_target)', + # Target both iPhone and iPad. + 'TARGETED_DEVICE_FAMILY': '1,2', + }], + ], + + # The Xcode generator will look for an xcode_settings section at the root + # of each dict and use it to apply settings on a file-wide basis. Most + # settings should not be here, they should be in target-specific + # xcode_settings sections, or better yet, should use non-Xcode-specific + # settings in target dicts. SYMROOT is a special case, because many other + # Xcode variables depend on it, including variables such as + # PROJECT_DERIVED_FILE_DIR. When a source group corresponding to something + # like PROJECT_DERIVED_FILE_DIR is added to a project, in order for the + # files to appear (when present) in the UI as actual files and not red + # red "missing file" proxies, the correct path to PROJECT_DERIVED_FILE_DIR, + # and therefore SYMROOT, needs to be set at the project level. + 'SYMROOT': '<(DEPTH)/xcodebuild', + }, +} diff --git a/build/gyp_includes/filename_rules.gypi b/build/gyp_includes/filename_rules.gypi new file mode 100644 index 0000000000..7b16a15595 --- /dev/null +++ b/build/gyp_includes/filename_rules.gypi @@ -0,0 +1,96 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This gypi file defines the patterns used for determining whether a +# file is excluded from the build on a given platform. It is +# included by common.gypi for chromium_code. + +{ + 'target_conditions': [ + ['OS!="win" or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_win(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)win/'], + ['exclude', '(^|/)win_[^/]*\\.(h|cc)$'] ], + }], + ['OS!="mac" or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_(cocoa|mac)(_unittest)?\\.(h|cc|mm?)$'], + ['exclude', '(^|/)(cocoa|mac)/'] ], + }], + ['OS!="ios" or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_ios(_unittest)?\\.(h|cc|mm?)$'], + ['exclude', '(^|/)ios/'] ], + }], + ['(OS!="mac" and OS!="ios") or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '\\.mm?$' ] ], + }], + # Do not exclude the linux files on *BSD since most of them can be + # shared at this point. + # In case a file is not needed, it is going to be excluded later on. + # TODO(evan): the above is not correct; we shouldn't build _linux + # files on non-linux. + ['OS!="linux" and OS!="solaris" and <(os_bsd)!=1 or >(nacl_untrusted_build)==1', { + 'sources/': [ + ['exclude', '_linux(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)linux/'], + ], + }], + ['OS!="android"', { + 'sources/': [ + ['exclude', '_android(_unittest)?\\.cc$'], + ['exclude', '(^|/)android/'], + ], + }], + ['OS=="win" and >(nacl_untrusted_build)==0', { + 'sources/': [ + ['exclude', '_posix(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)posix/'], + ], + }], + ['<(chromeos)!=1 or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_chromeos(_unittest)?\\.(h|cc)$'] ] + }], + ['>(nacl_untrusted_build)==0', { + 'sources/': [ + ['exclude', '_nacl(_unittest)?\\.(h|cc)$'], + ], + }], + ['OS!="linux" and OS!="solaris" and <(os_bsd)!=1 or >(nacl_untrusted_build)==1', { + 'sources/': [ + ['exclude', '_xdg(_unittest)?\\.(h|cc)$'], + ], + }], + ['<(use_x11)!=1 or >(nacl_untrusted_build)==1', { + 'sources/': [ + ['exclude', '_(x|x11)(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)x11_[^/]*\\.(h|cc)$'], + ], + }], + ['(<(toolkit_uses_gtk)!=1 or >(nacl_untrusted_build)==1) and (build_with_mozilla==0)', { + 'sources/': [ + ['exclude', '_gtk(_browsertest|_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)gtk/'], + ['exclude', '(^|/)gtk_[^/]*\\.(h|cc)$'], + ], + }], + ['<(toolkit_views)==0 or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_views\\.(h|cc)$'] ] + }], + ['<(use_aura)==0 or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_aura(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)aura/'], + ] + }], + ['<(use_aura)==0 or <(use_x11)==0 or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_aurax11\\.(h|cc)$'] ] + }], + ['<(use_aura)==0 or OS!="win" or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_aurawin\\.(h|cc)$'] ] + }], + ['<(use_ash)==0 or >(nacl_untrusted_build)==1', { + 'sources/': [ ['exclude', '_ash(_unittest)?\\.(h|cc)$'], + ['exclude', '(^|/)ash/'], + ] + }], + ] +} diff --git a/build/gyp_includes/internal/release_defaults.gypi b/build/gyp_includes/internal/release_defaults.gypi new file mode 100644 index 0000000000..1bf674ac12 --- /dev/null +++ b/build/gyp_includes/internal/release_defaults.gypi @@ -0,0 +1,18 @@ +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'msvs_settings': { + 'VCCLCompilerTool': { + 'StringPooling': 'true', + }, + 'VCLinkerTool': { + # No incremental linking. + 'LinkIncremental': '1', + # Eliminate Unreferenced Data (/OPT:REF). + 'OptimizeReferences': '2', + # Folding on (/OPT:ICF). + 'EnableCOMDATFolding': '2', + }, + }, +} diff --git a/build/gyp_includes/internal/release_impl.gypi b/build/gyp_includes/internal/release_impl.gypi new file mode 100644 index 0000000000..5ac0e09d1e --- /dev/null +++ b/build/gyp_includes/internal/release_impl.gypi @@ -0,0 +1,17 @@ +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'includes': ['release_defaults.gypi'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'OmitFramePointers': 'false', + # The above is not sufficient (http://crbug.com/106711): it + # simply eliminates an explicit "/Oy", but both /O2 and /Ox + # perform FPO regardless, so we must explicitly disable. + # We still want the false setting above to avoid having + # "/Oy /Oy-" and warnings about overriding. + 'AdditionalOptions': ['/Oy-'], + }, + }, +} diff --git a/build/gyp_includes/internal/release_impl_official.gypi b/build/gyp_includes/internal/release_impl_official.gypi new file mode 100644 index 0000000000..d084ae32cf --- /dev/null +++ b/build/gyp_includes/internal/release_impl_official.gypi @@ -0,0 +1,43 @@ +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'includes': ['release_defaults.gypi'], + 'defines': ['OFFICIAL_BUILD'], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'InlineFunctionExpansion': '2', + 'EnableIntrinsicFunctions': 'true', + 'EnableFiberSafeOptimizations': 'true', + 'OmitFramePointers': 'false', + # The above is not sufficient (http://crbug.com/106711): it + # simply eliminates an explicit "/Oy", but both /O2 and /Ox + # perform FPO regardless, so we must explicitly disable. + # We still want the false setting above to avoid having + # "/Oy /Oy-" and warnings about overriding. + 'AdditionalOptions': ['/Oy-'], + }, + 'VCLibrarianTool': { + 'AdditionalOptions': [ + '/ltcg', + '/expectedoutputsize:120000000' + ], + }, + 'VCLinkerTool': { + 'AdditionalOptions': [ + '/time', + # This may reduce memory fragmentation during linking. + # The expected size is 40*1024*1024, which gives us about 10M of + # headroom as of Dec 16, 2011. + '/expectedoutputsize:41943040', + ], + 'LinkTimeCodeGeneration': '1', + # The /PROFILE flag causes the linker to add a "FIXUP" debug stream to + # the generated PDB. According to MSDN documentation, this flag is only + # available (or perhaps supported) in the Enterprise (team development) + # version of Visual Studio. If this blocks your official build, simply + # comment out this line, then re-run "gclient runhooks". + 'Profile': 'true', + }, + }, +} diff --git a/build/gyp_includes/release.gypi b/build/gyp_includes/release.gypi new file mode 100644 index 0000000000..7595ef5a29 --- /dev/null +++ b/build/gyp_includes/release.gypi @@ -0,0 +1,17 @@ +{ + 'conditions': [ + # Handle build types. + ['buildtype=="Dev"', { + 'includes': ['internal/release_impl.gypi'], + }], + ['buildtype=="Official"', { + 'includes': ['internal/release_impl_official.gypi'], + }], + # TODO(bradnelson): may also need: + # checksenabled + # coverage + # dom_stats + # pgo_instrument + # pgo_optimize + ], +} diff --git a/build/mach_initialize.py b/build/mach_initialize.py new file mode 100644 index 0000000000..3914314a2b --- /dev/null +++ b/build/mach_initialize.py @@ -0,0 +1,607 @@ +# 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/. + +import math +import os +import shutil +import sys +from pathlib import Path + +if sys.version_info[0] < 3: + import __builtin__ as builtins + + class MetaPathFinder(object): + pass + +else: + from importlib.abc import MetaPathFinder + +from types import ModuleType + +STATE_DIR_FIRST_RUN = """ +Mach and the build system store shared state in a common directory +on the filesystem. The following directory will be created: + + {} + +If you would like to use a different directory, rename or move it to your +desired location, and set the MOZBUILD_STATE_PATH environment variable +accordingly. +""".strip() + + +CATEGORIES = { + "build": { + "short": "Build Commands", + "long": "Interact with the build system", + "priority": 80, + }, + "post-build": { + "short": "Post-build Commands", + "long": "Common actions performed after completing a build.", + "priority": 70, + }, + "testing": { + "short": "Testing", + "long": "Run tests.", + "priority": 60, + }, + "ci": { + "short": "CI", + "long": "Taskcluster commands", + "priority": 59, + }, + "devenv": { + "short": "Development Environment", + "long": "Set up and configure your development environment.", + "priority": 50, + }, + "build-dev": { + "short": "Low-level Build System Interaction", + "long": "Interact with specific parts of the build system.", + "priority": 20, + }, + "misc": { + "short": "Potpourri", + "long": "Potent potables and assorted snacks.", + "priority": 10, + }, + "release": { + "short": "Release automation", + "long": "Commands for used in release automation.", + "priority": 5, + }, + "disabled": { + "short": "Disabled", + "long": "The disabled commands are hidden by default. Use -v to display them. " + "These commands are unavailable for your current context, " + 'run "mach <command>" to see why.', + "priority": 0, + }, +} + + +def _activate_python_environment(topsrcdir, get_state_dir): + from mach.site import MachSiteManager + + mach_environment = MachSiteManager.from_environment( + topsrcdir, + get_state_dir, + ) + mach_environment.activate() + + +def _maybe_activate_mozillabuild_environment(): + if sys.platform != "win32": + return + + mozillabuild = Path(os.environ.get("MOZILLABUILD", r"C:\mozilla-build")) + os.environ.setdefault("MOZILLABUILD", str(mozillabuild)) + assert mozillabuild.exists(), ( + f'MozillaBuild was not found at "{mozillabuild}".\n' + "If it's installed in a different location, please " + 'set the "MOZILLABUILD" environment variable ' + "accordingly." + ) + + use_msys2 = (mozillabuild / "msys2").exists() + if use_msys2: + mozillabuild_msys_tools_path = mozillabuild / "msys2" / "usr" / "bin" + else: + mozillabuild_msys_tools_path = mozillabuild / "msys" / "bin" + + paths_to_add = [mozillabuild_msys_tools_path, mozillabuild / "bin"] + existing_paths = [Path(p) for p in os.environ.get("PATH", "").split(os.pathsep)] + for new_path in paths_to_add: + if new_path not in existing_paths: + os.environ["PATH"] += f"{os.pathsep}{new_path}" + + +def check_for_spaces(topsrcdir): + if " " in topsrcdir: + raise Exception( + f"Your checkout at path '{topsrcdir}' contains a space, which " + f"is not supported. Please move it to somewhere that does not " + f"have a space in the path before rerunning mach." + ) + + mozillabuild_dir = os.environ.get("MOZILLABUILD", "") + if sys.platform == "win32" and " " in mozillabuild_dir: + raise Exception( + f"Your installation of MozillaBuild appears to be installed on a path that " + f"contains a space ('{mozillabuild_dir}') which is not supported. Please " + f"reinstall MozillaBuild on a path without a space and restart your shell" + f"from the new installation." + ) + + +def initialize(topsrcdir, args=()): + # This directory was deleted in bug 1666345, but there may be some ignored + # files here. We can safely just delete it for the user so they don't have + # to clean the repo themselves. + deleted_dir = os.path.join(topsrcdir, "third_party", "python", "psutil") + if os.path.exists(deleted_dir): + shutil.rmtree(deleted_dir, ignore_errors=True) + + # We need the "mach" module to access the logic to parse virtualenv + # requirements. Since that depends on "packaging", we add it to the path too. + sys.path[0:0] = [ + os.path.join(topsrcdir, module) + for module in ( + os.path.join("python", "mach"), + os.path.join("third_party", "python", "packaging"), + ) + ] + + from mach.util import get_state_dir, get_virtualenv_base_dir, setenv + + state_dir = _create_state_dir() + + check_for_spaces(topsrcdir) + + # normpath state_dir to normalize msys-style slashes. + _activate_python_environment( + topsrcdir, lambda: os.path.normpath(get_state_dir(True, topsrcdir=topsrcdir)) + ) + _maybe_activate_mozillabuild_environment() + + import mach.main + from mach.command_util import ( + MACH_COMMANDS, + DetermineCommandVenvAction, + load_commands_from_spec, + ) + from mach.main import get_argument_parser + + # Set a reasonable limit to the number of open files. + # + # Some linux systems set `ulimit -n` to a very high number, which works + # well for systems that run servers, but this setting causes performance + # problems when programs close file descriptors before forking, like + # Python's `subprocess.Popen(..., close_fds=True)` (close_fds=True is the + # default in Python 3), or Rust's stdlib. In some cases, Firefox does the + # same thing when spawning processes. We would prefer to lower this limit + # to avoid such performance problems; processes spawned by `mach` will + # inherit the limit set here. + # + # The Firefox build defaults the soft limit to 1024, except for builds that + # do LTO, where the soft limit is 8192. We're going to default to the + # latter, since people do occasionally do LTO builds on their local + # machines, and requiring them to discover another magical setting after + # setting up an LTO build in the first place doesn't seem good. + # + # This code mimics the code in taskcluster/scripts/run-task. + try: + import resource + + # Keep the hard limit the same, though, allowing processes to change + # their soft limit if they need to (Firefox does, for instance). + (soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE) + # Permit people to override our default limit if necessary via + # MOZ_LIMIT_NOFILE, which is the same variable `run-task` uses. + limit = os.environ.get("MOZ_LIMIT_NOFILE") + if limit: + limit = int(limit) + else: + # If no explicit limit is given, use our default if it's less than + # the current soft limit. For instance, the default on macOS is + # 256, so we'd pick that rather than our default. + limit = min(soft, 8192) + # Now apply the limit, if it's different from the original one. + if limit != soft: + resource.setrlimit(resource.RLIMIT_NOFILE, (limit, hard)) + except ImportError: + # The resource module is UNIX only. + pass + + def resolve_repository(): + import mozversioncontrol + + try: + # This API doesn't respect the vcs binary choices from configure. + # If we ever need to use the VCS binary here, consider something + # more robust. + return mozversioncontrol.get_repository_object(path=topsrcdir) + except (mozversioncontrol.InvalidRepoPath, mozversioncontrol.MissingVCSTool): + return None + + def pre_dispatch_handler(context, handler, args): + # If --disable-tests flag was enabled in the mozconfig used to compile + # the build, tests will be disabled. Instead of trying to run + # nonexistent tests then reporting a failure, this will prevent mach + # from progressing beyond this point. + if handler.category == "testing" and not handler.ok_if_tests_disabled: + from mozbuild.base import BuildEnvironmentNotFoundException + + try: + from mozbuild.base import MozbuildObject + + # all environments should have an instance of build object. + build = MozbuildObject.from_environment() + if build is not None and not getattr( + build, "substs", {"ENABLE_TESTS": True} + ).get("ENABLE_TESTS"): + print( + "Tests have been disabled with --disable-tests.\n" + + "Remove the flag, and re-compile to enable tests." + ) + sys.exit(1) + except BuildEnvironmentNotFoundException: + # likely automation environment, so do nothing. + pass + + def post_dispatch_handler( + context, handler, instance, success, start_time, end_time, depth, args + ): + """Perform global operations after command dispatch. + + + For now, we will use this to handle build system telemetry. + """ + + # Don't finalize telemetry data if this mach command was invoked as part of + # another mach command. + if depth != 1: + return + + _finalize_telemetry_glean( + context.telemetry, handler.name == "bootstrap", success + ) + + def populate_context(key=None): + if key is None: + return + if key == "state_dir": + return state_dir + + if key == "local_state_dir": + return get_state_dir(specific_to_topsrcdir=True) + + if key == "topdir": + return topsrcdir + + if key == "pre_dispatch_handler": + return pre_dispatch_handler + + if key == "post_dispatch_handler": + return post_dispatch_handler + + if key == "repository": + return resolve_repository() + + raise AttributeError(key) + + # Note which process is top-level so that recursive mach invocations can avoid writing + # telemetry data. + if "MACH_MAIN_PID" not in os.environ: + setenv("MACH_MAIN_PID", str(os.getpid())) + + driver = mach.main.Mach(os.getcwd()) + driver.populate_context_handler = populate_context + + if not driver.settings_paths: + # default global machrc location + driver.settings_paths.append(state_dir) + # always load local repository configuration + driver.settings_paths.append(topsrcdir) + driver.load_settings() + + aliases = driver.settings.alias + + parser = get_argument_parser( + action=DetermineCommandVenvAction, + topsrcdir=topsrcdir, + ) + from argparse import Namespace + + namespace_in = Namespace() + setattr(namespace_in, "mach_command_aliases", aliases) + namespace = parser.parse_args(args, namespace_in) + + command_name = getattr(namespace, "command_name", None) + site_name = getattr(namespace, "site_name", "common") + command_site_manager = None + + # the 'clobber' command needs to run in the 'mach' venv, so we + # don't want to activate any other virtualenv for it. + if command_name != "clobber": + from mach.site import CommandSiteManager + + command_site_manager = CommandSiteManager.from_environment( + topsrcdir, + lambda: os.path.normpath(get_state_dir(True, topsrcdir=topsrcdir)), + site_name, + get_virtualenv_base_dir(topsrcdir), + ) + + command_site_manager.activate() + + for category, meta in CATEGORIES.items(): + driver.define_category(category, meta["short"], meta["long"], meta["priority"]) + + # Sparse checkouts may not have all mach_commands.py files. Ignore + # errors from missing files. Same for spidermonkey tarballs. + repo = resolve_repository() + if repo != "SOURCE": + missing_ok = ( + repo is not None and repo.sparse_checkout_present() + ) or os.path.exists(os.path.join(topsrcdir, "INSTALL")) + else: + missing_ok = () + + commands_that_need_all_modules_loaded = [ + "busted", + "help", + "mach-commands", + "mach-completion", + "mach-debug-commands", + ] + + def commands_to_load(top_level_command: str): + visited = set() + + def find_downstream_commands_recursively(command: str): + if not MACH_COMMANDS.get(command): + return + + if command in visited: + return + + visited.add(command) + + for command_dependency in MACH_COMMANDS[command].command_dependencies: + find_downstream_commands_recursively(command_dependency) + + find_downstream_commands_recursively(top_level_command) + + return list(visited) + + if ( + command_name not in MACH_COMMANDS + or command_name in commands_that_need_all_modules_loaded + ): + command_modules_to_load = MACH_COMMANDS + else: + command_names_to_load = commands_to_load(command_name) + command_modules_to_load = { + command_name: MACH_COMMANDS[command_name] + for command_name in command_names_to_load + } + + driver.command_site_manager = command_site_manager + load_commands_from_spec(command_modules_to_load, topsrcdir, missing_ok=missing_ok) + + return driver + + +def _finalize_telemetry_glean(telemetry, is_bootstrap, success): + """Submit telemetry collected by Glean. + + Finalizes some metrics (command success state and duration, system information) and + requests Glean to send the collected data. + """ + + from mach.telemetry import MACH_METRICS_PATH + from mozbuild.telemetry import ( + get_cpu_brand, + get_distro_and_version, + get_psutil_stats, + get_shell_info, + get_vscode_running, + ) + + mach_metrics = telemetry.metrics(MACH_METRICS_PATH) + mach_metrics.mach.duration.stop() + mach_metrics.mach.success.set(success) + system_metrics = mach_metrics.mach.system + cpu_brand = get_cpu_brand() + if cpu_brand: + system_metrics.cpu_brand.set(cpu_brand) + distro, version = get_distro_and_version() + system_metrics.distro.set(distro) + system_metrics.distro_version.set(version) + + vscode_terminal, ssh_connection = get_shell_info() + system_metrics.vscode_terminal.set(vscode_terminal) + system_metrics.ssh_connection.set(ssh_connection) + system_metrics.vscode_running.set(get_vscode_running()) + + has_psutil, logical_cores, physical_cores, memory_total = get_psutil_stats() + if has_psutil: + # psutil may not be available (we may not have been able to download + # a wheel or build it from source). + system_metrics.logical_cores.add(logical_cores) + if physical_cores is not None: + system_metrics.physical_cores.add(physical_cores) + if memory_total is not None: + system_metrics.memory.accumulate( + int(math.ceil(float(memory_total) / (1024 * 1024 * 1024))) + ) + telemetry.submit(is_bootstrap) + + +def _create_state_dir(): + # Global build system and mach state is stored in a central directory. By + # default, this is ~/.mozbuild. However, it can be defined via an + # environment variable. We detect first run (by lack of this directory + # existing) and notify the user that it will be created. The logic for + # creation is much simpler for the "advanced" environment variable use + # case. For default behavior, we educate users and give them an opportunity + # to react. + state_dir = os.environ.get("MOZBUILD_STATE_PATH") + if state_dir: + if not os.path.exists(state_dir): + print( + "Creating global state directory from environment variable: {}".format( + state_dir + ) + ) + else: + state_dir = os.path.expanduser("~/.mozbuild") + if not os.path.exists(state_dir): + if not os.environ.get("MOZ_AUTOMATION"): + print(STATE_DIR_FIRST_RUN.format(state_dir)) + + print("Creating default state directory: {}".format(state_dir)) + + os.makedirs(state_dir, mode=0o770, exist_ok=True) + return state_dir + + +# Hook import such that .pyc/.pyo files without a corresponding .py file in +# the source directory are essentially ignored. See further below for details +# and caveats. +# Objdirs outside the source directory are ignored because in most cases, if +# a .pyc/.pyo file exists there, a .py file will be next to it anyways. +class ImportHook(object): + def __init__(self, original_import): + self._original_import = original_import + # Assume the source directory is the parent directory of the one + # containing this file. + self._source_dir = ( + os.path.normcase( + os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + ) + + os.sep + ) + self._modules = set() + + def __call__(self, name, globals=None, locals=None, fromlist=None, level=-1): + if sys.version_info[0] >= 3 and level < 0: + level = 0 + + # name might be a relative import. Instead of figuring out what that + # resolves to, which is complex, just rely on the real import. + # Since we don't know the full module name, we can't check sys.modules, + # so we need to keep track of which modules we've already seen to avoid + # to stat() them again when they are imported multiple times. + module = self._original_import(name, globals, locals, fromlist, level) + + # Some tests replace modules in sys.modules with non-module instances. + if not isinstance(module, ModuleType): + return module + + resolved_name = module.__name__ + if resolved_name in self._modules: + return module + self._modules.add(resolved_name) + + # Builtin modules don't have a __file__ attribute. + if not getattr(module, "__file__", None): + return module + + # Note: module.__file__ is not always absolute. + path = os.path.normcase(os.path.abspath(module.__file__)) + # Note: we could avoid normcase and abspath above for non pyc/pyo + # files, but those are actually rare, so it doesn't really matter. + if not path.endswith((".pyc", ".pyo")): + return module + + # Ignore modules outside our source directory + if not path.startswith(self._source_dir): + return module + + # If there is no .py corresponding to the .pyc/.pyo module we're + # loading, remove the .pyc/.pyo file, and reload the module. + # Since we already loaded the .pyc/.pyo module, if it had side + # effects, they will have happened already, and loading the module + # with the same name, from another directory may have the same side + # effects (or different ones). We assume it's not a problem for the + # python modules under our source directory (either because it + # doesn't happen or because it doesn't matter). + if not os.path.exists(module.__file__[:-1]): + if os.path.exists(module.__file__): + os.remove(module.__file__) + del sys.modules[module.__name__] + module = self(name, globals, locals, fromlist, level) + + return module + + +# Hook import such that .pyc/.pyo files without a corresponding .py file in +# the source directory are essentially ignored. See further below for details +# and caveats. +# Objdirs outside the source directory are ignored because in most cases, if +# a .pyc/.pyo file exists there, a .py file will be next to it anyways. +class FinderHook(MetaPathFinder): + def __init__(self, klass): + # Assume the source directory is the parent directory of the one + # containing this file. + self._source_dir = ( + os.path.normcase( + os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + ) + + os.sep + ) + self.finder_class = klass + + def find_spec(self, full_name, paths=None, target=None): + spec = self.finder_class.find_spec(full_name, paths, target) + + # Some modules don't have an origin. + if spec is None or spec.origin is None: + return spec + + # Normalize the origin path. + path = os.path.normcase(os.path.abspath(spec.origin)) + # Note: we could avoid normcase and abspath above for non pyc/pyo + # files, but those are actually rare, so it doesn't really matter. + if not path.endswith((".pyc", ".pyo")): + return spec + + # Ignore modules outside our source directory + if not path.startswith(self._source_dir): + return spec + + # If there is no .py corresponding to the .pyc/.pyo module we're + # resolving, remove the .pyc/.pyo file, and try again. + if not os.path.exists(spec.origin[:-1]): + if os.path.exists(spec.origin): + os.remove(spec.origin) + spec = self.finder_class.find_spec(full_name, paths, target) + + return spec + + +# Additional hook for python >= 3.8's importlib.metadata. +class MetadataHook(FinderHook): + def find_distributions(self, *args, **kwargs): + return self.finder_class.find_distributions(*args, **kwargs) + + +def hook(finder): + has_find_spec = hasattr(finder, "find_spec") + has_find_distributions = hasattr(finder, "find_distributions") + if has_find_spec and has_find_distributions: + return MetadataHook(finder) + elif has_find_spec: + return FinderHook(finder) + return finder + + +# Install our hook. This can be deleted when the Python 3 migration is complete. +if sys.version_info[0] < 3: + builtins.__import__ = ImportHook(builtins.__import__) +else: + sys.meta_path = [hook(c) for c in sys.meta_path] diff --git a/build/macosx/catalog.py b/build/macosx/catalog.py new file mode 100644 index 0000000000..e3d937ffaf --- /dev/null +++ b/build/macosx/catalog.py @@ -0,0 +1,123 @@ +# 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/. + +import argparse +import plistlib +import ssl +import sys +from io import BytesIO +from urllib.request import urlopen +from xml.dom import minidom + +import certifi +from mozpack.macpkg import Pbzx, uncpio, unxar + + +def get_english(dict, default=None): + english = dict.get("English") + if english is None: + english = dict.get("en", default) + return english + + +def get_content_at(url): + ssl_context = ssl.create_default_context(cafile=certifi.where()) + f = urlopen(url, context=ssl_context) + return f.read() + + +def get_plist_at(url): + return plistlib.loads(get_content_at(url)) + + +def show_package_content(url, digest=None, size=None): + package = get_content_at(url) + if size is not None and len(package) != size: + print(f"Package does not match size given in catalog: {url}", file=sys.stderr) + sys.exit(1) + # Ideally we'd check the digest, but it's not md5, sha1 or sha256... + # if digest is not None and hashlib.???(package).hexdigest() != digest: + # print(f"Package does not match digest given in catalog: {url}", file=sys.stderr) + # sys.exit(1) + for name, content in unxar(BytesIO(package)): + if name == "Payload": + for path, _, __ in uncpio(Pbzx(content)): + if path: + print(path.decode("utf-8")) + + +def show_product_info(product, package_id=None): + # An alternative here would be to look at the MetadataURLs in + # product["Packages"], but going with Distributions allows to + # only do one request. + dist = get_english(product.get("Distributions")) + data = get_content_at(dist) + dom = minidom.parseString(data.decode("utf-8")) + for pkg_ref in dom.getElementsByTagName("pkg-ref"): + if pkg_ref.childNodes: + if pkg_ref.hasAttribute("packageIdentifier"): + id = pkg_ref.attributes["packageIdentifier"].value + else: + id = pkg_ref.attributes["id"].value + + if package_id and package_id != id: + continue + + for child in pkg_ref.childNodes: + if child.nodeType != minidom.Node.TEXT_NODE: + continue + for p in product["Packages"]: + if p["URL"].endswith("/" + child.data): + if package_id: + show_package_content( + p["URL"], p.get("Digest"), p.get("Size") + ) + else: + print(id, p["URL"]) + + +def show_products(products, filter=None): + for key, product in products.items(): + metadata_url = product.get("ServerMetadataURL", "") + if metadata_url and (not filter or filter in metadata_url): + metadata = get_plist_at(metadata_url) + localization = get_english(metadata.get("localization", {}), {}) + title = localization.get("title", None) + version = metadata.get("CFBundleShortVersionString", None) + print(key, title, version) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--catalog", + help="URL of the catalog", + default="https://swscan.apple.com/content/catalogs/others/index-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog", + ) + parser.add_argument( + "--filter", help="Only show entries with metadata url matching the filter" + ) + parser.add_argument( + "what", nargs="?", help="Show packages information about the given entry" + ) + args = parser.parse_args() + + data = get_plist_at(args.catalog) + products = data["Products"] + + if args.what: + if args.filter: + print( + "Cannot use --filter when showing verbose information about an entry", + file=sys.stderr, + ) + sys.exit(1) + product_id, _, package_id = args.what.partition("/") + show_product_info(products[product_id], package_id) + else: + show_products(products, args.filter) + + +if __name__ == "__main__": + main() diff --git a/build/macosx/cross-mozconfig.common b/build/macosx/cross-mozconfig.common new file mode 100644 index 0000000000..cf087ee771 --- /dev/null +++ b/build/macosx/cross-mozconfig.common @@ -0,0 +1,32 @@ +# 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/. + +. "$topsrcdir/build/mozconfig.common" + +# cctools for ld, ar, and other related tools ; dsymutil for rust. +mk_add_options "export PATH=$MOZ_FETCHES_DIR/cctools/bin:$MOZ_FETCHES_DIR/binutils/bin:$MOZ_FETCHES_DIR/clang/bin:$PATH" + +# dsymutil needs a libstdc++ more recent than what's on the system. +mk_add_options "export LD_LIBRARY_PATH=$MOZ_FETCHES_DIR/clang/lib" + +export CFLAGS="$CFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}" +export CXXFLAGS="$CXXFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}" +export MKFSHFS=$MOZ_FETCHES_DIR/hfsplus/newfs_hfs +export DMG_TOOL=$MOZ_FETCHES_DIR/dmg/dmg +export HFS_TOOL=$MOZ_FETCHES_DIR/dmg/hfsplus + +export HOST_CFLAGS="-g" +export HOST_CXXFLAGS="-g" +export HOST_LDFLAGS="-g" + +ac_add_options --target=x86_64-apple-darwin + +if [ "x$MOZ_PKG_SPECIAL" != "xasan" -a -z "$MOZ_AUTOMATION_ARTIFACT_BUILDS" ]; then + # Enable static analysis checks by default on OSX cross builds. + # Exception is ASan, where this breaks. + # The option is not valid on artifact builds, so don't add it there either. + ac_add_options --enable-clang-plugin +fi + +unset MOZ_STDCXX_COMPAT diff --git a/build/macosx/mozconfig.common b/build/macosx/mozconfig.common new file mode 100644 index 0000000000..8e20aac1dd --- /dev/null +++ b/build/macosx/mozconfig.common @@ -0,0 +1,8 @@ +if test `uname -s` = Linux; then + . $topsrcdir/build/macosx/cross-mozconfig.common +fi + +if [ -n "$TASKCLUSTER_PGO_PROFILE_USE" -a -z "$USE_ARTIFACT" ]; then + # Keep using ld64 on PGO/LTO builds because of performance regressions when using lld. + ac_add_options --enable-linker=ld64 +fi diff --git a/build/macosx/permissions/chown_revert.c b/build/macosx/permissions/chown_revert.c new file mode 100644 index 0000000000..72dc1e64d5 --- /dev/null +++ b/build/macosx/permissions/chown_revert.c @@ -0,0 +1,18 @@ +/* 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 <unistd.h> +#include <stdio.h> + +int main(int argc, char** argv) { + if (argc != 2) return 1; + + uid_t realuser = getuid(); + char uidstring[20]; + snprintf(uidstring, 19, "%i", realuser); + uidstring[19] = '\0'; + + return execl("/usr/sbin/chown", "/usr/sbin/chown", "-R", "-h", uidstring, + argv[1], (char*)0); +} diff --git a/build/macosx/permissions/chown_root.c b/build/macosx/permissions/chown_root.c new file mode 100644 index 0000000000..e2ef111c7f --- /dev/null +++ b/build/macosx/permissions/chown_root.c @@ -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 <unistd.h> + +int main(int argc, char** argv) { + if (argc != 2) return 1; + + return execl("/usr/sbin/chown", "/usr/sbin/chown", "-R", "-h", "root:admin", + argv[1], (char*)0); +} diff --git a/build/midl.py b/build/midl.py new file mode 100644 index 0000000000..0770ab8208 --- /dev/null +++ b/build/midl.py @@ -0,0 +1,223 @@ +# 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/. + +import functools +import os +import shutil +import subprocess +import sys + +import buildconfig + + +def relativize(path, base=None): + # For absolute path in Unix builds, we need relative paths because + # Windows programs run via Wine don't like these Unix absolute paths + # (they look like command line arguments). + if path.startswith("/"): + return os.path.relpath(path, base) + # For Windows absolute paths, we can just use the unmodified path. + # And if the path starts with '-', it's a command line argument. + if os.path.isabs(path) or path.startswith("-"): + return path + # Remaining case is relative paths, which may be relative to a different + # directory (os.getcwd()) than the needed `base`, so we "rebase" it. + return os.path.relpath(path, base) + + +@functools.lru_cache(maxsize=None) +def files_in(path): + return {p.lower(): os.path.join(path, p) for p in os.listdir(path)} + + +def search_path(paths, path): + for p in paths: + f = os.path.join(p, path) + if os.path.isfile(f): + return f + # try an case-insensitive match + maybe_match = files_in(p).get(path.lower()) + if maybe_match: + return maybe_match + raise RuntimeError(f"Cannot find {path}") + + +# Filter-out -std= flag from the preprocessor command, as we're not preprocessing +# C or C++, and the command would fail with the flag. +def filter_preprocessor(cmd): + prev = None + for arg in cmd: + if arg == "-Xclang": + prev = arg + continue + if not arg.startswith("-std="): + if prev: + yield prev + yield arg + prev = None + + +# Preprocess all the direct and indirect inputs of midl, and put all the +# preprocessed inputs in the given `base` directory. Returns a tuple containing +# the path of the main preprocessed input, and the modified flags to use instead +# of the flags given as argument. +def preprocess(base, input, flags): + import argparse + import re + from collections import deque + + IMPORT_RE = re.compile(r'import\s*"([^"]+)";') + + parser = argparse.ArgumentParser() + parser.add_argument("-I", action="append") + parser.add_argument("-D", action="append") + parser.add_argument("-acf") + args, remainder = parser.parse_known_args(flags) + preprocessor = ( + list(filter_preprocessor(buildconfig.substs["CXXCPP"])) + # Ideally we'd use the real midl version, but querying it adds a + # significant overhead to configure. In practice, the version number + # doesn't make a difference at the moment. + + ["-D__midl=801"] + + [f"-D{d}" for d in args.D or ()] + + [f"-I{i}" for i in args.I or ()] + ) + includes = ["."] + buildconfig.substs["INCLUDE"].split(";") + (args.I or []) + seen = set() + queue = deque([input]) + if args.acf: + queue.append(args.acf) + output = os.path.join(base, os.path.basename(input)) + while True: + try: + input = queue.popleft() + except IndexError: + break + if os.path.basename(input) in seen: + continue + seen.add(os.path.basename(input)) + input = search_path(includes, input) + # If there is a .acf file corresponding to the .idl we're processing, + # we also want to preprocess that file because midl might look for it too. + if input.lower().endswith(".idl"): + try: + acf = search_path( + [os.path.dirname(input)], os.path.basename(input)[:-4] + ".acf" + ) + if acf: + queue.append(acf) + except RuntimeError: + pass + command = preprocessor + [input] + preprocessed = os.path.join(base, os.path.basename(input)) + subprocess.run(command, stdout=open(preprocessed, "wb"), check=True) + # Read the resulting file, and search for imports, that we'll want to + # preprocess as well. + with open(preprocessed, "r") as fh: + for line in fh: + if not line.startswith("import"): + continue + m = IMPORT_RE.match(line) + if not m: + continue + imp = m.group(1) + queue.append(imp) + flags = [] + # Add -I<base> first in the flags, so that midl resolves imports to the + # preprocessed files we created. + for i in [base] + (args.I or []): + flags.extend(["-I", i]) + # Add the preprocessed acf file if one was given on the command line. + if args.acf: + flags.extend(["-acf", os.path.join(base, os.path.basename(args.acf))]) + flags.extend(remainder) + return output, flags + + +def midl(out, input, *flags): + out.avoid_writing_to_file() + midl_flags = buildconfig.substs["MIDL_FLAGS"] + base = os.path.dirname(out.name) or "." + tmpdir = None + try: + # If the build system is asking to not use the preprocessor to midl, + # we need to do the preprocessing ourselves. + if "-no_cpp" in midl_flags: + # Normally, we'd use tempfile.TemporaryDirectory, but in this specific + # case, we actually want a deterministic directory name, because it's + # recorded in the code midl generates. + tmpdir = os.path.join(base, os.path.basename(input) + ".tmp") + os.makedirs(tmpdir, exist_ok=True) + try: + input, flags = preprocess(tmpdir, input, flags) + except subprocess.CalledProcessError as e: + return e.returncode + midl = buildconfig.substs["MIDL"] + wine = buildconfig.substs.get("WINE") + if midl.lower().endswith(".exe") and wine: + command = [wine, midl] + else: + command = [midl] + command.extend(midl_flags) + command.extend([relativize(f, base) for f in flags]) + command.append("-Oicf") + command.append(relativize(input, base)) + print("Executing:", " ".join(command)) + result = subprocess.run(command, cwd=base) + return result.returncode + finally: + if tmpdir: + shutil.rmtree(tmpdir) + + +# midl outputs dlldata to a single dlldata.c file by default. This prevents running +# midl in parallel in the same directory for idl files that would generate dlldata.c +# because of race conditions updating the file. Instead, we ask midl to create +# separate files, and we merge them manually. +def merge_dlldata(out, *inputs): + inputs = [open(i) for i in inputs] + read_a_line = [True] * len(inputs) + while True: + lines = [ + f.readline() if read_a_line[n] else lines[n] for n, f in enumerate(inputs) + ] + unique_lines = set(lines) + if len(unique_lines) == 1: + # All the lines are identical + if not lines[0]: + break + out.write(lines[0]) + read_a_line = [True] * len(inputs) + elif ( + len(unique_lines) == 2 + and len([l for l in unique_lines if "#define" in l]) == 1 + ): + # Most lines are identical. When they aren't, it's typically because some + # files have an extra #define that others don't. When that happens, we + # print out the #define, and get a new input line from the files that had + # a #define on the next iteration. We expect that next line to match what + # the other files had on this iteration. + # Note: we explicitly don't support the case where there are different + # defines across different files, except when there's a different one + # for each file, in which case it's handled further below. + a = unique_lines.pop() + if "#define" in a: + out.write(a) + else: + out.write(unique_lines.pop()) + read_a_line = ["#define" in l for l in lines] + elif len(unique_lines) != len(lines): + # If for some reason, we don't get lines that are entirely different + # from each other, we have some unexpected input. + print( + "Error while merging dlldata. Last lines read: {}".format(lines), + file=sys.stderr, + ) + return 1 + else: + for line in lines: + out.write(line) + read_a_line = [True] * len(inputs) + + return 0 diff --git a/build/moz-automation.mk b/build/moz-automation.mk new file mode 100644 index 0000000000..5e165228ed --- /dev/null +++ b/build/moz-automation.mk @@ -0,0 +1,110 @@ +# +# 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/. + +ifndef ENABLE_TESTS +# We can't package tests if they aren't enabled. +MOZ_AUTOMATION_PACKAGE_TESTS = 0 +endif + +ifdef CROSS_COMPILE +# Narrow the definition of cross compilation to not include win32 builds +# on win64 and linux32 builds on linux64. +ifeq ($(HOST_OS_ARCH),$(OS_TARGET)) +ifneq (,$(filter x86%,$(TARGET_CPU))) +FUZZY_CROSS_COMPILE = +else +FUZZY_CROSS_COMPILE = 1 +endif +else +FUZZY_CROSS_COMPILE = 1 +endif +endif + +# Don't run make check when cross compiling, when doing artifact builds +# or when building instrumented builds for PGO. +ifneq (,$(USE_ARTIFACT)$(FUZZY_CROSS_COMPILE)$(MOZ_PROFILE_GENERATE)) +MOZ_AUTOMATION_CHECK := 0 +endif + +ifneq (,$(filter automation/%,$(MAKECMDGOALS))) +ifeq (4.0,$(firstword $(sort 4.0 $(MAKE_VERSION)))) +MAKEFLAGS += --output-sync=target +else +.NOTPARALLEL: +endif +endif + +ifndef JS_STANDALONE +include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk +include $(topsrcdir)/toolkit/mozapps/installer/upload-files.mk + +# Clear out DIST_FILES if it was set by upload-files.mk (for Android builds) +DIST_FILES = +endif + +# Helper variables to convert from MOZ_AUTOMATION_* variables to the +# corresponding the make target +tier_MOZ_AUTOMATION_BUILD_SYMBOLS = buildsymbols +tier_MOZ_AUTOMATION_PACKAGE = package +tier_MOZ_AUTOMATION_PACKAGE_TESTS = package-tests +tier_MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES = package-generated-sources +tier_MOZ_AUTOMATION_UPLOAD_SYMBOLS = uploadsymbols +tier_MOZ_AUTOMATION_UPLOAD = upload +tier_MOZ_AUTOMATION_CHECK = check + +# Automation build steps. Everything in MOZ_AUTOMATION_TIERS also gets used in +# TIERS for mach display. As such, the MOZ_AUTOMATION_TIERS are roughly sorted +# here in the order that they will be executed (since mach doesn't know of the +# dependencies between them). +moz_automation_symbols = \ + MOZ_AUTOMATION_PACKAGE_TESTS \ + MOZ_AUTOMATION_UPLOAD \ + $(NULL) + +ifneq (,$(COMPILE_ENVIRONMENT)$(MOZ_ARTIFACT_BUILDS)) +moz_automation_symbols += \ + MOZ_AUTOMATION_BUILD_SYMBOLS \ + MOZ_AUTOMATION_UPLOAD_SYMBOLS \ + MOZ_AUTOMATION_PACKAGE \ + MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES \ + MOZ_AUTOMATION_CHECK \ + $(NULL) +endif +MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$($(sym))),$(tier_$(sym)))) + +# Dependencies between automation build steps +automation-start/uploadsymbols: automation/buildsymbols + +automation-start/upload: automation/package +automation-start/upload: automation/package-tests +automation-start/upload: automation/buildsymbols +automation-start/upload: automation/package-generated-sources + +# Run the check tier after everything else. +automation-start/check: $(addprefix automation/,$(filter-out check,$(MOZ_AUTOMATION_TIERS))) + +automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS)) + @echo Automation steps completed. + +# Run as many tests as possible, even in case of one of them failing. +AUTOMATION_EXTRA_CMDLINE-check = --keep-going + +# The commands only run if the corresponding MOZ_AUTOMATION_* variable is +# enabled. This means, for example, if we enable MOZ_AUTOMATION_UPLOAD, then +# 'buildsymbols' will only run if MOZ_AUTOMATION_BUILD_SYMBOLS is also set. +# However, the target automation/buildsymbols will still be executed in this +# case because it is a prerequisite of automation/upload. +define automation_commands +@+$(PYTHON3) $(topsrcdir)/config/run-and-prefix.py $1 $(MAKE) $1 $(AUTOMATION_EXTRA_CMDLINE-$1) +$(call BUILDSTATUS,TIER_FINISH $1) +endef + +# The tier start message is in a separate target so make doesn't buffer it +# until the step completes with output syncing enabled. +automation-start/%: + $(if $(filter $*,$(MOZ_AUTOMATION_TIERS)),$(call BUILDSTATUS,TIER_START $*)) + +automation/%: automation-start/% + $(if $(filter $*,$(MOZ_AUTOMATION_TIERS)),$(call automation_commands,$*)) diff --git a/build/moz.build b/build/moz.build new file mode 100644 index 0000000000..a5f4144b0c --- /dev/null +++ b/build/moz.build @@ -0,0 +1,136 @@ +# -*- 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/. + +with Files("**"): + BUG_COMPONENT = ("Firefox Build System", "General") + +# This cannot be named "build" because of bug 922191. +SPHINX_TREES["buildsystem"] = "docs" + +with Files("docs/**"): + SCHEDULES.exclusive = ["docs"] + +if CONFIG["OS_ARCH"] == "WINNT": + DIRS += ["win32"] +else: + DIRS += ["unix"] + +if CONFIG["MOZ_STDCXX_COMPAT"]: + DIRS += ["unix/stdc++compat"] + +if CONFIG["RUSTC"]: + DIRS += ["rust/mozbuild"] + +CRAMTEST_MANIFESTS += [ + "tests/cram/cram.toml", +] + +DEFINES["ACCEPTED_MAR_CHANNEL_IDS"] = CONFIG["ACCEPTED_MAR_CHANNEL_IDS"] + +if CONFIG["MOZ_BUILD_APP"] == "browser": + PYTHON_UNITTEST_MANIFESTS += [ + "compare-mozconfig/python.toml", + ] + +if CONFIG["ENABLE_TESTS"] or CONFIG["MOZ_DMD"]: + FINAL_TARGET_FILES += ["/tools/rb/fix_stacks.py"] + +if CONFIG["MOZ_DMD"]: + FINAL_TARGET_FILES += ["/memory/replace/dmd/dmd.py"] + +# Put a useful .gdbinit and .gdbinit.py in $objdir/build, to be picked up +# automatically by GDB via either libxul.so-gdb.py or js-gdb.py. +OBJDIR_PP_FILES.build += [".gdbinit.py.in"] +OBJDIR_FILES.build += [".gdbinit.loader"] +OBJDIR_FILES.build += [".gdbinit"] + +# Install the clang-cl runtime library for ASAN next to the binaries we produce. +if CONFIG["MOZ_ASAN"] and CONFIG["CC_TYPE"] == "clang-cl": + FINAL_TARGET_FILES += ["%" + CONFIG["MOZ_CLANG_RT_ASAN_LIB_PATH"]] + FINAL_TARGET_FILES += [ + "%" + CONFIG["MOZ_CLANG_RT_ASAN_LIB_PATH"].replace(".dll", ".pdb") + ] + +# Install the clang runtime library for ASAN next to the binaries we produce. +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "android" and CONFIG["MOZ_ASAN"]: + FINAL_TARGET_FILES += ["%" + CONFIG["MOZ_CLANG_RT_ASAN_LIB_PATH"]] + +if CONFIG["MOZ_WIDGET_TOOLKIT"] != "android" and CONFIG["LLVM_SYMBOLIZER"]: + FINAL_TARGET_FILES += ["/" + CONFIG["LLVM_SYMBOLIZER"]] + +if CONFIG["MOZ_APP_BASENAME"]: + appini_defines = { + "TOPOBJDIR": TOPOBJDIR, + } + + for var in ( + "GRE_MILESTONE", + "MOZ_APP_VERSION", + "MOZ_APP_BASENAME", + "MOZ_APP_VENDOR", + "MOZ_APP_ID", + "MAR_CHANNEL_ID", + "MOZ_APP_REMOTINGNAME", + "MOZ_CRASHREPORTER_URL", + ): + appini_defines[var] = CONFIG[var] + + if CONFIG["MOZ_APP_DISPLAYNAME"] != CONFIG["MOZ_APP_BASENAME"]: + appini_defines["MOZ_APP_DISPLAYNAME"] = CONFIG["MOZ_APP_DISPLAYNAME"] + + if CONFIG["MOZ_BUILD_APP"] == "browser": + appini_defines["MOZ_BUILD_APP_IS_BROWSER"] = True + + if CONFIG["MOZ_APP_PROFILE"]: + appini_defines["MOZ_APP_PROFILE"] = CONFIG["MOZ_APP_PROFILE"] + + for var in ("MOZ_CRASHREPORTER", "MOZ_PROFILE_MIGRATOR", "MOZ_UPDATER"): + if CONFIG[var]: + appini_defines[var] = True + + appini_defines["MOZ_APPUPDATE_HOST"] = "aus5.mozilla.org" + if CONFIG["MOZ_APPUPDATE_HOST"]: + appini_defines["MOZ_APPUPDATE_HOST"] = CONFIG["MOZ_APPUPDATE_HOST"] + + GeneratedFile( + "application.ini", + script="../python/mozbuild/mozbuild/action/preprocessor.py", + entry_point="generate", + inputs=["application.ini.in"], + flags=[ + "-D%s=%s" % (k, "1" if v is True else v) + for k, v in sorted(appini_defines.items(), key=lambda t: t[0]) + ], + ) + + FINAL_TARGET_FILES += ["!application.ini"] + if CONFIG["MOZ_WIDGET_TOOLKIT"] != "android" and CONFIG["MOZ_UPDATER"]: + FINAL_TARGET_PP_FILES += ["update-settings.ini"] + + GeneratedFile( + "application.ini.h", script="appini_header.py", inputs=["!application.ini"] + ) + + +# Put a .lldbinit in the bin directory and the objdir, to be picked up +# automatically by LLDB when we debug executables using either of those two +# directories as the current working directory. The .lldbinit file will +# load $(topsrcdir)/.lldbinit, which is where the actual debugging commands are. +DEFINES["topsrcdir"] = TOPSRCDIR +DEFINES["topobjdir"] = TOPOBJDIR +FINAL_TARGET_PP_FILES += [".lldbinit.in"] +OBJDIR_FILES += ["!/dist/bin/.lldbinit"] + +# Put the .ycm_extra_conf.py file at the root of the objdir. It is used by +# the vim plugin YouCompleteMe. +OBJDIR_FILES += ["/.ycm_extra_conf.py"] + +if CONFIG["MOZ_VALGRIND"]: + OBJDIR_FILES._valgrind += [ + "valgrind/cross-architecture.sup", + "valgrind/i386-pc-linux-gnu.sup", + "valgrind/x86_64-pc-linux-gnu.sup", + ] diff --git a/build/moz.configure/android-ndk.configure b/build/moz.configure/android-ndk.configure new file mode 100644 index 0000000000..c19023a1ea --- /dev/null +++ b/build/moz.configure/android-ndk.configure @@ -0,0 +1,305 @@ +# -*- 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/. + + +@depends(toolchains_base_dir, "--help") +@imports(_from="os.path", _import="isdir") +@imports(_from="mozboot.android", _import="NDK_VERSION") +def default_android_ndk_root(toolchains_base_dir, _): + for ndk in ("android-ndk-%s" % NDK_VERSION, "android-ndk"): + path = os.path.join(toolchains_base_dir, ndk) + if isdir(path): + return path + + +option( + "--with-android-ndk", + nargs=1, + default=default_android_ndk_root, + help="location where the Android NDK can be found{|}", +) + +option("--with-android-toolchain", nargs=1, help="location of the Android toolchain") + +option( + "--with-android-lldb-server", nargs=1, help="location of the Android LLDB server" +) + +option( + "--with-android-googlevr-sdk", nargs=1, help="location of the Android GoogleVR SDK" +) + + +@dependable +def min_android_version(): + # Sync with android_sdk_version + return "21" + + +option( + "--with-android-version", + nargs=1, + help="android platform version{|}", + default=min_android_version, +) + + +@depends("--with-android-version", min_android_version) +@imports(_from="__builtin__", _import="ValueError") +def android_version(value, min_version): + if not value: + # Someone has passed --without-android-version. + die("--with-android-version cannot be disabled.") + + try: + version = int(value[0]) + except ValueError: + die("--with-android-version expects an integer value") + + if version < int(min_version): + die( + "--with-android-version must be at least %s (got %s)", min_version, value[0] + ) + + return version + + +@depends("--with-android-ndk") +@imports(_from="os.path", _import="isdir") +def ndk(value): + if value: + if not isdir(value[0]): + die( + "The path you specified with --with-android-ndk (%s) is not " + "a directory" % value[0] + ) + return value[0] + + die( + "You must specify --with-android-ndk=/path/to/ndk when targeting Android, " + "or try |mach bootstrap|." + ) + + +set_config("ANDROID_NDK", ndk) + + +@depends(ndk) +@checking("for android ndk version") +@imports(_from="__builtin__", _import="open") +@imports(_from="mozboot.android", _import="NDK_VERSION") +@imports(_from="mozboot.android", _import="get_ndk_version") +@imports(_from="mozboot.android", _import="GetNdkVersionError") +def ndk_version(ndk): + if not ndk: + # Building 'js/src' for non-Android. + return + + try: + major, minor, human = get_ndk_version(ndk) + except GetNdkVersionError as e: + die(str(e)) + + if NDK_VERSION != human: + die( + "The only supported version of the NDK is %s (have %s)\n" + "Please run |mach bootstrap| " + "to install the correct NDK." % (NDK_VERSION, human) + ) + return namespace( + major=major, + minor=minor, + ) + + +set_config("ANDROID_NDK_MAJOR_VERSION", ndk_version.major) +set_config("ANDROID_NDK_MINOR_VERSION", ndk_version.minor) + + +@imports(_from="os.path", _import="isdir") +@imports(_from="mozbuild.shellutil", _import="quote") +def host_dir(host, base_dir): + dir_format = "%s/%s-%s" + host_kernel = "windows" if host.kernel == "WINNT" else host.kernel.lower() + + dir = dir_format % (base_dir, host_kernel, host.cpu) + log.debug("Trying %s" % quote(dir)) + if not isdir(dir) and host.cpu == "x86_64": + dir = dir_format % (base_dir, host_kernel, "x86") + log.debug("Trying %s" % quote(dir)) + if not isdir(dir) and host.kernel == "Darwin" and host.cpu == "aarch64": + dir = dir_format % (base_dir, host_kernel, "x86_64") + log.debug("Trying %s" % quote(dir)) + if isdir(dir): + return dir + + +@depends(host, ndk, "--with-android-toolchain") +@checking("for the Android toolchain directory", lambda x: x or "not found") +def android_toolchain(host, ndk, toolchain): + if not ndk: + return + if toolchain: + return toolchain[0] + + toolchain = host_dir(host, os.path.join(ndk, "toolchains", "llvm", "prebuilt")) + if toolchain: + return toolchain + die("You have to specify --with-android-toolchain=" "/path/to/ndk/toolchain.") + + +@depends(target, android_toolchain) +@checking("for android sysroot directory") +@imports(_from="os.path", _import="isdir") +def android_sysroot(target, android_toolchain): + if target.os != "Android": + return + + search_dirs = [ + os.path.join(android_toolchain, "sysroot"), + ] + + for sysroot_dir in search_dirs: + if isdir(sysroot_dir): + return sysroot_dir + + die( + "Android sysroot directory not found in %s." + % str([sysroot_dir for sysroot_dir in search_dirs]) + ) + + +@depends(target, host, ndk, "--with-android-lldb-server") +@checking("for the Android LLDB server", lambda x: x or "not found") +@imports(_from="os", _import="listdir") +@imports(_from="os.path", _import="isdir") +@imports(_from="os.path", _import="isfile") +@imports(_from="mozbuild.shellutil", _import="quote") +def android_lldb_server(target, host, ndk, lldb): + if not ndk: + return + if lldb: + return lldb[0] + else: + clang_format = "toolchains/llvm/prebuilt/%s-%s/lib64/clang" + llvm_lib = "lib/linux" + + host_kernel = "windows" if host.kernel == "WINNT" else host.kernel.lower() + clang_path = os.path.join(ndk, clang_format % (host_kernel, host.cpu)) + if not isdir(clang_path) and host.kernel == "Darwin" and host.cpu == "aarch64": + clang_path = os.path.join(ndk, clang_format % (host_kernel, "x86_64")) + log.debug("Listing subdirectories of %s" % quote(clang_path)) + clang_subdirs = [ + x for x in listdir(clang_path) if isdir(os.path.join(clang_path, x)) + ] + log.debug("Got %r" % clang_subdirs) + if len(clang_subdirs) != 1: + die( + "Could not resolve lldb-server in %s. Please specify --with-android-lldb-server=/path/to/android/lldb-server" + % quote(clang_path) + ) + log.debug("Found version %s" % quote(clang_subdirs[0])) + + if target.cpu == "x86": + target_cpu = "i386" + else: + target_cpu = target.cpu + + full_path = os.path.join( + clang_path, clang_subdirs[0], llvm_lib, target_cpu, "lldb-server" + ) + log.debug("Trying %s" % quote(full_path)) + + if isfile(full_path): + return full_path + die("Please specify --with-android-lldb-server=/path/to/android/lldb-server") + + +set_config("ANDROID_LLDB_SERVER", android_lldb_server) + + +option( + env="STLPORT_LIBS", + nargs=1, + help="Options linker should pass for standard C++ library", +) + + +@depends("STLPORT_LIBS", ndk) +@imports(_from="os.path", _import="isfile") +def stlport_libs(value, ndk): + if value and len(value): + return value.split() + if not ndk: + return + + return ["-static-libstdc++"] + + +set_config("STLPORT_LIBS", stlport_libs) + + +@depends(android_sysroot, android_toolchain) +def extra_toolchain_flags(android_sysroot, toolchain_dir): + if not android_sysroot: + return [] + flags = [ + "--sysroot={}".format(android_sysroot), + "--gcc-toolchain={}".format(toolchain_dir), + ] + return flags + + +add_old_configure_assignment("extra_android_flags", extra_toolchain_flags) + + +@depends(extra_toolchain_flags) +def bindgen_cflags_android(toolchain_flags): + return toolchain_flags + + +@depends("--with-android-googlevr-sdk", target) +@checking("for GoogleVR SDK", lambda x: x.result) +@imports(_from="os.path", _import="exists") +@imports(_from="os.path", _import="abspath") +def googlevr_sdk(value, target): + if not value: + return namespace(result="Not specified") + path = abspath(value[0]) + if not exists(path): + die("Could not find GoogleVR SDK %s", path) + include = "%s/libraries/headers/" % path + if "arm" == target.cpu: + arch = "armeabi-v7a" + elif "aarch64" == target.cpu: + arch = "arm64-v8a" + elif "x86" == target.cpu: + arch = "x86" + else: + die("Unsupported GoogleVR cpu architecture %s" % target.cpu) + + libs = "{0}/libraries/jni/{1}/".format(path, arch) + + if not exists(libs): + die( + "Could not find GoogleVR NDK at %s. Did you try running " + "'./gradlew :extractNdk' in %s?", + libs, + path, + ) + + return namespace( + result=path, + include=include, + libs=libs, + enabled=True, + ) + + +set_define("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled) +set_config("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled) +set_config("MOZ_ANDROID_GOOGLE_VR_INCLUDE", googlevr_sdk.include) +set_config("MOZ_ANDROID_GOOGLE_VR_LIBS", googlevr_sdk.libs) diff --git a/build/moz.configure/android-sdk.configure b/build/moz.configure/android-sdk.configure new file mode 100644 index 0000000000..7607ed2135 --- /dev/null +++ b/build/moz.configure/android-sdk.configure @@ -0,0 +1,157 @@ +# -*- 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/. + +# Ensure Android SDK and build-tools versions depending on mobile target. + + +@depends(host, toolchains_base_dir, "--help") +@imports(_from="os.path", _import="isdir") +def default_android_sdk_root(host, toolchains_base_dir, _): + sdk_basename = { + "Darwin": "android-sdk-macosx", + "Linux": "android-sdk-linux", + "WINNT": "android-sdk-windows", + }.get(host.kernel, "android-sdk") + for sdk_basename in (sdk_basename, "android-sdk"): + path = os.path.join(toolchains_base_dir, sdk_basename) + if isdir(path): + return path + + +option( + "--with-android-sdk", + nargs=1, + default=default_android_sdk_root, + help="location where the Android SDK can be found (like ~/.mozbuild/android-sdk-linux){|}", +) + + +@depends("--with-android-sdk") +@imports(_from="os.path", _import="isdir") +def android_sdk_root(value): + if value: + if not isdir(value[0]): + die( + "The path you specified with --with-android-sdk (%s) is not " + "a directory" % value[0] + ) + return value[0] + + die( + "You must specify --with-android-sdk=/path/to/sdk when targeting Android, " + "or try |mach bootstrap|." + ) + + +@dependable +def android_sdk_version(): + # We support Android SDK version 21 and up by default. + # See the --enable-android-min-sdk option below. + # + # Warning: Before increasing the with-android-min-sdk value, please note several places in + # and out of tree have to be changed. Otherwise, places like Treeherder or archive.mozilla.org + # will advertise a bad API level. This may confuse people. As an example, please look at + # bug 1384482. + # If you think you can't handle the whole set of changes, please reach out to the Release + # Engineering team. + return namespace( + build_tools_version="34.0.0", + target_sdk_version="34", + min_sdk_version="21", + ) + + +option( + "--with-android-min-sdk", + default=android_sdk_version.min_sdk_version, + help="Impose a minimum Firefox for Android SDK version", +) + + +@depends("--with-android-min-sdk", android_sdk_version.target_sdk_version) +@imports(_from="__builtin__", _import="ValueError") +def valid_android_min_sdk(min_sdk_version, target_sdk_version): + if not min_sdk_version: + die("--without-android-min-sdk is not a valid option") + try: + if int(min_sdk_version[0]) > int(target_sdk_version): + die( + "--with-android-min-sdk is expected to be less than {}".format( + target_sdk_version + ) + ) + except ValueError: + die("--with-android-min-sdk takes a numerical value") + return min_sdk_version[0] + + +set_config("MOZ_ANDROID_MIN_SDK_VERSION", valid_android_min_sdk) + + +@depends(android_sdk_root, android_sdk_version) +@checking("for Android build-tools") +@imports(_from="os.path", _import="exists") +@imports(_from="os.path", _import="isdir") +def android_build_tools(sdk_root, sdk_version): + android_build_tools_base = os.path.join(sdk_root, "build-tools") + version = sdk_version.build_tools_version + if isdir(os.path.join(android_build_tools_base, version)): + tools = os.path.join(android_build_tools_base, version) + for zipalign in ("zipalign", "zipalign.exe"): + if exists(os.path.join(tools, zipalign)): + return [tools] + + die( + "You must install the Android build-tools version %s. " + "Try |mach bootstrap|. (Looked for %s/%s)" + % (version, android_build_tools_base, version) + ) + + +@depends(android_sdk_root) +@checking("for Android platform-tools") +@imports(_from="os.path", _import="exists") +@imports(_from="os.path", _import="isdir") +def android_platform_tools(sdk_root): + tools = os.path.join(sdk_root, "platform-tools") + for adb in ("adb", "adb.exe"): + if exists(os.path.join(tools, adb)): + return [tools] + + die( + "You must install the Android platform-tools. Try |mach bootstrap|. (Looked for %s)" + % tools + ) + + +@depends(android_sdk_root) +def android_emulator_path(sdk_root): + return [os.path.join(sdk_root, "emulator")] + + +@template +def check_android_tools(tool, tool_dir): + check = check_prog( + tool.upper(), (tool, tool + ".exe"), paths=tool_dir, allow_missing=True + ) + + @depends(check) + def require_tool(result): + if result is None: + die("The program %s was not found. Try |mach bootstrap|" % tool) + return result + + return require_tool + + +check_android_tools("zipalign", android_build_tools) +check_android_tools("adb", android_platform_tools) +check_android_tools("emulator", android_emulator_path) + +set_config("ANDROID_SDK_ROOT", android_sdk_root) + +set_config("ANDROID_BUILD_TOOLS_VERSION", android_sdk_version.build_tools_version) +set_config("ANDROID_TARGET_SDK", android_sdk_version.target_sdk_version) diff --git a/build/moz.configure/arm.configure b/build/moz.configure/arm.configure new file mode 100644 index 0000000000..5d26f4d732 --- /dev/null +++ b/build/moz.configure/arm.configure @@ -0,0 +1,305 @@ +# -*- 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/. + + +@depends(target.os) +def arm_option_defaults(os): + if os == "Android": + arch = "armv7-a" + thumb = "yes" + fpu = "neon" + float_abi = "softfp" + else: + arch = thumb = fpu = float_abi = "toolchain-default" + return namespace( + arch=arch, + thumb=thumb, + fpu=fpu, + float_abi=float_abi, + ) + + +# Note: '{...|}' in the help of all options with a non-constant default to +# make the lint happy. The first arm is always going to be used, because a +# default is always returned. The lint is fooled by this file being +# conditional. If it weren't conditional, the lint wouldn't ask for '{|}' to +# be there. +option( + "--with-arch", + nargs=1, + default=arm_option_defaults.arch, + help="{Use specific CPU features (-march=type). Resets thumb, fpu, " + "float-abi, etc. defaults when set|}", +) + + +@depends("--with-arch") +def arch_option(value): + if value: + if value[0] != "toolchain-default": + return ["-march={}".format(value[0])] + return [] + + +option( + "--with-thumb", + choices=("yes", "no", "toolchain-default"), + default=arm_option_defaults.thumb, + nargs="?", + help="{Use Thumb instruction set (-mthumb)|}", +) + + +def normalize_arm_option(value): + if value: + if len(value): + if value[0] == "yes": + return True + elif value[0] == "no": + return False + else: + return value[0] + return True + return False + + +@depends("--with-thumb") +def thumb_option(value): + value = normalize_arm_option(value) + if value is True: + return ["-mthumb"] + if value is False: + return ["-marm"] + return [] + + +option( + "--with-thumb-interwork", + choices=("yes", "no", "toolchain-default"), + default="toolchain-default", + nargs="?", + help="Use Thumb/ARM instuctions interwork (-mthumb-interwork)", +) + + +@depends("--with-thumb-interwork") +def thumb_interwork_option(value): + value = normalize_arm_option(value) + if value is True: + return ["-mthumb-interwork"] + if value is False: + return ["-mno-thumb-interwork"] + return [] + + +option( + "--with-fpu", + nargs=1, + default=arm_option_defaults.fpu, + help="{Use specific FPU type (-mfpu=type)|}", +) + + +@depends("--with-fpu") +def fpu_option(value): + if value: + if value[0] != "toolchain-default": + return ["-mfpu={}".format(value[0])] + return [] + + +option( + "--with-float-abi", + nargs=1, + default=arm_option_defaults.float_abi, + help="{Use specific arm float ABI (-mfloat-abi=type)|}", +) + + +@depends("--with-float-abi") +def float_abi_option(value): + if value: + if value[0] != "toolchain-default": + return ["-mfloat-abi={}".format(value[0])] + return [] + + +option( + "--with-soft-float", + choices=("yes", "no", "toolchain-default"), + default="toolchain-default", + nargs="?", + help="Use soft float library (-msoft-float)", +) + + +@depends("--with-soft-float") +def soft_float_option(value): + value = normalize_arm_option(value) + if value is True: + return ["-msoft-float"] + if value is False: + return ["-mno-soft-float"] + return [] + + +check_and_add_flag( + "-mno-unaligned-access", when=depends(target.os)(lambda os: os == "Android") +) + + +# The set of flags that clang understands +@depends( + arch_option, + thumb_option, + fpu_option, + float_abi_option, + soft_float_option, +) +def all_clang_arm_flags(arch, thumb, fpu, float_abi, soft_float): + return arch + thumb + fpu + float_abi + soft_float + + +# All the flags the compiler understands. When the compiler is clang, this +# still includes unsupported flags, but we live it to configure to fail +# during a compiler check. These checks aren't available for clang as used +# by bindgen, so we keep the separate set of flags for clang for bindgen. +@depends(all_clang_arm_flags, thumb_interwork_option) +def all_arm_flags(flags, interwork): + return flags + interwork + + +add_old_configure_assignment("_ARM_FLAGS", all_arm_flags) +add_old_configure_assignment("_THUMB_FLAGS", thumb_option) + + +@depends(configure_cache, c_compiler, all_arm_flags) +@checking("ARM version support in compiler", lambda x: x.arm_arch) +@imports(_from="textwrap", _import="dedent") +def arm_target(configure_cache, compiler, all_arm_flags): + # We're going to preprocess the following source to figure out some details + # about the arm target options we have enabled. + source = dedent( + """\ + %ARM_ARCH __ARM_ARCH + #if __thumb2__ + %THUMB2 yes + #else + %THUMB2 no + #endif + // Confusingly, the __SOFTFP__ preprocessor variable indicates the + // "softfloat" ABI, not the "softfp" ABI. + #if __SOFTFP__ + %FLOAT_ABI soft + #elif __ARM_PCS_VFP + %FLOAT_ABI hard + #else + %FLOAT_ABI softfp + #endif + // There is more subtlety to it than this preprocessor test, but MOZ_FPU doesn't + // need to be too fine-grained. + #if __ARM_NEON + %FPU neon + #elif __ARM_VFPV2__ || __ARM_FP == 12 + %FPU vfpv2 + #elif __ARM_VFPV3__ + %FPU vfpv3 + #elif __ARM_VFPV4__ || __ARM_FP == 14 + %FPU vfpv4 + #elif __ARM_FPV5__ + %FPU fp-armv8 + #endif + """ + ) + result = try_invoke_compiler( + configure_cache, + [compiler.compiler] + compiler.flags, + compiler.language, + source, + ["-E"] + all_arm_flags, + wrapper=compiler.wrapper, + ) + # Metadata emitted by preprocessors such as GCC with LANG=ja_JP.utf-8 may + # have non-ASCII characters. Treat the output as bytearray. + data = {"fpu": None} # fpu may not get a value from the preprocessor. + for line in result.splitlines(): + if line.startswith("%"): + k, _, v = line.partition(" ") + k = k.lstrip("%").lower() + if k == "arm_arch": + data[k] = int(v) + else: + data[k] = { + "yes": True, + "no": False, + }.get(v, v) + log.debug("%s = %s", k, data[k]) + + return namespace(**data) + + +@depends(arm_target.arm_arch, when=depends(target.os)(lambda os: os == "Android")) +def armv7(arch): + if arch < 7: + die("Android/armv6 and earlier are not supported") + + +set_config("MOZ_THUMB2", True, when=arm_target.thumb2) +set_define("MOZ_THUMB2", True, when=arm_target.thumb2) + + +have_arm_simd = c_compiler.try_compile( + body='asm("uqadd8 r1, r1, r2");', check_msg="for ARM SIMD support in compiler" +) + +set_config("HAVE_ARM_SIMD", have_arm_simd) +set_define("HAVE_ARM_SIMD", have_arm_simd) + +have_arm_neon = c_compiler.try_compile( + body='asm(".fpu neon\\n vadd.i8 d0, d0, d0");', + check_msg="for ARM NEON support in compiler", +) + +set_config("HAVE_ARM_NEON", have_arm_neon) +set_define("HAVE_ARM_NEON", have_arm_neon) + + +# We don't need to build NEON support if we're targetting a non-NEON device. +# This matches media/webrtc/trunk/webrtc/build/common.gypi. +@depends(arm_target.arm_arch, when=have_arm_neon) +def build_arm_neon(arm_arch): + return arm_arch >= 7 + + +set_config("BUILD_ARM_NEON", True, when=build_arm_neon) +set_define("BUILD_ARM_NEON", True, when=build_arm_neon) + + +set_config("ARM_ARCH", depends(arm_target.arm_arch)(lambda x: str(x))) +set_config("MOZ_FPU", arm_target.fpu) + + +@depends(arm_target) +def neon_flags(arm_target): + # Building with -mfpu=neon requires either the "softfp" or the + # "hardfp" ABI. Depending on the compiler's default target, and the + # CFLAGS, the default ABI might be neither, in which case it is the + # "softfloat" ABI. + # The "softfloat" ABI is binary-compatible with the "softfp" ABI, so + # we can safely mix code built with both ABIs. So, if we detect + # that compiling uses the "softfloat" ABI, force the use of the + # "softfp" ABI instead. + flags = ["-mfpu=neon"] + if arm_target.float_abi == "soft": + flags.append("-mfloat-abi=softfp") + if arm_target.arm_arch < 7: + # clang needs to be forced to at least armv7 for -mfpu=neon to do + # something. + flags.append("-march=armv7-a") + return tuple(flags) + + +set_config("NEON_FLAGS", neon_flags) diff --git a/build/moz.configure/bindgen.configure b/build/moz.configure/bindgen.configure new file mode 100644 index 0000000000..72f4d4173b --- /dev/null +++ b/build/moz.configure/bindgen.configure @@ -0,0 +1,377 @@ +# -*- 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/. + + +option(env="CBINDGEN", nargs=1, help="Path to cbindgen") + + +@imports(_from="textwrap", _import="dedent") +def check_cbindgen_version(cbindgen, fatal=False): + log.debug("trying cbindgen: %s" % cbindgen) + + cbindgen_min_version = Version("0.26.0") + + # cbindgen x.y.z + version = Version(check_cmd_output(cbindgen, "--version").strip().split(" ")[1]) + log.debug("%s has version %s" % (cbindgen, version)) + if version >= cbindgen_min_version: + return True + if not fatal: + return False + + die( + dedent( + """\ + cbindgen version {} is too old. At least version {} is required. + + Please update using 'cargo install cbindgen --force' or running + './mach bootstrap', after removing the existing executable located at + {}. + """.format( + version, cbindgen_min_version, cbindgen + ) + ) + ) + + +# Similar behavior to what check_prog does. +has_cbindgen_input = depends("CBINDGEN")(lambda x: x) +bootstrap_cbindgen = depends(has_cbindgen_input)(lambda i: not i) + + +@depends_if( + "CBINDGEN", + bootstrap_search_path("cbindgen", when=bootstrap_cbindgen), + rust_search_path, +) +@checking("for cbindgen") +@imports(_from="textwrap", _import="dedent") +def cbindgen(cbindgen_override, bootstrap_search_path, rust_search_path): + if cbindgen_override: + check_cbindgen_version(cbindgen_override[0], fatal=True) + return cbindgen_override[0] + + candidates = [] + for path in bootstrap_search_path + rust_search_path: + candidate = find_program("cbindgen", [path]) + if not candidate: + continue + if check_cbindgen_version(candidate): + return candidate + candidates.append(candidate) + + if not candidates: + raise FatalCheckError( + dedent( + """\ + Cannot find cbindgen. Please run `mach bootstrap`, + `cargo install cbindgen`, ensure that `cbindgen` is on your PATH, + or point at an executable with `CBINDGEN`. + """ + ) + ) + check_cbindgen_version(candidates[0], fatal=True) + + +set_config("CBINDGEN", cbindgen) + +# Bindgen can use rustfmt to format Rust file, but it's not required. +option(env="RUSTFMT", nargs=1, help="Path to the rustfmt program") + +rustfmt = check_prog( + "RUSTFMT", + ["rustfmt"], + paths=rust_search_path, + input="RUSTFMT", + allow_missing=True, +) + + +option( + "--with-libclang-path", + nargs=1, + help="Absolute path to a directory containing Clang/LLVM libraries for bindgen (version 3.9.x or above)", +) +option( + "--with-clang-path", + nargs=1, + help="Absolute path to a Clang binary for bindgen (version 3.9.x or above)", +) + + +@depends( + "--with-clang-path", + configure_cache, + c_compiler, + cxx_compiler, + clang_search_path, + target, + target_sysroot.path, + android_version, +) +@checking("for clang for bindgen", lambda x: x.path if x else "not found") +def bindgen_clang_compiler( + clang_path, + configure_cache, + c_compiler, + cxx_compiler, + clang_search_path, + target, + sysroot_path, + android_version, +): + # When the target compiler is clang, use that, including flags. + if cxx_compiler.type == "clang": + if clang_path and clang_path[0] not in ( + c_compiler.compiler, + cxx_compiler.compiler, + ): + die( + "--with-clang-path is not valid when the target compiler is %s", + cxx_compiler.type, + ) + return namespace( + path=cxx_compiler.compiler, + flags=cxx_compiler.flags, + ) + # When the target compiler is clang-cl, use clang in the same directory, + # and figure the right flags to use. + if cxx_compiler.type == "clang-cl": + if clang_path and os.path.dirname(clang_path[0]) != os.path.dirname( + cxx_compiler.compiler + ): + die( + "--with-clang-path must point to clang in the same directory " + "as the target compiler" + ) + if not clang_path: + clang_path = [os.path.join(os.path.dirname(cxx_compiler.compiler), "clang")] + + clang_path = find_program( + clang_path[0] if clang_path else "clang++", clang_search_path + ) + if not clang_path: + return + # Hack before bug 1617793: if the compiler is clang-cl, hack the target + if cxx_compiler.type == "clang-cl": + target = split_triplet("%s-pc-windows-msvc" % target.raw_cpu) + flags = [] + if sysroot_path: + flags.extend(("--sysroot", sysroot_path)) + info = check_compiler( + configure_cache, [clang_path] + flags, "C++", target, android_version + ) + # Usually, one check_compiler pass would be enough, but when cross-compiling + # and the host and target don't use the same default C++ standard, we don't + # get the --std flag, so try again. This is the same thing as valid_compiler() + # does in toolchain.configure. + if info.flags: + flags += info.flags + info = check_compiler( + configure_cache, [clang_path] + flags, "C++", target, android_version + ) + return namespace( + path=clang_path, + flags=flags + info.flags, + ) + + +@depends("--with-libclang-path", bindgen_clang_compiler, host_library_name_info, host) +@checking("for libclang for bindgen", lambda x: x if x else "not found") +@imports("glob") +@imports(_from="os", _import="pathsep") +@imports(_from="os.path", _import="split", _as="pathsplit") +@imports("re") +def bindgen_libclang_path(libclang_path, clang, library_name_info, host): + if not clang: + if libclang_path: + die( + "--with-libclang-path is not valid without a clang compiler " + "for bindgen" + ) + return + + # Try to ensure that the clang shared library that bindgen is going + # to look for is actually present. The files that we search for + # mirror the logic in clang-sys/build.rs. + libclang_choices = [] + if host.os == "WINNT": + libclang_choices.append("libclang.dll") + libclang_choices.append( + "%sclang%s" % (library_name_info.dll.prefix, library_name_info.dll.suffix) + ) + if host.kernel == "Linux": + libclang_choices.append("libclang.so.*") + + if host.os == "OpenBSD": + libclang_choices.append("libclang.so.*.*") + + candidates = [] + if not libclang_path: + # Try to find libclang_path based on clang search dirs. + clang_search_dirs = check_cmd_output(clang.path, "-print-search-dirs") + for line in clang_search_dirs.splitlines(): + name, _, value = line.partition(": =") + if host.os == "WINNT" and name == "programs": + # On Windows, libclang.dll is in bin/ rather than lib/, + # so scan the programs search dirs. + # To make matters complicated, clang before version 9 uses `:` + # separate between paths (and `;` in newer versions) + if pathsep in value: + candidates.extend(value.split(pathsep)) + else: + for part in value.split(":"): + # Assume that if previous "candidate" was of length 1, + # it's a drive letter and the current part is the rest of + # the corresponding full path. + if candidates and len(candidates[-1]) == 1: + candidates[-1] += ":" + part + else: + candidates.append(part) + elif host.os != "WINNT" and name == "libraries": + # On other platforms, use the directories from the libraries + # search dirs that looks like $something/clang/$version. + for dir in value.split(pathsep): + dir, version = pathsplit(dir) + if re.match(r"[0-9.]+", version): + dir, name = pathsplit(dir) + if name == "clang": + candidates.append(dir) + else: + candidates.append(libclang_path[0]) + + for dir in candidates: + for pattern in libclang_choices: + log.debug('Trying "%s" in "%s"', pattern, dir) + libs = glob.glob(os.path.join(dir, pattern)) + if libs: + return libs[0] + + +@depends(bindgen_clang_compiler, bindgen_libclang_path, build_project) +def bindgen_config_paths(clang, libclang, build_project): + # XXX: we want this code to be run for both Gecko and JS, but we don't + # necessarily want to force a bindgen/Rust dependency on JS just yet. + # Actually, we don't want to force an error if we're not building the + # browser generally. We therefore whitelist the projects that require + # bindgen facilities at this point and leave it at that. + if build_project in ("browser", "mobile/android"): + if not clang: + die( + "Could not find clang to generate run bindings for C/C++. " + "Please install the necessary packages, run `mach bootstrap`, " + "or use --with-clang-path to give the location of clang." + ) + + if not libclang: + die( + "Could not find libclang to generate rust bindings for C/C++. " + "Please install the necessary packages, run `mach bootstrap`, " + "or use --with-libclang-path to give the path containing it." + ) + + if clang and libclang: + return namespace( + libclang=libclang, + libclang_path=os.path.dirname(libclang), + clang_path=clang.path, + clang_flags=clang.flags, + ) + + +@depends(bindgen_config_paths.libclang, when=bindgen_config_paths) +@checking("that libclang is new enough", lambda s: "yes" if s else "no") +@imports(_from="ctypes", _import="CDLL") +@imports(_from="textwrap", _import="dedent") +def min_libclang_version(libclang): + try: + lib = CDLL(libclang) + # We want at least 5.0. The API we test below is enough for that. + # Just accessing it should throw if not found. + fun = lib.clang_getAddressSpace + return True + except: + die( + dedent( + """\ + The libclang located at {} is too old (need at least 5.0). + + Please make sure to update it or point to a newer libclang using + --with-libclang-path. + """.format( + libclang + ) + ) + ) + return False + + +set_config("MOZ_LIBCLANG_PATH", bindgen_config_paths.libclang_path) +set_config("MOZ_CLANG_PATH", bindgen_config_paths.clang_path) + + +@depends( + target, + cxx_compiler, + bindgen_cflags_android, + bindgen_config_paths.clang_flags, + all_clang_arm_flags, +) +def basic_bindgen_cflags( + target, compiler_info, android_cflags, clang_flags, all_arm_flags +): + args = [ + "-x", + "c++", + "-fno-sized-deallocation", + "-fno-aligned-new", + "-DTRACING=1", + "-DIMPL_LIBXUL", + "-DMOZILLA_INTERNAL_API", + "-DRUST_BINDGEN", + ] + + if target.os == "Android": + args += android_cflags + + args += { + "WINNT": [ + "-DWIN32=1", + ], + }.get(target.os, []) + + if compiler_info.type == "clang-cl": + args += [ + # To enable the builtin __builtin_offsetof so that CRT wouldn't + # use reinterpret_cast in offsetof() which is not allowed inside + # static_assert(). + "-D_CRT_USE_BUILTIN_OFFSETOF", + # Enable hidden attribute (which is not supported by MSVC and + # thus not enabled by default with a MSVC-compatibile build) + # to exclude hidden symbols from the generated file. + "-DHAVE_VISIBILITY_HIDDEN_ATTRIBUTE=1", + ] + + return args + (clang_flags or []) + (all_arm_flags or []) + + +option( + env="BINDGEN_CFLAGS", + nargs=1, + help="Options bindgen should pass to the C/C++ parser", +) + + +@depends(basic_bindgen_cflags, "BINDGEN_CFLAGS") +@checking("bindgen cflags", lambda s: s if s else "no") +def bindgen_cflags(base_flags, extra_flags): + flags = base_flags + if extra_flags and len(extra_flags): + flags += extra_flags[0].split() + return " ".join(flags) + + +set_config("BINDGEN_SYSTEM_FLAGS", bindgen_cflags) diff --git a/build/moz.configure/bootstrap.configure b/build/moz.configure/bootstrap.configure new file mode 100644 index 0000000000..daaff7cdaa --- /dev/null +++ b/build/moz.configure/bootstrap.configure @@ -0,0 +1,341 @@ +# -*- 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/. + +option( + env="MOZ_FETCHES_DIR", + nargs=1, + when="MOZ_AUTOMATION", + help="Directory containing fetched artifacts", +) + + +@depends("MOZ_FETCHES_DIR", when="MOZ_AUTOMATION") +def moz_fetches_dir(value): + if value: + return value[0] + + +@depends(vcs_checkout_type, milestone.is_nightly, "MOZ_AUTOMATION") +def bootstrap_default(vcs_checkout_type, is_nightly, automation): + if automation: + return False + # We only enable if building off a VCS checkout of central. + if is_nightly and vcs_checkout_type: + return True + + +option( + "--enable-bootstrap", + nargs="*", + default=bootstrap_default, + help="{Automatically bootstrap or update some toolchains|Disable bootstrap or update of toolchains}", +) + + +@depends_if("--enable-bootstrap") +def enable_bootstrap(bootstrap): + include = set() + exclude = set() + for item in bootstrap: + if item.startswith("-"): + exclude.add(item.lstrip("-")) + else: + include.add(item) + + def match(name): + if name in exclude: + return False + if include and name in include: + return True + return not bool(include) + + return match + + +@depends(developer_options, "--enable-bootstrap", moz_fetches_dir) +def bootstrap_search_path_order(developer_options, bootstrap, moz_fetches_dir): + if moz_fetches_dir: + log.debug("Prioritizing MOZ_FETCHES_DIR in toolchain path.") + return "prepend" + + if bootstrap: + log.debug( + "Prioritizing mozbuild state dir in toolchain paths because " + "bootstrap mode is enabled." + ) + return "maybe-prepend" + + if developer_options: + log.debug( + "Prioritizing mozbuild state dir in toolchain paths because " + "you are not building in release mode." + ) + return "prepend" + + log.debug( + "Prioritizing system over mozbuild state dir in " + "toolchain paths because you are building in " + "release mode." + ) + return "append" + + +toolchains_base_dir = moz_fetches_dir | mozbuild_state_path + + +@dependable +@imports("os") +@imports(_from="os", _import="environ") +def original_path(): + return environ["PATH"].split(os.pathsep) + + +@depends(host, when="--enable-bootstrap") +@imports("os") +@imports("traceback") +@imports(_from="mozbuild.toolchains", _import="toolchain_task_definitions") +@imports(_from="__builtin__", _import="Exception") +def bootstrap_toolchain_tasks(host): + prefix = { + ("x86_64", "GNU", "Linux"): "linux64", + ("x86_64", "OSX", "Darwin"): "macosx64", + ("aarch64", "OSX", "Darwin"): "macosx64-aarch64", + ("x86_64", "WINNT", "WINNT"): "win64", + ("aarch64", "WINNT", "WINNT"): "win64-aarch64", + }.get((host.cpu, host.os, host.kernel)) + try: + tasks = toolchain_task_definitions() + except Exception as e: + message = traceback.format_exc() + log.warning(str(e)) + log.debug(message) + return None + + def task_data(t): + result = { + "index": t.optimization["index-search"], + "artifact": t.attributes["toolchain-artifact"], + } + command = t.attributes.get("toolchain-command") + if command: + result["command"] = command + return result + + # We only want to use toolchains annotated with "local-toolchain". We also limit the + # amount of data to what we use, so that trace logs can be more useful. + tasks = { + k: task_data(t) + for k, t in tasks.items() + if t.attributes.get("local-toolchain") and "index-search" in t.optimization + } + + return namespace(prefix=prefix, tasks=tasks) + + +@template +def bootstrap_path(path, **kwargs): + when = kwargs.pop("when", None) + allow_failure = kwargs.pop("allow_failure", None) + if kwargs: + configure_error( + "bootstrap_path only takes `when` and `allow_failure` as a keyword argument" + ) + + @depends( + enable_bootstrap, + toolchains_base_dir, + moz_fetches_dir, + bootstrap_toolchain_tasks, + build_environment, + dependable(path), + dependable(allow_failure), + when=when, + ) + @imports("os") + @imports("subprocess") + @imports("sys") + @imports(_from="mozbuild.util", _import="ensureParentDir") + @imports(_from="importlib", _import="import_module") + @imports(_from="shutil", _import="rmtree") + @imports(_from="__builtin__", _import="open") + @imports(_from="__builtin__", _import="Exception") + def bootstrap_path( + bootstrap, + toolchains_base_dir, + moz_fetches_dir, + tasks, + build_env, + path, + allow_failure, + ): + if not path: + return + path_parts = path.split("/") + path_prefix = "" + # Small hack until clang-tidy stops being a separate toolchain in a + # weird location. + if path_parts[0] == "clang-tools": + path_prefix = path_parts.pop(0) + + def try_bootstrap(exists): + if not tasks: + return False + prefixes = [""] + if tasks.prefix: + prefixes.insert(0, "{}-".format(tasks.prefix)) + for prefix in prefixes: + label = "toolchain-{}{}".format(prefix, path_parts[0]) + task = tasks.tasks.get(label) + if task: + break + log.debug("Trying to bootstrap %s", label) + if not task: + return False + task_index = task["index"] + log.debug("Resolved %s to %s", label, task_index[0]) + task_index = task_index[0].split(".")[-1] + artifact = task["artifact"] + # `mach artifact toolchain` doesn't support authentication for + # private artifacts. Some toolchains may provide a command that can be + # used for local production of the artifact. + command = None + if not artifact.startswith("public/"): + command = task.get("command") + if not command: + log.debug("Cannot bootstrap %s: not a public artifact", label) + return False + index_file = os.path.join(toolchains_base_dir, "indices", path_parts[0]) + try: + with open(index_file) as fh: + index = fh.read().strip() + except Exception: + # On automation, if there's an artifact in MOZ_FETCHES_DIR, we assume it's + # up-to-date. + index = task_index if moz_fetches_dir else None + if index == task_index and exists: + log.debug("%s is up-to-date", label) + return True + # Manually import with import_module so that we can gracefully disable bootstrap + # when e.g. building from a js standalone tarball, that doesn't contain the + # taskgraph code. In those cases, `mach artifact toolchain --from-build` would + # also fail. + task_id = None + if not command: + try: + IndexSearch = import_module( + "taskgraph.optimize.strategies" + ).IndexSearch + except Exception: + log.debug("Cannot bootstrap %s: missing taskgraph module", label) + return False + task_id = IndexSearch().should_replace_task( + task, {}, None, task["index"] + ) + if task_id: + # If we found the task in the index, use the `mach artifact toolchain` + # fast path. + command = [ + "artifact", + "toolchain", + "--from-task", + f"{task_id}:{artifact}", + ] + elif command: + # For private local toolchains, run the associated command. + command = ( + [ + "python", + "--virtualenv", + "build", + os.path.join( + build_env.topsrcdir, + "taskcluster/scripts/misc", + command["script"], + ), + ] + + command["arguments"] + + [path_parts[0]] + ) + # Clean up anything that was bootstrapped previously before going + # forward. In other cases, that's taken care of by mach artifact toolchain. + rmtree( + os.path.join(toolchains_base_dir, path_prefix, path_parts[0]), + ignore_errors=True, + ) + else: + # Otherwise, use the slower path, which will print a better error than + # we would be able to. + command = ["artifact", "toolchain", "--from-build", label] + + log.info( + "%s bootstrapped toolchain in %s", + "Updating" if exists else "Installing", + os.path.join(toolchains_base_dir, path_prefix, path_parts[0]), + ) + os.makedirs(os.path.join(toolchains_base_dir, path_prefix), exist_ok=True) + proc = subprocess.run( + [ + sys.executable, + os.path.join(build_env.topsrcdir, "mach"), + "--log-no-times", + ] + + command, + cwd=os.path.join(toolchains_base_dir, path_prefix), + check=not allow_failure, + ) + if proc.returncode != 0 and allow_failure: + return False + ensureParentDir(index_file) + with open(index_file, "w") as fh: + fh.write(task_index) + return True + + path = os.path.join(toolchains_base_dir, path_prefix, *path_parts) + if bootstrap and bootstrap(path_parts[0]): + try: + if not try_bootstrap(os.path.exists(path)): + # If there aren't toolchain artifacts to use for this build, + # don't return a path. + return None + except Exception as e: + log.error("%s", e) + die("If you can't fix the above, retry with --disable-bootstrap.") + # We re-test whether the path exists because it may have been created by + # try_bootstrap. Automation will not have gone through the bootstrap + # process, but we want to return the path if it exists. + if os.path.exists(path): + return path + + return bootstrap_path + + +@template +def bootstrap_search_path(path, paths=original_path, **kwargs): + @depends( + enable_bootstrap, + dependable(path), + bootstrap_path(path, **kwargs), + bootstrap_search_path_order, + paths, + original_path, + ) + def bootstrap_search_path( + bootstrap, path, bootstrap_path, order, paths, original_path + ): + if paths is None: + paths = original_path + if not bootstrap_path: + return paths + if order == "maybe-prepend": + if bootstrap(path.split("/")[0]): + order = "prepend" + else: + order = "append" + if order == "prepend": + return [bootstrap_path] + paths + return paths + [bootstrap_path] + + return bootstrap_search_path diff --git a/build/moz.configure/checks.configure b/build/moz.configure/checks.configure new file mode 100644 index 0000000000..73e8b0a886 --- /dev/null +++ b/build/moz.configure/checks.configure @@ -0,0 +1,206 @@ +# -*- 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/. + +# Templates implementing some generic checks. +# ============================================================== + +# Declare some exceptions. This is cumbersome, but since we shouldn't need a +# lot of them, let's stack them all here. When adding a new one, put it in the +# _declare_exceptions template, and add it to the return statement. Then +# destructure in the assignment below the function declaration. + + +@template +@imports(_from="__builtin__", _import="Exception") +def _declare_exceptions(): + class FatalCheckError(Exception): + """An exception to throw from a function decorated with @checking. + It will result in calling die() with the given message. + Debugging messages emitted from the decorated function will also be + printed out.""" + + return (FatalCheckError,) + + +(FatalCheckError,) = _declare_exceptions() + +del _declare_exceptions + +# Helper to display "checking" messages +# @checking('for foo') +# def foo(): +# return 'foo' +# is equivalent to: +# def foo(): +# log.info('checking for foo... ') +# ret = foo +# log.info(ret) +# return ret +# This can be combined with e.g. @depends: +# @depends(some_option) +# @checking('for something') +# def check(value): +# ... +# An optional callback can be given, that will be used to format the returned +# value when displaying it. + + +@template +def checking(what, callback=None): + def decorator(func): + def wrapped(*args, **kwargs): + log.info("checking %s... ", what) + with log.queue_debug(): + error, ret = None, None + try: + ret = func(*args, **kwargs) + except FatalCheckError as e: + error = str(e) + display_ret = callback(ret) if callback else ret + if display_ret is True: + log.info("yes") + elif display_ret is False or display_ret is None: + log.info("no") + else: + log.info(display_ret) + if error is not None: + die(error) + return ret + + return wrapped + + return decorator + + +# Template to check for programs in $PATH. +# - `var` is the name of the variable that will be set with `set_config` when +# the program is found. +# - `progs` is a list (or tuple) of program names that will be searched for. +# It can also be a reference to a @depends function that returns such a +# list. If the list is empty and there is no input, the check is skipped. +# - `what` is a human readable description of what is being looked for. It +# defaults to the lowercase version of `var`. +# - `input` is a string reference to an existing option or a reference to a +# @depends function resolving to explicit input for the program check. +# The default is to create an option for the environment variable `var`. +# This argument allows to use a different kind of option (possibly using a +# configure flag), or doing some pre-processing with a @depends function. +# - `allow_missing` indicates whether not finding the program is an error. +# - `paths` is a list of paths or @depends function returning a list of paths +# that will cause the given path(s) to be searched rather than $PATH. Input +# paths may either be individual paths or delimited by os.pathsep, to allow +# passing $PATH (for example) as an element. +# - `bootstrap` is a path relative to the bootstrap root path (e.g ~/.mozbuild) +# where to find the program if it's bootstrapped. +# - `validate` is a callback function that takes a path and returns True if +# the program at that location is appropriate or not, or False if not. +# when the callback returns False, check_prog ignores the program and goes +# on to the next from the `progs` list. +# +# - `bootstrap_search_path` is not an argument that users of the template are +# supposed to pass. See the override of check_prog in top-level moz.configure. +# +# The simplest form is: +# check_prog('PROG', ('a', 'b')) +# This will look for 'a' or 'b' in $PATH, and set_config PROG to the one +# it can find. If PROG is already set from the environment or command line, +# use that value instead. +@template +@imports(_from="mozbuild.shellutil", _import="quote") +def check_prog( + var, + progs, + what=None, + input=None, + allow_missing=False, + paths=None, + allow_spaces=False, + bootstrap=None, + when=None, + validate=None, + bootstrap_search_path=None, +): + if input is not None: + # Wrap input with type checking and normalization. + @depends(input, when=when) + def input(value): + if not value: + return + if isinstance(value, str): + return (value,) + if isinstance(value, (tuple, list)) and len(value) == 1: + return value + configure_error( + "input must resolve to a tuple or a list with a " + "single element, or a string" + ) + + else: + option( + env=var, + nargs=1, + when=when, + help="Path to %s" % (what or "the %s program" % var.lower()), + ) + input = var + what = what or var.lower() + + # Trick to make a @depends function out of an immediate value. + progs = dependable(progs) + paths = dependable(paths) + allow_missing = dependable(allow_missing) + + if bootstrap: + if input is var: + # A when is needed when depending on an option, so normalize + # to a function that can used without. + has_input = depends(input, when=when)(lambda x: x) + else: + has_input = input + # We don't want to bootstrap when an explicit value was given as input. + if when: + bootstrap_when = depends(when, has_input)(lambda w, i: w and not i) + else: + bootstrap_when = depends(has_input)(lambda i: not i) + paths = bootstrap_search_path(bootstrap, paths, when=bootstrap_when) + + # Avoid displaying the "Checking for" message when the inputs are such + # that we don't actually want anything to be checked. It is a bit + # convoluted because of how `when` works. + # We first wrap all the inputs except allow_missing (which doesn't count + # for whether to display the "Checking for" message). + @depends_if(input, progs, paths, when=when) + def inputs(input, progs, paths): + if progs is None: + progs = () + + if not isinstance(progs, (tuple, list)): + configure_error("progs must resolve to a list or tuple!") + + return namespace(value=input, progs=progs, paths=paths) + + @depends(inputs, allow_missing, when=inputs) + @checking("for %s" % what, lambda x: quote(x) if x else "not found") + def check(inputs, allow_missing): + value = inputs.value + progs = inputs.progs + paths = inputs.paths + + for prog in value or progs: + log.debug("%s: Looking for %s", var.lower(), quote(prog)) + result = find_program(prog, paths, allow_spaces) + if validate and result and not validate(result): + log.debug("%s: %s found but didn't work", var.lower(), quote(result)) + continue + if result: + return result + + if not allow_missing or value: + raise FatalCheckError("Cannot find %s" % what) + + set_config(var, check) + + return check diff --git a/build/moz.configure/compile-checks.configure b/build/moz.configure/compile-checks.configure new file mode 100644 index 0000000000..a639a012f1 --- /dev/null +++ b/build/moz.configure/compile-checks.configure @@ -0,0 +1,445 @@ +# -*- 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/. + + +# Generates a test program and attempts to compile it. In case of failure, the +# resulting check will return None. If the test program succeeds, it will return +# the output of the test program. +# - `includes` are the includes (as file names) that will appear at the top of +# the generated test program. +# - `body` is the code that will appear in the main function of the generated +# test program. `return 0;` is appended to the function body automatically. +# - `language` is the language selection, so that the appropriate compiler is +# used. +# - `flags` are the flags to be passed to the compiler, in addition to `-c`. +# - `check_msg` is the message to be printed to accompany compiling the test +# program. +@template +def try_compile( + includes=None, + body="", + language="C++", + flags=None, + check_msg=None, + when=None, + onerror=lambda: None, +): + compiler = { + "C": c_compiler, + "C++": cxx_compiler, + }[language] + + return compiler.try_compile( + includes, body, flags, check_msg, when=when, onerror=onerror + ) + + +# Generates a test program and attempts to link it. In case of failure, the +# resulting check will return None. If the link succeeds, it will return +# True +# - `includes` are the includes (as file names) that will appear at the top of +# the generated test program. +# - `body` is the code that will appear in the main function of the generated +# test program. `return 0;` is appended to the function body automatically. +# - `language` is the language selection, so that the appropriate compiler is +# used. +# - `flags` are the flags to be passed to the compiler. +# - `check_msg` is the message to be printed to accompany compiling the test +# program. +@template +def try_link( + includes=None, + body="", + language="C++", + flags=None, + check_msg=None, + when=None, + onerror=lambda: None, +): + compiler = { + "C": c_compiler, + "C++": cxx_compiler, + }[language] + + return compiler.try_link( + linker_ldflags, + includes, + body, + flags, + check_msg, + when=when, + onerror=onerror, + ) + + +# Checks for the presence of the given header on the target system by compiling +# a test program including that header. The return value of the template is a +# check function returning True if the header is present, and None if it is not. +# The value of this check function is also used to set a variable (with set_define) +# corresponding to the checked header. For instance, HAVE_MALLOC_H will be set in +# defines if check_header if called with 'malloc.h' as input and malloc.h is +# present on the target. +# - `header` is the header, as a file name, to check for. +# - `language` is the language selection, so that the appropriate compiler is +# used. +# - `flags` are the flags to be passed to the compiler, in addition to `-c`. +# - `includes` are additional includes, as file names, to appear before the +# header checked for. +# - `when` is a depends function that if present will make performing the check +# conditional on the value of that function. +@template +def check_header( + header, language="C++", flags=None, includes=None, when=None, onerror=lambda: None +): + if when is None: + when = always + + if includes: + includes = includes[:] + else: + includes = [] + includes.append(header) + + have_header = try_compile( + includes=includes, + language=language, + flags=flags, + check_msg="for %s" % header, + when=when, + onerror=onerror, + ) + header_var = "HAVE_%s" % ( + header.upper().replace("-", "_").replace("/", "_").replace(".", "_") + ) + set_define(header_var, have_header) + return have_header + + +# A convenience wrapper for check_header for checking multiple headers. +# returns an array of the resulting checks in order corresponding to the +# provided headers. +# - `headers` are the headers to be checked. +# - `kwargs` are keyword arguments passed verbatim to check_header. + + +@template +def check_headers(*headers, **kwargs): + checks = [] + for header in headers: + checks.append(check_header(header, **kwargs)) + return checks + + +@depends(linker_ldflags, target.kernel) +def check_symbol_flags(linker_ldflags, kernel): + if kernel == "WINNT": + # The build doesn't use the compiler to link things as of writing, + # but some compilation checks do. When using clang-cl, the only + # linker we really support is lld.link, but clang-cl defaults to + # link.exe (even when cross-compiling). So we force the use of + # lld.link for the linkage checks. + return ["-fuse-ld=lld"] + return linker_ldflags + + +# Checks for the presence of the given symbol on the target system by compiling +# a test program. The return value of the template is a check function +# returning True if the symbol can be found, and None if it is not. +@template +def check_symbol(symbol, language="C", flags=None, when=None, onerror=lambda: None): + if when is None: + when = always + + compiler, extern_c = { + "C": (c_compiler, ""), + "C++": (cxx_compiler, 'extern "C" '), + }[language] + + # Stolen from autoconf 2.13 ; might be irrelevant now, but it doesn't hurt to + # keep using a char return type. + comment = [ + "/* Override any gcc2 internal prototype to avoid an error. */", + "/* We use char because int might match the return type of a gcc2", + " builtin and then its argument prototype would still apply. */", + ] + + if flags: + + @depends(check_symbol_flags, dependable(flags)) + def flags(base_flags, extra_flags): + if base_flags and extra_flags: + return base_flags + list(extra_flags) + if extra_flags: + return extra_flags + return base_flags + + else: + flags = check_symbol_flags + + return compiler.try_run( + header=comment + ["%schar %s();" % (extern_c, symbol)], + body="%s();" % symbol, + flags=flags, + check_msg="for %s" % symbol, + when=when, + onerror=onerror, + ) + + +# Determine whether to add a given flag to the given lists of flags for C or +# C++ compilation. +# - `flag` is the flag to test +# - `flags_collection` is a @depends function for a namespace of lists of +# C/C++ compiler flags to add to. +# - `test_flags` is a list of flags to pass to the compiler instead of merely +# passing `flag`. This is especially useful for checking warning flags. If +# this list is empty, `flag` will be passed on its own. +# - `compiler` (optional) is the compiler to test against (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, both compilers +# are tested; the list of flags added to is dependent on the compiler tested. +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +# - `check`, when not set, skips checking whether the flag is supported and +# adds it to the list of flags unconditionally. +# - `mode`, can be "compile", "link" or "assemble" +@template +def check_and_add_flags( + flag, + flags_collection, + test_flags=(), + compiler=None, + when=None, + check=True, + mode="compile", +): + assert mode in ("compile", "link", "assemble") + + if compiler is not None: + compilers = (compiler,) + elif mode in ("link", "assemble"): + compilers = (c_compiler,) + else: + compilers = (c_compiler, cxx_compiler) + + if when is None: + when = always + + results = [] + + if test_flags: + flags = test_flags + else: + flags = [flag] + + for c in compilers: + assert c in {c_compiler, cxx_compiler, host_c_compiler, host_cxx_compiler} + if mode == "compile": + lang, list_of_flags = { + c_compiler: ("C", flags_collection.cflags), + cxx_compiler: ("C++", flags_collection.cxxflags), + host_c_compiler: ("host C", flags_collection.host_cflags), + host_cxx_compiler: ("host C++", flags_collection.host_cxxflags), + }[c] + elif mode == "assemble": + lang, list_of_flags = { + c_compiler: ("C", flags_collection.asflags), + host_c_compiler: ("host C", flags_collection.host_asflags), + }[c] + elif mode == "link": + lang, list_of_flags = { + c_compiler: ("C", flags_collection.ldflags), + cxx_compiler: ("C++", flags_collection.ldflags), + host_c_compiler: ("host C", flags_collection.host_ldflags), + host_cxx_compiler: ("host C++", flags_collection.host_ldflags), + }[c] + + result = when + + if check: + + @depends(c, dependable(flags)) + def flags(c, flags): + # Don't error out just because clang complains about other things. + if c.type in ("clang", "clang-cl"): + flags += ["-Wno-error=unused-command-line-argument"] + + return flags + + if mode == "link": + + def runner(*args, **kwargs): + if c in (c_compiler, cxx_compiler): + return c.try_link(linker_ldflags, *args, **kwargs) + else: + return c.try_link(host_linker_ldflags, *args, **kwargs) + + tool = "linker" + else: + runner = c.try_compile + tool = "compiler" + + result = runner( + flags=flags, + when=result, + check_msg="whether the %s %s supports %s" % (lang, tool, flag), + ) + + @depends(result, list_of_flags) + def maybe_add_flag(result, list_of_flags): + if result: + list_of_flags.append(flag) + + results.append(result) + + return tuple(results) + + +@dependable +def warnings_flags(): + return namespace(cflags=[], cxxflags=[], host_cflags=[], host_cxxflags=[]) + + +# Tests whether GCC or clang support the given warning flag, and if it is, +# add it to the list of warning flags for the build. +# - `warning` is the warning flag (e.g. -Wfoo) +# - `compiler` (optional) is the compiler to test against (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, both compilers +# are tested. +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +# - `check`, when not set, skips checking whether the flag is supported and +# adds it to the list of warning flags unconditionally. This is only meant +# for add_warning(). +@template +def check_and_add_warning(warning, compiler=None, when=None, check=True): + # GCC and clang will fail if given an unknown warning option like + # -Wfoobar. But later versions won't fail if given an unknown negated + # warning option like -Wno-foobar. So when we are checking for support + # of a negated warning option, we actually test the positive form, but + # add the negated form to the flags variable. + if warning.startswith("-Wno-") and not warning.startswith("-Wno-error="): + flags = ["-Werror", "-W" + warning[5:]] + elif warning.startswith("-Werror="): + flags = [warning] + else: + flags = ["-Werror", warning] + + return check_and_add_flags( + warning, warnings_flags, flags, compiler=compiler, when=when, check=check + ) + + +# Add the given warning to the list of warning flags for the build. +# - `warning` is the warning flag (e.g. -Wfoo) +# - `compiler` (optional) is the compiler to add the flag for (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, the warning flag +# is added for both compilers. +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. + + +@template +def add_warning(warning, compiler=None, when=None): + check_and_add_warning(warning, compiler, when, check=False) + + +# Like the warning checks above, but for general compilation flags. +@dependable +def compilation_flags(): + return namespace(cflags=[], cxxflags=[], host_cflags=[], host_cxxflags=[]) + + +# Tests whether GCC or clang support the given compilation flag; if the flag +# is supported, add it to the list of compilation flags for the build. +# - `flag` is the flag to test +# - `compiler` (optional) is the compiler to test against (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, both compilers +# are tested. +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +# - `check`, when not set, skips checking whether the flag is supported and +# adds it to the list of flags unconditionally. This is only meant for +# add_flag(). +@template +def check_and_add_flag(flag, compiler=None, when=None, check=True): + flags = ["-Werror", flag] + + return check_and_add_flags( + flag, compilation_flags, flags, compiler=compiler, when=when, check=check + ) + + +# Add the given flag to the list of flags for the build. +# - `flag` is the flag (e.g. -fno-sized-deallocation) +# - `compiler` (optional) is the compiler to add the flag for (c_compiler or +# cxx_compiler, from toolchain.configure). When omitted, the flag is added +# for both compilers. +# - `when` (optional) is a @depends function or option name conditioning +# when the flag is wanted. +@template +def add_flag(warning, compiler=None, when=None): + check_and_add_flag(warning, compiler, when, check=False) + + +# Like the compilation checks above, but for asm flags. +@dependable +def asm_flags(): + return namespace(asflags=[], host_asflags=[]) + + +# Tests the given assembler flag is supported; if the flag +# is supported, add it to the list of compilation flags for the build. +# - `flag` is the flag to test +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +# - `check`, when not set, skips checking whether the flag is supported and +# adds it to the list of flags unconditionally. This is only meant for +# add_flag(). +@template +def check_and_add_asm_flag(flag, when=None, check=True): + return check_and_add_flags( + flag, + asm_flags, + [flag], + when=when, + check=check, + mode="assemble", + ) + + +# Like the compilation checks above, but for linker flags. +@dependable +def linker_flags(): + return namespace(ldflags=[], host_ldflags=[]) + + +# Tests the given linker flag is supported; if the flag +# is supported, add it to the list of compilation flags for the build. +# - `flag` is the flag to test +# - `when` (optional) is a @depends function or option name conditioning +# when the warning flag is wanted. +# - `check`, when not set, skips checking whether the flag is supported and +# adds it to the list of flags unconditionally. This is only meant for +# add_flag(). +@template +def check_and_add_linker_flag(flag, compiler=None, when=None, check=True): + return check_and_add_flags( + flag, + linker_flags, + [flag], + when=when, + check=check, + mode="link", + ) + + +# Add the given flag to the list of linker flags for the build. +# - `flag` is the flag (e.g. -fno-sized-deallocation) +# - `when` (optional) is a @depends function or option name conditioning +# when the flag is wanted. +@template +def add_linker_flag(flag, compiler=None, when=None): + check_and_add_linker_flag(flag, compiler, when, check=False) diff --git a/build/moz.configure/compilers-util.configure b/build/moz.configure/compilers-util.configure new file mode 100644 index 0000000000..598de3dc80 --- /dev/null +++ b/build/moz.configure/compilers-util.configure @@ -0,0 +1,204 @@ +# -*- 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 +@imports("textwrap") +@imports(_from="mozbuild.configure", _import="SandboxDependsFunction") +def compiler_class(compiler, host_or_target): + is_target = host_or_target is target + + class Compiler(SandboxDependsFunction): + def _try_compile_or_link( + self, + includes, + body, + flags, + ldflags, + check_msg, + when, + onerror, + ): + if ldflags is None: + + @depends(dependable(flags)) + def flags(flags): + flags = list(flags or []) + flags.append("-c") + return flags + + else: + + @depends(compiler, dependable(ldflags), dependable(flags), when=when) + def flags(compiler, ldflags, flags): + if compiler.type == "clang-cl": + configure_error( + "checking linker flags for clang-cl is not supported yet" + ) + + flags = list(flags or []) + flags.extend(ldflags) + return flags + + @depends(dependable(includes)) + def header(includes): + includes = includes or [] + return ["#include <%s>" % f for f in includes] + + return self.try_run( + header=header, + body=body, + flags=flags, + check_msg=check_msg, + when=when, + onerror=onerror, + ) + + # Generates a test program and attempts to compile it. In case of + # failure, the resulting check will return None. If the test program + # succeeds, it will return the output of the test program. + # - `includes` are the includes (as file names) that will appear at the + # top of the generated test program. + # - `body` is the code that will appear in the main function of the + # generated test program. `return 0;` is appended to the function + # body automatically. + # - `flags` are the flags to be passed to the compiler, in addition to + # `-c`. + # - `check_msg` is the message to be printed to accompany compiling the + # test program. + def try_compile( + self, + includes=None, + body="", + flags=None, + check_msg=None, + when=None, + onerror=lambda: None, + ): + return self._try_compile_or_link( + includes=includes, + body=body, + flags=flags, + ldflags=None, + check_msg=check_msg, + when=when, + onerror=onerror, + ) + + # Same steps as try_compile but doesn't add "-c" + def try_link( + self, + ldflags, + includes=None, + body="", + flags=None, + check_msg=None, + when=None, + onerror=lambda: None, + ): + return self._try_compile_or_link( + includes=includes, + body=body, + flags=flags, + ldflags=ldflags, + check_msg=check_msg, + when=when, + onerror=onerror, + ) + + # Generates a test program and run the compiler against it. In case of + # failure, the resulting check will return None. + # - `header` is code that will appear at the top of the generated test + # program. + # - `body` is the code that will appear in the main function of the + # generated test program. `return 0;` is appended to the function + # body automatically. + # - `flags` are the flags to be passed to the compiler. + # - `check_msg` is the message to be printed to accompany compiling the + # test program. + # - `onerror` is a function called when the check fails. + def try_run( + self, + header=None, + body="", + flags=None, + check_msg=None, + when=None, + onerror=lambda: None, + ): + source = textwrap.dedent( + """\ + int + main(void) + { + %s + ; + return 0; + } + """ + % body + ) + + if check_msg: + + def checking_fn(fn): + return checking(check_msg)(fn) + + else: + + def checking_fn(fn): + return fn + + # We accept onerror being a @depends function that returns a callable. + # So, create a similar @depends function when it's not already one. + if not isinstance(onerror, SandboxDependsFunction): + onerror = dependable(lambda: onerror) + + @depends( + self, + dependable(flags), + extra_toolchain_flags, + dependable(header), + onerror, + configure_cache, + when=when, + ) + @checking_fn + def func( + compiler, + flags, + extra_flags, + header, + onerror, + configure_cache, + ): + flags = list(flags or []) + if is_target: + flags += extra_flags or [] + header = header or "" + if isinstance(header, (list, tuple)): + header = "\n".join(header) + if header: + header += "\n" + + if ( + try_invoke_compiler( + configure_cache, + [compiler.compiler] + compiler.flags, + compiler.language, + header + source, + flags, + onerror=onerror, + wrapper=compiler.wrapper, + ) + is not None + ): + return True + + return func + + compiler.__class__ = Compiler + return compiler diff --git a/build/moz.configure/flags.configure b/build/moz.configure/flags.configure new file mode 100644 index 0000000000..8354b9af34 --- /dev/null +++ b/build/moz.configure/flags.configure @@ -0,0 +1,198 @@ +# -*- 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/. + +# We support C++14, but we don't want to enable the sized deallocation +# facilities in C++14 yet. +check_and_add_flag("-fno-sized-deallocation", compiler=cxx_compiler) +# Likewise for C++17 and aligned allocation. It's not immediately obvious +# from the clang and GCC documentation, but they both support this. +check_and_add_flag("-fno-aligned-new", compiler=cxx_compiler) + +# Please keep these last in this file. +add_old_configure_assignment("_COMPILATION_CFLAGS", compilation_flags.cflags) +add_old_configure_assignment("_COMPILATION_CXXFLAGS", compilation_flags.cxxflags) +add_old_configure_assignment("_COMPILATION_HOST_CFLAGS", compilation_flags.host_cflags) +add_old_configure_assignment( + "_COMPILATION_HOST_CXXFLAGS", compilation_flags.host_cxxflags +) + + +option( + "--disable-new-pass-manager", + help="Use the legacy LLVM pass manager in clang builds", +) + + +@depends( + "--enable-new-pass-manager", + c_compiler, + host, + target, + "MOZ_PGO", + enable_fuzzing, + ubsan, +) +def pass_manager(enabled, compiler, host, target, pgo, enable_fuzzing, ubsan): + if compiler.type not in ("clang", "clang-cl"): + return None + + # As of clang 13, the default pass manager is the new one. + if compiler.version >= "13.0.0": + if enabled: + return namespace(flags=None, enabled=True) + if compiler.type == "clang": + return namespace(flags=["-flegacy-pass-manager"], enabled=False) + if compiler.type == "clang-cl": + return namespace(flags=["-Xclang", "-flegacy-pass-manager"], enabled=False) + + if not enabled: + if compiler.version >= "15.0.0": + die("--disable-new-pass-manager is only supported with clang < 15") + return None + if compiler.version < "9.0.0": + if enabled.origin != "default": + die("--enable-new-pass-manager is only supported with clang >= 9") + return None + + if host.os == "OSX": + # Some native Mac builds hang with the new pass manager. Given the + # inability to test in CI, don't take the risk of further breakage. + if enabled.origin != "default": + die( + "--enable-new-pass-manager causes problems on mac hosts with clang < 13" + ) + return None + if target.os == "OSX" and not pgo: + # Also disable when cross-compiling to Mac, because plain-ish opt + # builds hang. Variants like asan and ccov work fine, but it would be + # too tedious to test them all here. PGO is the only thing that matters + # enough to make an exception for. + if enabled.origin != "default": + die( + "--enable-new-pass-manager causes problems on mac builds with clang < 13" + ) + return None + if enable_fuzzing and compiler.version < "10.0.0": + # Clang 9 does not seem to play well with libFuzzer + if enabled.origin != "default": + die( + "--enable-new-pass-manager causes problems on fuzzing builds with clang < 10" + ) + return None + if ubsan and compiler.version == "10.0.0": + # Clang 10.0.0 hangs with some ubsan-inserted code constructs. + # This was fixed in 10.0.1 (https://llvm.org/pr45835) + if enabled.origin != "default": + die( + "--enable-new-pass-manager causes problems with ubsan builds with clang 10.0.0" + ) + return None + if compiler.type == "clang": + return namespace(flags=["-fexperimental-new-pass-manager"], enabled=True) + elif compiler.type == "clang-cl": + return namespace( + flags=["-Xclang", "-fexperimental-new-pass-manager"], enabled=True + ) + + +set_config("MOZ_PASS_MANAGER_FLAGS", pass_manager.flags) + + +# Try to make builds more reproducible and allow sharing built artifacts across +# source and object directories by using -ffile-prefix-map and friends. To +# "unwind" the prefix maps, use: +# +# (gdb) set substitute-path /topsrcdir/ $topsrcdir/ +# +# (lldb) settings set target.source-map /topobjdir/ $topobjdir/ +# +# See, for example, https://lldb.llvm.org/use/map.html. +@depends( + path_remapping, + path_remappings, + c_compiler, +) +@imports(_from="os", _import="sep") +def file_prefix_map_flags(path_remapping, path_remappings, compiler): + if "c" not in path_remapping: + return [] + + if (compiler.type == "gcc" and compiler.version < "8.1") or ( + compiler.type in ("clang", "clang-cl") and compiler.version < "10.0.0" + ): + die( + f"Compiler of type {compiler.type} and version {compiler.version} " + "does not support --enable-path-remapping." + ) + + flags = [] + for old, new in path_remappings: + # We would prefer to use just -ffile-prefix-map, but clang-cl doesn't + # seem to recognize it. + for flag in ("-fdebug-prefix-map", "-fmacro-prefix-map"): + flag = f"{flag}={old}={new}" + if compiler.type in ("gcc", "clang"): + flags.append(flag) + elif compiler.type == "clang-cl": + flags.extend(["-Xclang", flag]) + + return flags + + +set_config("MOZ_FILE_PREFIX_MAP_FLAGS", file_prefix_map_flags) + + +@depends(c_compiler) +def is_gcc(c_compiler): + return c_compiler.type == "gcc" + + +@depends(c_compiler) +def is_gnu_cc(c_compiler): + return c_compiler.type != "clang-cl" + + +@depends(developer_options, when=is_gnu_cc) +def check_build_id_uuid(developer_options): + return developer_options + + +@depends(developer_options, when=is_gnu_cc) +def check_build_id_sha1(developer_options): + return not developer_options + + +check_and_add_flag("-pipe", when=is_gcc) + +check_and_add_linker_flag("-Wl,--build-id=uuid", when=check_build_id_uuid) +check_and_add_linker_flag("-Wl,--build-id=sha1", when=check_build_id_sha1) + +check_and_add_asm_flag("-Wa,--noexecstack", when=is_gnu_cc) +check_and_add_linker_flag("-Wl,-z,noexecstack", when=is_gnu_cc) +check_and_add_linker_flag("-Wl,-z,text", when=is_gnu_cc) +check_and_add_linker_flag("-Wl,-z,relro", when=is_gnu_cc) +check_and_add_linker_flag("-Wl,-z,now", when=is_gnu_cc) +check_and_add_linker_flag("-Wl,-z,nocopyreloc", when=is_gnu_cc) + + +@depends("--enable-address-sanitizer", is_gnu_cc) +def check_Bsymbolic(enable_asan, is_gnu_cc): + return enable_asan and is_gnu_cc + + +# ASan assumes no symbols are being interposed, and when that happens, +# it's not happy with it. Inconveniently, since Firefox is exporting +# libffi symbols and Gtk+3 pulls system libffi via libwayland-client, +# system libffi interposes libffi symbols that ASan assumes are in +# libxul, so it barfs about buffer overflows. +# Using -Wl,-Bsymbolic ensures no exported symbol can be interposed. +check_and_add_linker_flag("-Wl,-Bsymbolic", when=check_Bsymbolic) + +# Please keep these last in this file. +add_old_configure_assignment("_COMPILATION_ASFLAGS", asm_flags.asflags) +add_old_configure_assignment("_COMPILATION_HOST_ASFLAGS", asm_flags.host_asflags) +add_old_configure_assignment("_COMPILATION_LDFLAGS", linker_flags.ldflags) +add_old_configure_assignment("_COMPILATION_HOST_LDFLAGS", linker_flags.host_ldflags) diff --git a/build/moz.configure/headers.configure b/build/moz.configure/headers.configure new file mode 100644 index 0000000000..5332c7365f --- /dev/null +++ b/build/moz.configure/headers.configure @@ -0,0 +1,119 @@ +# -*- 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/. + +# Check for headers defining standard int types. +check_header("stdint.h") +have_inttypes = check_header("inttypes.h") + +# Assume we have ansi C header files available. +set_define("STDC_HEADERS", True) + +set_config("HAVE_INTTYPES_H", have_inttypes) + +building_linux = depends(target)(lambda target: target.kernel == "Linux") + +have_malloc = check_header("malloc.h") + +check_header("alloca.h") + +add_old_configure_assignment("HAVE_MALLOC_H", have_malloc) + +check_headers( + "sys/byteorder.h", + "getopt.h", + "unistd.h", + "nl_types.h", + "cpuid.h", + "fts.h", +) + +# These are all the places some variant of statfs can be hiding. +check_headers( + "sys/statvfs.h", + "sys/statfs.h", + "sys/vfs.h", + "sys/mount.h", +) + +# Quota support +# Check for both the header and quotactl() because Android headers can have the +# header but not quotactl(). +set_define( + "HAVE_SYS_QUOTA_H", + try_compile( + includes=["sys/quota.h"], + body="quotactl(0, nullptr, 0, (caddr_t)nullptr);", + check_msg="for sys/quota.h", + ), +) +check_header("linux/quota.h", includes=["sys/socket.h"], when=building_linux) + +# SCTP support - needs various network include headers +check_headers( + "linux/if_addr.h", + "linux/rtnetlink.h", + includes=["sys/socket.h"], + when=building_linux, +) + +check_header("sys/queue.h") + +check_headers( + "sys/types.h", + "netinet/in.h", + "byteswap.h", +) + +# memfd_create(2) -- Note that older versions of the Linux man-pages +# project incorrectly cite <sys/memfd.h>, which doesn't exist; this +# was fixed in the man-pages-5.00 release. +set_define( + "HAVE_MEMFD_CREATE", + try_compile( + includes=["sys/mman.h"], + body='memfd_create("", 0);', + check_msg="for memfd_create in sys/mman.h", + ), +) + +# TODO: Move these checks to file specific to --enable-project=js. +have_perf_event_h = check_header("linux/perf_event.h", when=building_linux) + +option( + "--with-linux-headers", + help="location where the Linux kernel headers can be found", + nargs=1, +) + +passed_linux_header_flags = depends_if("--with-linux-headers")( + lambda v: ["-I%s" % v[0]] +) + + +@depends( + try_compile( + includes=["asm/unistd.h"], + body="return sizeof(__NR_perf_event_open);", + flags=passed_linux_header_flags, + check_msg="for perf_event_open system call", + ), + when=have_perf_event_h, +) +def have_perf_event_open(have_perf_event_open): + if have_perf_event_open: + return True + + +set_config("HAVE_LINUX_PERF_EVENT_H", have_perf_event_open) + + +@depends(passed_linux_header_flags, have_perf_event_open) +def linux_headers_includes(passed_linux_header_flags, have_perf_event_open): + if have_perf_event_open and passed_linux_header_flags: + return passed_linux_header_flags[0] + + +set_config("LINUX_HEADERS_INCLUDES", linux_headers_includes) diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure new file mode 100644 index 0000000000..11e22ee536 --- /dev/null +++ b/build/moz.configure/init.configure @@ -0,0 +1,1278 @@ +# -*- 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/. + +include("util.configure") +include("checks.configure") + +# Make `toolkit` available when toolkit/moz.configure is not included. +toolkit = dependable(None) +# Likewise with `bindgen_config_paths` when +# build/moz.configure/bindgen.configure is not included. +bindgen_config_paths = dependable(None) + + +@depends("--help") +def build_environment(_): + topobjdir = os.path.realpath(".") + topsrcdir = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..")) + dist = os.path.join(topobjdir, "dist") + + return namespace( + topsrcdir=topsrcdir, + topobjdir=topobjdir, + dist=dist, + ) + + +@depends(build_environment) +@imports(_import="json") +@imports(_from="pathlib", _import="Path") +def configure_cache(build_environment): + """ + This cache is used to cache the results of compiler invocations + between different runs of configure and save them to the disk, which + results in a significant speed up of subsequent configure runs (15%-50%). + + It is not currently thread safe because it is just a simple dictionary + wrapped in a dummy class (ConfigureCache). It could be improved to be + thread safe in the future, if we ever make configure parallelized, but + for now there is no advantage to doing so. + """ + + class ConfigureCache(dict): + pass + + cache_file = Path(build_environment.topobjdir) / "configure.cache" + if cache_file.exists(): + with cache_file.open() as f: + cache_data = json.load(f) + else: + cache_data = {} + + cache = ConfigureCache(cache_data) + cache.version_checked_compilers = set() + + return cache + + +set_config("TOPSRCDIR", build_environment.topsrcdir) +set_config("TOPOBJDIR", build_environment.topobjdir) +set_config("DIST", build_environment.dist) + +add_old_configure_assignment("_topsrcdir", build_environment.topsrcdir) +add_old_configure_assignment("_objdir", build_environment.topobjdir) +add_old_configure_assignment("DIST", build_environment.dist) + +option(env="MOZ_AUTOMATION", help="Enable options for automated builds") +set_config("MOZ_AUTOMATION", depends_if("MOZ_AUTOMATION")(lambda x: True)) + + +option(env="OLD_CONFIGURE", nargs=1, help="Path to the old configure script") + +option(env="MOZCONFIG", nargs=1, help="Mozconfig location") + + +# Read user mozconfig +# ============================================================== +# Note: the dependency on --help is only there to always read the mozconfig, +# even when --help is passed. Without this dependency, the function wouldn't +# be called when --help is passed, and the mozconfig wouldn't be read. + + +@depends("MOZCONFIG", "OLD_CONFIGURE", build_environment, "--help") +@imports(_from="mozbuild.mozconfig", _import="MozconfigLoader") +@imports(_from="mozboot.mozconfig", _import="find_mozconfig") +@imports("os") +def mozconfig(mozconfig, old_configure, build_env, help): + # Don't read the mozconfig for the js configure (yay backwards + # compatibility) + # While the long term goal is that js and top-level use the same configure + # and the same overall setup, including the possibility to use mozconfigs, + # figuring out what we want to do wrt mozconfig vs. command line and + # environment variable is not a clear-cut case, and it's more important to + # fix the immediate problem mozconfig causes to js developers by + # "temporarily" returning to the previous behavior of not loading the + # mozconfig for the js configure. + # Separately to the immediate problem for js developers, there is also the + # need to not load a mozconfig when running js configure as a subconfigure. + # Unfortunately, there is no direct way to tell whether the running + # configure is the js configure. The indirect way is to look at the + # OLD_CONFIGURE path, which points to js/src/old-configure. + # I expect we'll have figured things out for mozconfigs well before + # old-configure dies. + if ( + old_configure + and os.path.dirname(os.path.abspath(old_configure[0])).endswith("/js/src") + or (mozconfig and mozconfig[0] == os.devnull) + ): + return {"path": None} + + topsrcdir = build_env.topsrcdir + loader = MozconfigLoader(topsrcdir) + mozconfig = mozconfig[0] if mozconfig else None + mozconfig = find_mozconfig(topsrcdir, env={"MOZCONFIG": mozconfig}) + mozconfig = loader.read_mozconfig(mozconfig) + + return mozconfig + + +set_config("MOZCONFIG", depends(mozconfig)(lambda m: m["path"])) + + +# Mozilla-Build +# ============================================================== +option(env="MOZILLABUILD", nargs=1, help="Path to Mozilla Build (Windows-only)") + +option(env="CONFIG_SHELL", nargs=1, help="Path to a POSIX shell") + +# It feels dirty replicating this from python/mozbuild/mozbuild/mozconfig.py, +# but the end goal being that the configure script would go away... + + +@depends("CONFIG_SHELL", "MOZILLABUILD") +@checking("for a shell") +@imports("sys") +@imports(_from="pathlib", _import="Path") +def shell(value, mozillabuild): + if value: + return find_program(value[0]) + shell = "sh" + if mozillabuild: + if (Path(mozillabuild[0]) / "msys2").exists(): + shell = mozillabuild[0] + "/msys2/usr/bin/sh" + else: + shell = mozillabuild[0] + "/msys/bin/sh" + if sys.platform == "win32": + shell = shell + ".exe" + return find_program(shell) + + +# This defines a reasonable shell for when running with --help. +# If one was passed in the environment, though, fall back to that. +@depends("--help", "CONFIG_SHELL") +def help_shell(help, shell): + if help and not shell: + return "sh" + + +shell = help_shell | shell + + +# Python 3 +# ======== +@dependable +@checking("for Python 3", callback=lambda x: "%s (%s)" % (x.path, x.str_version)) +@imports("sys") +@imports(_from="mach.site", _import="PythonVirtualenv") +@imports(_from="os.path", _import="realpath") +def virtualenv_python3(): + return namespace( + # sys.executable is currently not updated for in-process activations. However, + # sys.prefix is, so we can calculate the python executable's path from there. + path=normalize_path(PythonVirtualenv(realpath(sys.prefix)).python_path), + str_version=".".join(str(i) for i in sys.version_info[0:3]), + ) + + +set_config("PYTHON3", virtualenv_python3.path) +set_config("PYTHON3_VERSION", virtualenv_python3.str_version) +add_old_configure_assignment("PYTHON3", virtualenv_python3.path) + + +# Inject mozconfig options +# ============================================================== +# All options defined above this point can't be injected in mozconfig_options +# below, so collect them. + + +@template +def early_options(): + @depends("--help") + @imports("__sandbox__") + def early_options(_): + return set(option.env for option in __sandbox__._options.values() if option.env) + + return early_options + + +early_options = early_options() + + +@depends(mozconfig, early_options, "MOZ_AUTOMATION", "--help") +# This gives access to the sandbox. Don't copy this blindly. +@imports("__sandbox__") +@imports("os") +def mozconfig_options(mozconfig, early_options, automation, help): + if mozconfig["path"]: + if "MOZ_AUTOMATION_MOZCONFIG" in mozconfig["env"]["added"]: + if not automation: + log.error( + "%s directly or indirectly includes an in-tree " "mozconfig.", + mozconfig["path"], + ) + log.error( + "In-tree mozconfigs make strong assumptions about " + "and are only meant to be used by Mozilla " + "automation." + ) + die("Please don't use them.") + helper = __sandbox__._helper + log.info("Adding configure options from %s" % mozconfig["path"]) + for arg in mozconfig["configure_args"]: + log.info(" %s" % arg) + # We could be using imply_option() here, but it has other + # contraints that don't really apply to the command-line + # emulation that mozconfig provides. + helper.add(arg, origin="mozconfig", args=helper._args) + + def add(key, value): + if key.isupper(): + arg = "%s=%s" % (key, value) + log.info(" %s" % arg) + if key not in early_options: + helper.add(arg, origin="mozconfig", args=helper._args) + + for key, value in mozconfig["env"]["added"].items(): + add(key, value) + os.environ[key] = value + for key, (_, value) in mozconfig["env"]["modified"].items(): + add(key, value) + os.environ[key] = value + for key, value in mozconfig["vars"]["added"].items(): + add(key, value) + for key, (_, value) in mozconfig["vars"]["modified"].items(): + add(key, value) + + +@depends(build_environment, "--help") +@imports(_from="os.path", _import="exists") +def js_package(build_env, help): + return not exists(os.path.join(build_env.topsrcdir, "browser")) + + +# Source checkout and version control integration. +# ================================================ + + +@depends(build_environment, "MOZ_AUTOMATION", js_package, "--help") +@checking("for vcs source checkout") +@imports("os") +def vcs_checkout_type(build_env, automation, js_package, help): + if os.path.exists(os.path.join(build_env.topsrcdir, ".hg")): + return "hg" + elif os.path.exists(os.path.join(build_env.topsrcdir, ".git")): + return "git" + elif automation and not js_package and not help: + raise FatalCheckError( + "unable to resolve VCS type; must run " + "from a source checkout when MOZ_AUTOMATION " + "is set" + ) + + +# Resolve VCS binary for detected repository type. + + +# TODO remove hg.exe once bug 1382940 addresses ambiguous executables case. +hg = check_prog( + "HG", + ( + "hg.exe", + "hg", + ), + allow_missing=True, + when=depends(vcs_checkout_type)(lambda x: x == "hg"), +) +git = check_prog( + "GIT", + ("git",), + allow_missing=True, + when=depends(vcs_checkout_type)(lambda x: x == "git"), +) + + +@depends_if(hg) +@checking("for Mercurial version") +@imports("os") +@imports("re") +def hg_version(hg): + # HGPLAIN in Mercurial 1.5+ forces stable output, regardless of set + # locale or encoding. + env = dict(os.environ) + env["HGPLAIN"] = "1" + + out = check_cmd_output(hg, "--version", env=env) + + match = re.search(r"Mercurial Distributed SCM \(version ([^\)]+)", out) + + if not match: + raise FatalCheckError("unable to determine Mercurial version: %s" % out) + + # The version string may be "unknown" for Mercurial run out of its own + # source checkout or for bad builds. But LooseVersion handles it. + + return Version(match.group(1)) + + +# Resolve Mercurial config items so other checks have easy access. +# Do NOT set this in the config because it may contain sensitive data +# like API keys. + + +@depends_all(build_environment, hg, hg_version) +@imports("os") +def hg_config(build_env, hg, version): + env = dict(os.environ) + env["HGPLAIN"] = "1" + + # Warnings may get sent to stderr. But check_cmd_output() ignores + # stderr if exit code is 0. And the command should always succeed if + # `hg version` worked. + out = check_cmd_output(hg, "config", env=env, cwd=build_env.topsrcdir) + + config = {} + + for line in out.strip().splitlines(): + key, value = [s.strip() for s in line.split("=", 1)] + config[key] = value + + return config + + +@depends_if(git) +@checking("for Git version") +@imports("re") +def git_version(git): + out = check_cmd_output(git, "--version").rstrip() + + match = re.search("git version (.*)$", out) + + if not match: + raise FatalCheckError("unable to determine Git version: %s" % out) + + return Version(match.group(1)) + + +# Only set VCS_CHECKOUT_TYPE if we resolved the VCS binary. +# Require resolved VCS info when running in automation so automation's +# environment is more well-defined. + + +@depends(vcs_checkout_type, hg_version, git_version, "MOZ_AUTOMATION") +def exposed_vcs_checkout_type(vcs_checkout_type, hg, git, automation): + if vcs_checkout_type == "hg": + if hg: + return "hg" + + if automation: + raise FatalCheckError("could not resolve Mercurial binary info") + + elif vcs_checkout_type == "git": + if git: + return "git" + + if automation: + raise FatalCheckError("could not resolve Git binary info") + elif vcs_checkout_type: + raise FatalCheckError("unhandled VCS type: %s" % vcs_checkout_type) + + +set_config("VCS_CHECKOUT_TYPE", exposed_vcs_checkout_type) + +# Obtain a Repository interface for the current VCS repository. + + +@depends(build_environment, exposed_vcs_checkout_type, hg, git) +@imports(_from="mozversioncontrol", _import="get_repository_object") +def vcs_repository(build_env, vcs_checkout_type, hg, git): + if vcs_checkout_type == "hg": + return get_repository_object(build_env.topsrcdir, hg=hg) + elif vcs_checkout_type == "git": + return get_repository_object(build_env.topsrcdir, git=git) + elif vcs_checkout_type: + raise FatalCheckError("unhandled VCS type: %s" % vcs_checkout_type) + + +@depends_if(vcs_repository) +@checking("for sparse checkout") +def vcs_sparse_checkout(repo): + return repo.sparse_checkout_present() + + +set_config("VCS_SPARSE_CHECKOUT", vcs_sparse_checkout) + +# The application/project to build +# ============================================================== +option( + "--enable-application", + nargs=1, + env="MOZ_BUILD_APP", + help="Application to build. Same as --enable-project.", +) + + +@depends("--enable-application") +def application(app): + if app: + return app + + +imply_option("--enable-project", application) + + +@depends(build_environment, js_package) +def default_project(build_env, js_package): + if js_package or build_env.topobjdir.endswith("/js/src"): + return "js" + return "browser" + + +option("--enable-project", nargs=1, default=default_project, help="Project to build") + + +# Artifact builds +# ============================================================== + +option( + "--enable-artifact-builds", + env="MOZ_ARTIFACT_BUILDS", + help="Download and use prebuilt binary artifacts.", +) + + +@depends("--enable-artifact-builds") +def artifact_builds(value): + if value: + return True + + +set_config("MOZ_ARTIFACT_BUILDS", artifact_builds) + +# Host and target systems +# ============================================================== +option("--host", nargs=1, help="Define the system type performing the build") + +option( + "--target", + nargs=1, + help="Define the system type where the resulting executables will be " "used", +) + + +@imports(_from="mozbuild.configure.constants", _import="Abi") +@imports(_from="mozbuild.configure.constants", _import="CPU") +@imports(_from="mozbuild.configure.constants", _import="CPU_bitness") +@imports(_from="mozbuild.configure.constants", _import="Endianness") +@imports(_from="mozbuild.configure.constants", _import="Kernel") +@imports(_from="mozbuild.configure.constants", _import="OS") +@imports(_from="__builtin__", _import="ValueError") +def split_triplet(triplet, allow_wasi=False): + # The standard triplet is defined as + # CPU_TYPE-VENDOR-OPERATING_SYSTEM + # There is also a quartet form: + # CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM + # But we can consider the "KERNEL-OPERATING_SYSTEM" as one. + # Additionally, some may omit "unknown" when the vendor + # is not specified and emit + # CPU_TYPE-OPERATING_SYSTEM + vendor = "unknown" + parts = triplet.split("-", 2) + if len(parts) == 3: + cpu, vendor, os = parts + elif len(parts) == 2: + cpu, os = parts + else: + raise ValueError("Unexpected triplet string: %s" % triplet) + + # Autoconf uses config.sub to validate and canonicalize those triplets, + # but the granularity of its results has never been satisfying to our + # use, so we've had our own, different, canonicalization. We've also + # historically not been very consistent with how we use the canonicalized + # values. Hopefully, this will help us make things better. + # The tests are inherited from our decades-old autoconf-based configure, + # which can probably be improved/cleaned up because they are based on a + # mix of uname and config.guess output, while we now only use the latter, + # which presumably has a cleaner and leaner output. Let's refine later. + raw_os = os = os.replace("/", "_") + abi = None + sub_configure_alias = triplet + if "android" in os: + canonical_os = "Android" + canonical_kernel = "Linux" + elif os.startswith("linux"): + canonical_os = "GNU" + canonical_kernel = "Linux" + elif os.startswith("kfreebsd") and os.endswith("-gnu"): + canonical_os = "GNU" + canonical_kernel = "kFreeBSD" + elif os.startswith("gnu"): + canonical_os = canonical_kernel = "GNU" + elif os.startswith("mingw") or os in ("windows-msvc", "windows-gnu"): + canonical_os = canonical_kernel = "WINNT" + if not os.startswith("mingw"): + if os == "windows-msvc": + abi = "msvc" + elif os == "windows-gnu": + abi = "mingw" + # Many things down the line are looking for the string "mingw32" + # until they are all fixed, we pretend that's the raw os we had + # in the first place, even when we didn't. + sub_configure_alias = sub_configure_alias[: -len(os)] + "mingw32" + raw_os = "mingw32" + elif os.startswith("darwin"): + canonical_kernel = "Darwin" + canonical_os = "OSX" + elif os.startswith("dragonfly"): + canonical_os = canonical_kernel = "DragonFly" + elif os.startswith("freebsd"): + canonical_os = canonical_kernel = "FreeBSD" + elif os.startswith("netbsd"): + canonical_os = canonical_kernel = "NetBSD" + elif os.startswith("openbsd"): + canonical_os = canonical_kernel = "OpenBSD" + elif os.startswith("solaris"): + canonical_os = canonical_kernel = "SunOS" + elif os.startswith("wasi") and allow_wasi: + canonical_os = canonical_kernel = "WASI" + else: + raise ValueError("Unknown OS: %s" % os) + + # The CPU granularity is probably not enough. Moving more things from + # old-configure will tell us if we need more + if cpu.endswith("86") or (cpu.startswith("i") and "86" in cpu): + canonical_cpu = "x86" + endianness = "little" + elif cpu in ("x86_64", "ia64"): + canonical_cpu = cpu + endianness = "little" + elif cpu in ("s390", "s390x"): + canonical_cpu = cpu + endianness = "big" + elif cpu in ("powerpc64", "ppc64", "powerpc64le", "ppc64le"): + canonical_cpu = "ppc64" + endianness = "little" if "le" in cpu else "big" + elif cpu in ("powerpc", "ppc", "rs6000") or cpu.startswith("powerpc"): + canonical_cpu = "ppc" + endianness = "big" + elif cpu in ("Alpha", "alpha", "ALPHA"): + canonical_cpu = "Alpha" + endianness = "little" + elif cpu.startswith("hppa") or cpu == "parisc": + canonical_cpu = "hppa" + endianness = "big" + elif cpu.startswith("sparc64") or cpu.startswith("sparcv9"): + canonical_cpu = "sparc64" + endianness = "big" + elif cpu.startswith("sparc") or cpu == "sun4u": + canonical_cpu = "sparc" + endianness = "big" + elif cpu.startswith("arm"): + canonical_cpu = "arm" + endianness = "big" if cpu.startswith(("armeb", "armbe")) else "little" + elif cpu in ("m68k"): + canonical_cpu = "m68k" + endianness = "big" + elif cpu in ("mips", "mipsel"): + canonical_cpu = "mips32" + endianness = "little" if "el" in cpu else "big" + elif cpu in ("mips64", "mips64el"): + canonical_cpu = "mips64" + endianness = "little" if "el" in cpu else "big" + elif cpu.startswith("aarch64"): + canonical_cpu = "aarch64" + endianness = "little" + elif cpu in ("riscv64", "riscv64gc"): + canonical_cpu = "riscv64" + endianness = "little" + elif cpu.startswith("loongarch64"): + canonical_cpu = "loongarch64" + endianness = "little" + elif cpu == "sh4": + canonical_cpu = "sh4" + endianness = "little" + elif cpu == "wasm32" and allow_wasi: + canonical_cpu = "wasm32" + endianness = "little" + else: + raise ValueError("Unknown CPU type: %s" % cpu) + + # Toolchains, most notably for cross compilation may use cpu-os + # prefixes. We need to be more specific about the LLVM target on Mac + # so cross-language LTO will work correctly. + + if os.startswith("darwin"): + toolchain = "%s-apple-%s" % (cpu, os) + else: + toolchain = "%s-%s" % (cpu, os) + + return namespace( + alias=triplet, + cpu=CPU(canonical_cpu), + bitness=CPU_bitness[canonical_cpu], + kernel=Kernel(canonical_kernel), + os=OS(canonical_os), + endianness=Endianness(endianness), + # For now, only report the Windows ABI. + abi=abi and Abi(abi), + raw_cpu=cpu, + raw_os=raw_os, + toolchain=toolchain, + vendor=vendor, + sub_configure_alias=sub_configure_alias, + ) + + +# This defines a fake target/host namespace for when running with --help +# If either --host or --target is passed on the command line, then fall +# back to the real deal. +@depends("--help", "--host", "--target") +def help_host_target(help, host, target): + if help and not host and not target: + return namespace( + alias="unknown-unknown-unknown", + cpu="unknown", + bitness="unknown", + kernel="unknown", + os="unknown", + endianness="unknown", + abi="unknown", + raw_cpu="unknown", + raw_os="unknown", + toolchain="unknown-unknown", + ) + + +def config_sub(shell, triplet): + config_sub = os.path.join(os.path.dirname(__file__), "..", "autoconf", "config.sub") + # Config.sub doesn't like the *-windows-msvc/*-windows-gnu triplets, so + # munge those before and after calling config.sub. + suffix = None + munging = { + "-windows-msvc": "-mingw32", + "-windows-gnu": "-mingw32", + } + for check_suffix, replacement in munging.items(): + if triplet.endswith(check_suffix): + suffix = check_suffix + triplet = triplet[: -len(suffix)] + replacement + break + result = check_cmd_output(shell, config_sub, triplet).strip() + if suffix: + assert result.endswith(replacement) + result = result[: -len(replacement)] + suffix + return result + + +@depends("--host", shell) +@checking("for host system type", lambda h: h.alias) +@imports("os") +@imports("sys") +@imports(_from="__builtin__", _import="ValueError") +def real_host(value, shell): + if not value and sys.platform == "win32": + arch = os.environ.get("PROCESSOR_ARCHITEW6432") or os.environ.get( + "PROCESSOR_ARCHITECTURE" + ) + if arch == "AMD64": + return split_triplet("x86_64-pc-windows-msvc") + elif arch == "x86": + return split_triplet("i686-pc-windows-msvc") + + if not value: + config_guess = os.path.join( + os.path.dirname(__file__), "..", "autoconf", "config.guess" + ) + + # Ensure that config.guess is determining the host triplet, not the target + # triplet + env = os.environ.copy() + env.pop("CC_FOR_BUILD", None) + env.pop("HOST_CC", None) + env.pop("CC", None) + + host = check_cmd_output(shell, config_guess, env=env).strip() + try: + return split_triplet(host) + except ValueError: + pass + else: + host = value[0] + + host = config_sub(shell, host) + + try: + return split_triplet(host) + except ValueError as e: + die(e) + + +host = help_host_target | real_host + + +@depends("--target", real_host, shell, "--enable-project", "--enable-application") +@checking("for target system type", lambda t: t.alias) +@imports(_from="__builtin__", _import="ValueError") +def real_target(value, host, shell, project, application): + # Because --enable-project is implied by --enable-application, and + # implied options are not currently handled during --help, which is + # used get the build target in mozbuild.base, we manually check + # whether --enable-application was given, and fall back to + # --enable-project if not. Both can't be given contradictory values + # under normal circumstances, so it's fine. + if application: + project = application[0] + elif project: + project = project[0] + if not value: + if project == "mobile/android": + target_cpu, target_system = ( + ("aarch64", "android") + if host.cpu == "aarch64" + else ("arm", "androideabi") + ) + return split_triplet(f"{target_cpu}-unknown-linux-{target_system}") + return host + # If --target was only given a cpu arch, expand it with the + # non-cpu part of the host. For mobile/android, expand it with + # unknown-linux-android. + target = value[0] + if "-" not in target: + if project == "mobile/android": + rest = "unknown-linux-android" + if target.startswith("arm"): + rest += "eabi" + else: + cpu, rest = host.alias.split("-", 1) + target = "-".join((target, rest)) + try: + return split_triplet(target) + except ValueError: + pass + + try: + return split_triplet(config_sub(shell, target), allow_wasi=(project == "js")) + except ValueError as e: + die(e) + + +target = help_host_target | real_target + + +@depends(host, target) +@checking("whether cross compiling") +def cross_compiling(host, target): + return host != target + + +set_config("CROSS_COMPILE", cross_compiling) +set_define("CROSS_COMPILE", cross_compiling) + + +@depends(target) +def have_64_bit(target): + if target.bitness == 64: + return True + + +set_config("HAVE_64BIT_BUILD", have_64_bit) +set_define("HAVE_64BIT_BUILD", have_64_bit) +add_old_configure_assignment("HAVE_64BIT_BUILD", have_64_bit) + +# Some third-party code bases depend on this being set for big-endians. +set_define( + "WORDS_BIGENDIAN", True, when=depends(target.endianness)(lambda e: e == "big") +) + + +# Autoconf needs these set + + +@depends(host) +def host_for_sub_configure(host): + return "--host=%s" % host.sub_configure_alias + + +@depends(target) +def target_for_sub_configure(target): + return "--target=%s" % target.sub_configure_alias + + +# These variables are for compatibility with the current moz.builds and +# old-configure. Eventually, we'll want to canonicalize better. +@depends(target) +def target_variables(target): + if target.kernel == "kFreeBSD": + os_target = "GNU/kFreeBSD" + os_arch = "GNU_kFreeBSD" + elif target.kernel == "Darwin" or (target.kernel == "Linux" and target.os == "GNU"): + os_target = target.kernel + os_arch = target.kernel + else: + os_target = target.os + os_arch = target.kernel + + return namespace( + OS_TARGET=str(os_target), + OS_ARCH=str(os_arch), + INTEL_ARCHITECTURE=target.cpu in ("x86", "x86_64") or None, + ) + + +set_config("OS_TARGET", target_variables.OS_TARGET) +add_old_configure_assignment("OS_TARGET", target_variables.OS_TARGET) +set_config("OS_ARCH", target_variables.OS_ARCH) +add_old_configure_assignment("OS_ARCH", target_variables.OS_ARCH) +obsolete_config("CPU_ARCH", replacement="TARGET_CPU") +set_config("INTEL_ARCHITECTURE", target_variables.INTEL_ARCHITECTURE) +set_config("TARGET_CPU", target.cpu) +add_old_configure_assignment("TARGET_CPU", target.cpu) +set_config("TARGET_RAW_CPU", target.raw_cpu) +set_config("TARGET_OS", target.os) +set_config("TARGET_RAW_OS", target.raw_os) +set_config("TARGET_ENDIANNESS", target.endianness) + + +@depends(host) +def host_variables(host): + if host.kernel == "kFreeBSD": + os_arch = "GNU_kFreeBSD" + else: + os_arch = host.kernel + return namespace( + HOST_OS_ARCH=os_arch, + ) + + +set_config("HOST_CPU_ARCH", host.cpu) +set_config("HOST_OS_ARCH", host_variables.HOST_OS_ARCH) +add_old_configure_assignment("HOST_OS_ARCH", host_variables.HOST_OS_ARCH) +set_config("HOST_ALIAS", host.alias) + + +@depends(target) +def target_is_windows(target): + if target.kernel == "WINNT": + return True + + +@depends(host) +def host_is_windows(host): + if host.kernel == "WINNT": + return True + + +set_define("_WINDOWS", target_is_windows) +set_define("WIN32", target_is_windows) +set_define("XP_WIN", target_is_windows) + + +@depends(target) +def target_is_unix(target): + if target.kernel != "WINNT": + return True + + +set_define("XP_UNIX", target_is_unix) + + +@depends(target) +def target_is_darwin(target): + if target.kernel == "Darwin": + return True + + +set_define("XP_DARWIN", target_is_darwin) + + +@depends(target) +def target_is_osx(target): + if target.kernel == "Darwin" and target.os == "OSX": + return True + + +@depends(host) +def host_is_osx(host): + if host.os == "OSX": + return True + + +set_define("XP_MACOSX", target_is_osx) + + +@depends(target) +def target_has_linux_kernel(target): + if target.kernel == "Linux": + return True + + +set_define("XP_LINUX", target_has_linux_kernel) + + +@depends(target) +def target_is_linux_or_wasi(target): + if (target.kernel == "Linux" and target.os == "GNU") or target.kernel == "WASI": + return True + + +@depends(target) +def target_is_android(target): + if target.os == "Android": + return True + + +set_define("ANDROID", target_is_android) + + +@depends(target) +def target_is_openbsd(target): + if target.kernel == "OpenBSD": + return True + + +set_define("XP_OPENBSD", target_is_openbsd) + + +@depends(target) +def target_is_netbsd(target): + if target.kernel == "NetBSD": + return True + + +set_define("XP_NETBSD", target_is_netbsd) + + +@depends(target) +def target_is_freebsd(target): + if target.kernel == "FreeBSD": + return True + + +set_define("XP_FREEBSD", target_is_freebsd) + + +@depends(target) +def target_is_solaris(target): + if target.kernel == "SunOS": + return True + + +set_define("XP_SOLARIS", target_is_solaris) + + +@depends(target) +def target_is_sparc(target): + if target.cpu == "sparc64": + return True + + +set_define("SPARC64", target_is_sparc) + + +@depends(target, when=target_is_android) +def android_cpu_arch(target): + d = { + "aarch64": "arm64-v8a", + "arm": "armeabi-v7a", + "x86": "x86", + "x86_64": "x86_64", + } + if target.cpu not in d: + die(f"Cannot determine android_cpu_arch: unknown target.cpu: {target.cpu}") + return d[target.cpu] + + +set_config("ANDROID_CPU_ARCH", android_cpu_arch) + + +@depends("--enable-project", build_environment, "--help") +@imports(_from="os.path", _import="exists") +def include_project_configure(project, build_env, help): + if not project: + die("--enable-project is required.") + + base_dir = build_env.topsrcdir + path = os.path.join(base_dir, project[0], "moz.configure") + if not exists(path): + die("Cannot find project %s", project[0]) + return path + + +@depends("--enable-project") +def build_project(project): + return project[0] + + +set_config("MOZ_BUILD_APP", build_project) +set_define("MOZ_BUILD_APP", build_project) +add_old_configure_assignment("MOZ_BUILD_APP", build_project) + + +option(env="MOZILLA_OFFICIAL", help="Build an official release") + + +@depends("MOZILLA_OFFICIAL") +def mozilla_official(official): + if official: + return True + + +set_config("MOZILLA_OFFICIAL", mozilla_official) +set_define("MOZILLA_OFFICIAL", mozilla_official) +add_old_configure_assignment("MOZILLA_OFFICIAL", mozilla_official) + + +# Allow specifying custom paths to the version files used by the milestone() function below. +option( + "--with-version-file-path", + nargs=1, + help="Specify a custom path to app version files instead of auto-detecting", + default=None, +) + + +@depends("--with-version-file-path") +def version_path(path): + return path + + +# Allow to easily build nightly with a release / beta configuration so that we +# can have the same options we'd have on a release version. +# This is useful for performance profiling, as there are things that we don't +# enable in release (like the background hang monitor) that can affect +# performance. +option( + "--as-milestone", + help="Build with another milestone configuration (e.g., as release)", + choices=("early-beta", "late-beta", "release"), + default=None, +) + + +# set RELEASE_OR_BETA and NIGHTLY_BUILD variables depending on the cycle we're in +# The logic works like this: +# - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD) +# - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora +# - otherwise, we're building Release/Beta (define RELEASE_OR_BETA) +@depends( + build_environment, + build_project, + version_path, + "--as-milestone", + "--help", +) +@imports(_from="__builtin__", _import="open") +@imports("os") +@imports("re") +def milestone(build_env, build_project, version_path, as_milestone, _): + versions = [] + paths = ["config/milestone.txt"] + if build_project == "js": + paths = paths * 3 + else: + paths += [ + "browser/config/version.txt", + "browser/config/version_display.txt", + ] + if version_path: + version_path = version_path[0] + else: + version_path = os.path.join(build_project, "config") + for f in ("version.txt", "version_display.txt"): + f = os.path.join(version_path, f) + if not os.path.exists(os.path.join(build_env.topsrcdir, f)): + break + paths.append(f) + + for p in paths: + with open(os.path.join(build_env.topsrcdir, p), "r") as fh: + content = fh.read().splitlines() + if not content: + die("Could not find a version number in {}".format(p)) + versions.append(content[-1]) + + is_early_beta_or_earlier = None + if as_milestone: + if "a1" not in versions[0]: + # We could make this work with some effort + die("--as-milestone only works on nightly builds") + as_milestone = as_milestone[0] + as_milestone_flag = "" if as_milestone == "release" else "b1" + versions = [v.replace("a1", as_milestone_flag) for v in versions] + if as_milestone == "early-beta": + is_early_beta_or_earlier = True + + milestone, firefox_version, firefox_version_display = versions[:3] + + # version.txt content from the project directory if there is one, otherwise + # the firefox version. + app_version = versions[3] if len(versions) > 3 else firefox_version + # version_display.txt content from the project directory if there is one, + # otherwise version.txt content from the project directory, otherwise the + # firefox version for display. + app_version_display = versions[-1] if len(versions) > 3 else firefox_version_display + + is_nightly = is_release_or_beta = None + + if "a1" in milestone: + is_nightly = True + elif "a" not in milestone: + is_release_or_beta = True + + major_version = milestone.split(".")[0] + m = re.search(r"([ab]\d+)", milestone) + ab_patch = m.group(1) if m else "" + + if not as_milestone: + defines = os.path.join(build_env.topsrcdir, "build", "defines.sh") + with open(defines, "r") as fh: + for line in fh.read().splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + name, _, value = line.partition("=") + name = name.strip() + value = value.strip() + if name != "EARLY_BETA_OR_EARLIER": + die( + "Only the EARLY_BETA_OR_EARLIER variable can be set in build/defines.sh" + ) + if value and any(x in app_version_display for x in "ab"): + is_early_beta_or_earlier = True + + # Only expose the major version milestone in the UA string and hide the + # patch leve (bugs 572659 and 870868). + # + # Only expose major milestone and alpha version in the symbolversion + # string; as the name suggests, we use it for symbol versioning on Linux. + return namespace( + version=milestone, + uaversion="%s.0" % major_version, + symbolversion="%s%s" % (major_version, ab_patch), + is_nightly=is_nightly, + is_release_or_beta=is_release_or_beta, + is_early_beta_or_earlier=is_early_beta_or_earlier, + is_esr=app_version_display.endswith("esr") or None, + app_version=app_version, + app_version_display=app_version_display, + ) + + +set_config("GRE_MILESTONE", milestone.version) +set_config("NIGHTLY_BUILD", milestone.is_nightly) +set_define("NIGHTLY_BUILD", milestone.is_nightly) +set_config("RELEASE_OR_BETA", milestone.is_release_or_beta) +set_define("RELEASE_OR_BETA", milestone.is_release_or_beta) +set_config("MOZ_ESR", milestone.is_esr) +set_define("MOZ_ESR", milestone.is_esr) +set_config("EARLY_BETA_OR_EARLIER", milestone.is_early_beta_or_earlier) +set_define("EARLY_BETA_OR_EARLIER", milestone.is_early_beta_or_earlier) +set_define("MOZILLA_VERSION", depends(milestone)(lambda m: '"%s"' % m.version)) +set_config("MOZILLA_VERSION", milestone.version) +set_define("MOZILLA_VERSION_U", milestone.version) +set_define("MOZILLA_UAVERSION", depends(milestone)(lambda m: '"%s"' % m.uaversion)) +set_config("MOZILLA_SYMBOLVERSION", milestone.symbolversion) +# JS configure still want to look at this one. +add_old_configure_assignment("MOZILLA_SYMBOLVERSION", milestone.symbolversion) + +set_config("MOZ_APP_VERSION", milestone.app_version) +set_config("MOZ_APP_VERSION_DISPLAY", milestone.app_version_display) +add_old_configure_assignment("MOZ_APP_VERSION", milestone.app_version) + +add_old_configure_assignment("NIGHTLY_BUILD", milestone.is_nightly) + +# The app update channel is 'default' when not supplied. The value is used in +# the application's confvars.sh (and is made available to a project specific +# moz.configure). +option( + "--enable-update-channel", + nargs=1, + help="Select application update channel", + default="default", +) + + +@depends("--enable-update-channel") +def update_channel(channel): + if not channel or channel[0] == "": + return "default" + return channel[0].lower() + + +set_config("MOZ_UPDATE_CHANNEL", update_channel) +set_define("MOZ_UPDATE_CHANNEL", update_channel) +add_old_configure_assignment("MOZ_UPDATE_CHANNEL", update_channel) + + +option( + env="MOZBUILD_STATE_PATH", + nargs=1, + help="Path to a persistent state directory for the build system " + "and related tools", +) + + +@depends("MOZBUILD_STATE_PATH", "--help") +@imports("os") +def mozbuild_state_path(path, _): + if path: + return normalize_path(path[0]) + return normalize_path(os.path.expanduser(os.path.join("~", ".mozbuild"))) + + +@depends("MOZILLABUILD", shell, host_is_windows) +@imports(_from="pathlib", _import="Path") +def mozillabuild_bin_paths(mozillabuild, shell, host_is_windows): + paths = [] + if not mozillabuild or not host_is_windows: + return paths + paths.append(os.path.dirname(shell)) + paths.append(str(Path(mozillabuild[0]) / "bin")) + return paths + + +@depends(mozillabuild_bin_paths) +@imports("os") +def prefer_mozillabuild_path(mozillabuild_bin_paths): + return mozillabuild_bin_paths + os.environ["PATH"].split(os.pathsep) + + +# milestone.is_nightly corresponds to cases NIGHTLY_BUILD is set. + + +@depends(milestone) +def enabled_in_nightly(milestone): + return milestone.is_nightly + + +# Branding +# ============================================================== +option( + "--with-app-basename", + env="MOZ_APP_BASENAME", + nargs=1, + help="Typically stays consistent for multiple branded versions of a " + 'given application (e.g. Aurora and Firefox both use "Firefox"), but ' + "may vary for full rebrandings (e.g. Iceweasel). Used for " + 'application.ini\'s "Name" field, which controls profile location in ' + 'the absence of a "Profile" field (see below), and various system ' + "integration hooks (Unix remoting, Windows MessageWindow name, etc.", +) + + +@depends("--with-app-basename", target_is_android) +def moz_app_basename(value, target_is_android): + if value: + return value[0] + if target_is_android: + return "Fennec" + return "Firefox" + + +set_config( + "MOZ_APP_BASENAME", + moz_app_basename, + when=depends(build_project)(lambda p: p != "js"), +) diff --git a/build/moz.configure/java.configure b/build/moz.configure/java.configure new file mode 100644 index 0000000000..0bb0a22c71 --- /dev/null +++ b/build/moz.configure/java.configure @@ -0,0 +1,76 @@ +# -*- 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/. + + +# Java detection +# ======================================================== +option( + "--with-java-bin-path", + nargs=1, + help="Location of Java binaries", +) + + +@depends("--with-java-bin-path", host, toolchains_base_dir) +@imports(_from="mozboot.android", _import="JavaLocationFailedException") +@imports(_from="mozboot.android", _import="locate_java_bin_path") +@imports(_from="os", _import="environ") +@imports(_from="os.path", _import="dirname") +def java_search_paths(path, host, toolchains_base_dir): + if path: + # Look for javac and jar in the specified path. + return path + + try: + path = locate_java_bin_path(host.kernel, toolchains_base_dir) + + java_home = environ.get("JAVA_HOME") + if java_home and java_home != dirname(path): + log.info( + "Ignoring JAVA_HOME value. Use --with-java-bin-path " + "to override the default Java location." + ) + return [path] + except JavaLocationFailedException as e: + die(str(e)) + + +# Finds the given java tool, failing with a custom error message if we can't +# find it. + + +@template +def check_java_tool(tool): + check = check_prog( + tool.upper(), (tool,), paths=java_search_paths, allow_missing=True + ) + + @depends(check) + def require_tool(result): + if result is None: + die( + "The program %s was not found. Use '--with-java-bin-path={java-bin-dir}'" + % tool + ) + return result + + return require_tool + + +check_java_tool("java") + + +# Java Code Coverage +# ======================================================== +option( + "--enable-java-coverage", + env="MOZ_JAVA_CODE_COVERAGE", + help="Enable Java code coverage", +) + +set_config( + "MOZ_JAVA_CODE_COVERAGE", depends("--enable-java-coverage")(lambda v: bool(v)) +) diff --git a/build/moz.configure/keyfiles.configure b/build/moz.configure/keyfiles.configure new file mode 100644 index 0000000000..242a773aac --- /dev/null +++ b/build/moz.configure/keyfiles.configure @@ -0,0 +1,68 @@ +# -*- 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 keyfile(desc, default=None, help=None, callback=lambda x: x): + help = help or ( + "Use the secret key contained in the given keyfile " "for %s requests" % desc + ) + name = desc.lower().replace(" ", "-") + no_key = callback("no-%s-key" % name) + + option("--with-%s-keyfile" % name, nargs=1, default=default, help=help) + + @depends("--with-%s-keyfile" % name) + @checking("for the %s key" % desc, lambda x: x and x is not no_key) + @imports(_from="__builtin__", _import="open") + @imports(_from="__builtin__", _import="IOError") + def keyfile(value): + if value: + try: + with open(value[0]) as fh: + result = fh.read().strip() + if result: + return callback(result) + raise FatalCheckError("'%s' is empty." % value[0]) + except IOError as e: + raise FatalCheckError("'%s': %s." % (value[0], e.strerror)) + return no_key + + return keyfile + + +@template +def simple_keyfile(desc, default=None): + value = keyfile(desc, default=default) + set_config("MOZ_%s_KEY" % desc.upper().replace(" ", "_"), value) + + +@template +def id_and_secret_keyfile(desc, default=None): + def id_and_secret(value): + if value.startswith("no-") and value.endswith("-key"): + id = value[:-3] + "clientid" + secret = value + elif " " in value: + id, secret = value.split(" ", 1) + else: + raise FatalCheckError("%s key file has an invalid format." % desc) + return namespace( + id=id, + secret=secret, + ) + + content = keyfile( + desc, + help="Use the client id and secret key contained " + "in the given keyfile for %s requests" % desc, + default=default, + callback=id_and_secret, + ) + + name = desc.upper().replace(" ", "_") + set_config("MOZ_%s_CLIENTID" % name, content.id) + set_config("MOZ_%s_KEY" % name, content.secret) diff --git a/build/moz.configure/lto-pgo.configure b/build/moz.configure/lto-pgo.configure new file mode 100644 index 0000000000..ab6a527fe4 --- /dev/null +++ b/build/moz.configure/lto-pgo.configure @@ -0,0 +1,437 @@ +# -*- 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/. + +# PGO +# ============================================================== +llvm_profdata = check_prog( + "LLVM_PROFDATA", ["llvm-profdata"], allow_missing=True, paths=clang_search_path +) + + +@depends_if(llvm_profdata) +@checking("whether llvm-profdata supports 'order' subcommand") +def llvm_profdata_order(profdata): + retcode, _, _ = get_cmd_output(profdata, "order", "--help") + return retcode == 0 + + +option( + "--enable-profile-generate", + env="MOZ_PROFILE_GENERATE", + nargs="?", + choices=("cross",), + help="Build a PGO instrumented binary", +) + +imply_option("MOZ_PGO", depends_if("--enable-profile-generate")(lambda _: True)) + +set_config( + "MOZ_PROFILE_GENERATE", depends_if("--enable-profile-generate")(lambda _: True) +) + +set_define( + "MOZ_PROFILE_GENERATE", depends_if("--enable-profile-generate")(lambda _: True) +) + +add_old_configure_assignment( + "MOZ_PROFILE_GENERATE", 1, when="--enable-profile-generate" +) + +option( + "--enable-profile-use", + env="MOZ_PROFILE_USE", + nargs="?", + choices=("cross",), + help="Use a generated profile during the build", +) + +option( + "--with-pgo-profile-path", + help="Path to the directory with unmerged profile data to use during the build" + ", or to a merged profdata file", + nargs=1, +) + +imply_option("MOZ_PGO", depends_if("--enable-profile-use")(lambda _: True)) + +set_config("MOZ_PROFILE_USE", depends_if("--enable-profile-use")(lambda _: True)) + + +@depends( + "--with-pgo-profile-path", + "--enable-profile-use", + llvm_profdata, + build_environment, +) +@imports("os") +def pgo_profile_path(path, pgo_use, profdata, build_env): + topobjdir = build_env.topobjdir + if topobjdir.endswith("/js/src"): + topobjdir = topobjdir[:-7] + + if not path: + return os.path.join(topobjdir, "instrumented", "merged.profdata") + if path and not pgo_use: + die("Pass --enable-profile-use to use --with-pgo-profile-path.") + if path and not profdata: + die("LLVM_PROFDATA must be set to process the pgo profile.") + if not os.path.isfile(path[0]): + die("Argument to --with-pgo-profile-path must be a file.") + if not os.path.isabs(path[0]): + die("Argument to --with-pgo-profile-path must be an absolute path.") + return path[0] + + +set_config("PGO_PROFILE_PATH", pgo_profile_path) + + +@depends( + "--enable-profile-use", + pgo_profile_path, + llvm_profdata, + llvm_profdata_order, + build_environment, +) +def orderfile_path(profile_use, path, profdata, profdata_order, build_env): + if not profile_use: + return None + + if not profdata_order: + return None + + topobjdir = build_env.topobjdir + + orderfile = os.path.join(topobjdir, "orderfile.txt") + check_cmd_output(profdata, "order", path, "-o", orderfile) + return orderfile + + +pgo_temporal = c_compiler.try_compile( + flags=["-fprofile-generate", "-mllvm", "-pgo-temporal-instrumentation"], + check_msg="whether the C compiler supports temporal instrumentation", + when="--enable-profile-generate", +) + + +@depends( + c_compiler, + select_linker, + target, + pgo_profile_path, + orderfile_path, + target_is_windows, + pgo_temporal, +) +@imports("multiprocessing") +def pgo_flags( + compiler, linker, target, profdata, orderfile, target_is_windows, pgo_temporal +): + if compiler.type == "gcc": + return namespace( + gen_cflags=["-fprofile-generate"], + gen_ldflags=["-fprofile-generate"], + use_cflags=["-fprofile-use", "-fprofile-correction", "-Wcoverage-mismatch"], + use_ldflags=["-fprofile-use"], + ) + + if compiler.type in ("clang-cl", "clang"): + prefix = "" + if compiler.type == "clang-cl": + prefix = "/clang:" + gen_ldflags = None + else: + gen_ldflags = ["-fprofile-generate"] + + use_ldflags = [] + if orderfile: + if compiler.type == "clang-cl": + use_ldflags += ["-ORDER:@" + orderfile] + elif linker.KIND == "ld64" or (linker.KIND == "lld" and target.os == "OSX"): + use_ldflags += ["-Wl,-order_file", orderfile] + elif linker.KIND == "lld": + use_ldflags += [ + "-Wl,--symbol-ordering-file", + orderfile, + "-Wl,--no-warn-symbol-ordering", + ] + + if use_ldflags: + log.info("Activating PGO-based orderfile") + + gen_cflags = [prefix + "-fprofile-generate"] + + if pgo_temporal: + gen_cflags += ["-mllvm", "-pgo-temporal-instrumentation"] + + if target_is_windows: + # native llvm-profdata.exe on Windows can't read profile data + # if name compression is enabled (which cross-compiling enables + # by default) + gen_cflags += ["-mllvm", "-enable-name-compression=false"] + + return namespace( + gen_cflags=gen_cflags, + gen_ldflags=gen_ldflags, + use_cflags=[ + prefix + "-fprofile-use=%s" % profdata, + # Some error messages about mismatched profile data + # come in via -Wbackend-plugin, so disable those too. + "-Wno-error=backend-plugin", + ], + use_ldflags=use_ldflags, + ) + + +set_config("PROFILE_GEN_CFLAGS", pgo_flags.gen_cflags) +set_config("PROFILE_GEN_LDFLAGS", pgo_flags.gen_ldflags) +set_config("PROFILE_USE_CFLAGS", pgo_flags.use_cflags) +set_config("PROFILE_USE_LDFLAGS", pgo_flags.use_ldflags) + +option( + "--with-pgo-jarlog", + help="Use the provided jarlog file when packaging during a profile-use " "build", + nargs=1, +) + +set_config("PGO_JARLOG_PATH", depends_if("--with-pgo-jarlog")(lambda p: p)) + + +@depends("MOZ_PGO", "--enable-profile-use", "--enable-profile-generate", c_compiler) +def moz_pgo_rust(pgo, profile_use, profile_generate, c_compiler): + if not pgo: + return + + # Enabling PGO through MOZ_PGO only and not --enable* flags. + if not profile_use and not profile_generate: + return + + if profile_use and profile_generate: + die("Cannot build with --enable-profile-use and --enable-profile-generate.") + + want_cross = (len(profile_use) and profile_use[0] == "cross") or ( + len(profile_generate) and profile_generate[0] == "cross" + ) + + if not want_cross: + return + + if c_compiler.type == "gcc": + die("Cannot use cross-language PGO with GCC.") + + return True + + +set_config("MOZ_PGO_RUST", moz_pgo_rust) + +# LTO +# ============================================================== + +option( + "--enable-lto", + env="MOZ_LTO", + nargs="*", + choices=("full", "thin", "cross"), + help="Enable LTO", +) + +option( + env="MOZ_LD64_KNOWN_GOOD", + nargs=1, + help="Indicate that ld64 is free of symbol aliasing bugs.", +) + +imply_option("MOZ_LD64_KNOWN_GOOD", depends_if("MOZ_AUTOMATION")(lambda _: True)) + + +@depends( + "--enable-lto", + c_compiler, + select_linker, + "MOZ_LD64_KNOWN_GOOD", + target, + "--enable-profile-generate", + pass_manager.enabled, + "--enable-profile-use", + "MOZ_AUTOMATION", +) +@imports("multiprocessing") +def lto( + values, + c_compiler, + select_linker, + ld64_known_good, + target, + instrumented_build, + pass_manager, + pgo_build, + moz_automation, +): + cflags = [] + ldflags = [] + enabled = None + rust_lto = False + + if not values: + return + + # Sanitize LTO modes. + if "full" in values and "thin" in values: + die("incompatible --enable-lto choices 'full' and 'thin'") + + # If a value was given to --enable-lto, use that. Otherwise, make the lto + # mode explicit, using full with gcc, and full or thin with clang depending + # on the performance benefit. + # Defaulting to full LTO is costly in terms of compilation time, so we only + # default to it if MOZ_AUTOMATION and PGO are on, and for some platforms. + # Based on speedometer3 scores, full lto + pgo is beneficial for Linux and + # Windows for x86_64 targets. + if values == () or values == ("cross",): + if c_compiler.type == "gcc": + values += ("full",) + elif ( + pgo_build + and moz_automation + and target.os in ("WINNT", "GNU") + and target.cpu == "x86_64" + ): + values += ("full",) + else: + values += ("thin",) + + if instrumented_build: + log.warning("Disabling LTO because --enable-profile-generate is specified") + return + + if c_compiler.type == "gcc": + if "cross" in values: + die("Cross-language LTO is not supported with GCC.") + if "thin" in values: + die( + "gcc does not support thin LTO. Use `--enable-lto` " + "to enable full LTO for gcc." + ) + + if ( + target.kernel == "Darwin" + and target.os == "OSX" + and "cross" in values + and select_linker.KIND == "ld64" + and not ld64_known_good + ): + die( + "The Mac linker is known to have a bug that affects cross-language " + "LTO. If you know that your linker is free from this bug, please " + "set the environment variable `MOZ_LD64_KNOWN_GOOD=1` and re-run " + "configure." + ) + + if c_compiler.type == "clang": + if "full" in values: + cflags.append("-flto") + ldflags.append("-flto") + else: + cflags.append("-flto=thin") + ldflags.append("-flto=thin") + + if target.os == "Android" and "cross" in values: + # Work around https://github.com/rust-lang/rust/issues/90088 + # by enabling the highest level of SSE the rust targets default + # to. + # https://github.com/rust-lang/rust/blob/bdfcb88e8b6203ccb46a2fb6649979b773efc8ac/compiler/rustc_target/src/spec/i686_linux_android.rs#L13 + # https://github.com/rust-lang/rust/blob/8d1083e319841624f64400e1524805a40d725439/compiler/rustc_target/src/spec/x86_64_linux_android.rs#L7 + if target.cpu == "x86": + ldflags.append("-Wl,-plugin-opt=-mattr=+ssse3") + elif target.cpu == "x86_64": + ldflags.append("-Wl,-plugin-opt=-mattr=+sse4.2") + elif c_compiler.type == "clang-cl": + if "full" in values: + cflags.append("-flto") + else: + cflags.append("-flto=thin") + # With clang-cl, -flto can only be used with -c or -fuse-ld=lld. + # AC_TRY_LINKs during configure don't have -c, so pass -fuse-ld=lld. + cflags.append("-fuse-ld=lld") + + # Explicitly set the CPU to optimize for so the linker doesn't + # choose a poor default. Rust compilation by default uses the + # pentium4 CPU on x86: + # + # https://github.com/rust-lang/rust/blob/049a49b91151a88c95fa0d62a53fd0a0ac2c3af9/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs#L5 + # + # which specifically supports "long" (multi-byte) nops. See + # https://bugzilla.mozilla.org/show_bug.cgi?id=1568450#c8 for details. + # + # The pentium4 seems like kind of a weird CPU to optimize for, but + # it seems to have worked out OK thus far. LLVM does not seem to + # specifically schedule code for the pentium4's deep pipeline, so + # that probably contributes to it being an OK default for our + # purposes. + if target.cpu == "x86": + ldflags.append("-mllvm:-mcpu=pentium4") + # This is also the CPU that Rust uses. The LLVM source code + # recommends this as the "generic 64-bit specific x86 processor model": + # + # https://github.com/llvm/llvm-project/blob/e7694f34ab6a12b8bb480cbfcb396d0a64fe965f/llvm/lib/Target/X86/X86.td#L1165-L1187 + if target.cpu == "x86_64": + ldflags.append("-mllvm:-mcpu=x86-64") + # We do not need special flags for arm64. Hooray for fixed-length + # instruction sets. + else: + num_cores = multiprocessing.cpu_count() + cflags.append("-flto") + cflags.append("-flifetime-dse=1") + + ldflags.append("-flto=%s" % num_cores) + ldflags.append("-flifetime-dse=1") + + # Tell LTO not to inline functions above a certain size, to mitigate + # binary size growth while still getting good performance. + # (For hot functions, PGO will put a multiplier on this limit.) + if target.os == "WINNT": + ldflags.append("-mllvm:-import-instr-limit=10") + elif target.os == "OSX": + ldflags.append("-Wl,-mllvm,-import-instr-limit=10") + elif c_compiler.type == "clang": + ldflags.append("-Wl,-plugin-opt=-import-instr-limit=10") + + # If we're using the new pass manager, we can also enable the new PM + # during LTO. Further we can use the resulting size savings to increase + # the import limit in hot functions. + if pass_manager: + if target.os == "WINNT": + if c_compiler.version >= "12.0.0" and c_compiler.version < "13.0.0": + ldflags.append("-opt:ltonewpassmanager") + if c_compiler.version >= "12.0.0": + ldflags.append("-mllvm:-import-hot-multiplier=30") + elif target.os == "OSX": + ldflags.append("-Wl,-mllvm,-import-hot-multiplier=30") + else: + if c_compiler.version < "13.0.0": + ldflags.append("-Wl,-plugin-opt=new-pass-manager") + ldflags.append("-Wl,-plugin-opt=-import-hot-multiplier=30") + + # Pick Rust LTO mode in case of cross lTO. Thin is the default. + if "cross" in values: + rust_lto = "full" if "full" in values else "thin" + else: + rust_lto = "" + + return namespace( + enabled=True, + cflags=cflags, + ldflags=ldflags, + rust_lto=rust_lto, + ) + + +add_old_configure_assignment("MOZ_LTO", lto.enabled) +set_config("MOZ_LTO", lto.enabled) +set_define("MOZ_LTO", lto.enabled) +set_config("MOZ_LTO_CFLAGS", lto.cflags) +set_config("MOZ_LTO_LDFLAGS", lto.ldflags) +set_config("MOZ_LTO_RUST_CROSS", lto.rust_lto) +add_old_configure_assignment("MOZ_LTO_CFLAGS", lto.cflags) +add_old_configure_assignment("MOZ_LTO_LDFLAGS", lto.ldflags) diff --git a/build/moz.configure/memory.configure b/build/moz.configure/memory.configure new file mode 100644 index 0000000000..4368ad8c86 --- /dev/null +++ b/build/moz.configure/memory.configure @@ -0,0 +1,120 @@ +# -*- 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/. + + +@depends(target, js_package) +def jemalloc_default(target, js_package): + if js_package: + return False + return target.kernel in ("Darwin", "Linux", "WINNT") + + +option( + "--enable-jemalloc", + env="MOZ_MEMORY", + default=jemalloc_default, + help="{Replace|Do not replace} memory allocator with jemalloc", +) + + +set_config("MOZ_MEMORY", True, when="--enable-jemalloc") +set_define("MOZ_MEMORY", True, when="--enable-jemalloc") +add_old_configure_assignment("MOZ_MEMORY", True, when="--enable-jemalloc") + + +@depends(milestone, build_project) +def replace_malloc_default(milestone, build_project): + if build_project == "memory": + return True + if milestone.is_early_beta_or_earlier and build_project != "js": + return True + + +option( + "--enable-replace-malloc", + default=replace_malloc_default, + when="--enable-jemalloc", + help="{Enable|Disable} ability to dynamically replace the malloc implementation", +) + + +set_config("MOZ_REPLACE_MALLOC", True, when="--enable-replace-malloc") +set_define("MOZ_REPLACE_MALLOC", True, when="--enable-replace-malloc") + + +@depends(build_project, when="--enable-replace-malloc") +def replace_malloc_static(build_project): + # Default to statically linking replace-malloc libraries that can be + # statically linked, except when building with --enable-project=memory. + if build_project != "memory": + return True + + +set_config("MOZ_REPLACE_MALLOC_STATIC", replace_malloc_static) + +# PHC (Probabilistic Heap Checker) +# ============================================================== + + +# In general, it only makes sense for PHC to run on the platforms that have a +# crash reporter. +@depends( + build_project, + target, + when="--enable-jemalloc", +) +def phc_default(build_project, target): + if build_project == "js": + return False + + # Both Linux32 and Win32 have frequent crashes when stack tracing (for + # unclear reasons), so PHC is enabled only on 64-bit only in both cases. + return (target.cpu in ("x86_64", "aarch64")) and ( + (target.os == "GNU" and target.kernel == "Linux") + or (target.kernel == "WINNT") + or (target.os == "OSX") + ) + + +option( + "--enable-phc", + env="MOZ_PHC", + default=phc_default, + when="--enable-jemalloc", + help="{Enable|Disable} PHC (Probabilistic Memory Checker). " + "Also enables frame pointers when needed", +) + +set_config("MOZ_PHC", True, when="--enable-phc") + + +# PHC parses stacks using frame pointers on these systems. +@depends("--enable-phc", target, have_unwind, when="--enable-jemalloc") +def phc_implies_frame_pointers(phc, target, have_unwind): + if not phc: + return False + + # This should be kept in sync with the ifdefs in memory/build/PHC.cpp + # that control stack walking. + # This is true for the first two options in PHC.cpp + if (target.os == "WINNT" and target.cpu == "x86") or target.kernel == "Darwin": + return True + + # This should match the #defines in mozglue/misc/StackWalk.cpp + if (target.cpu in ("x86", "ppc")) and (target.kernel in ("Darwin", "Linux")): + return not have_unwind + + return False + + +imply_option("--enable-frame-pointers", True, when=phc_implies_frame_pointers) + + +with only_when(depends(target.os)(lambda os: os != "WINNT")): + set_define("HAVE_STRNDUP", check_symbol("strndup")) + set_define("HAVE_POSIX_MEMALIGN", check_symbol("posix_memalign")) + set_define("HAVE_MEMALIGN", check_symbol("memalign")) + set_define("HAVE_MALLOC_USABLE_SIZE", check_symbol("malloc_usable_size")) diff --git a/build/moz.configure/node.configure b/build/moz.configure/node.configure new file mode 100644 index 0000000000..66668e7861 --- /dev/null +++ b/build/moz.configure/node.configure @@ -0,0 +1,90 @@ +# -*- 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/. + +option("--disable-nodejs", help="Require Node.js to build") +option(env="NODEJS", nargs=1, help="Path to nodejs") + + +@depends( + "--enable-nodejs", + "NODEJS", + bootstrap_search_path("node", when=depends("NODEJS")(lambda x: not x)), + host, +) +@checking( + "for nodejs", callback=lambda x: "%s (%s)" % (x.path, x.str_version) if x else "no" +) +@imports(_from="mozbuild.nodeutil", _import="find_node_executable") +@imports(_from="mozbuild.nodeutil", _import="NODE_MIN_VERSION") +@imports(_from="__builtin__", _import="OSError") +@imports("errno") +def nodejs(require, env_node, search_path, host): + # We don't use the dependency directly, but having it ensures the + # auto-upgrade code in bootstrap_search_path is triggered, while + # find_node_executable will use more or less the same search path. + # We do however need to use the variable for the configure lint + # not to fail. + search_path + + node_exe = env_node[0] if env_node else None + + try: + nodejs, version = find_node_executable(node_exe) + except OSError as e: + if host.cpu == "aarch64" and host.os == "OSX" and e.errno == errno.EBADARCH: + # Ideally we'd do it when --enable-bootstrap is set, but when we're wrapped in + # mach build or mach configure, running the command doesn't print anything and + # waits on input (for license agreement) that it can't actually get. + # mach bootstrap should have taken care of it anyways, but in case it hasn't, + # it's simpler to ask to run the rosetta install than the whole mach bootstrap. + die( + "Rosetta is needed to run node. Please run `softwareupdate --install-rosetta`" + ) + raise + + MAYBE_FILE_A_BUG = """ + + Executing `mach bootstrap --no-system-changes` should + install a compatible version in ~/.mozbuild on most platforms. + If you believe this is a bug, <https://mzl.la/2vLbXAv> is a good way + to file. More details: <https://bit.ly/2BbyD1E> + """ + + if not nodejs: + msg = ( + "could not find Node.js executable later than %s; ensure " + "`node` or `nodejs` is in PATH or set NODEJS in environment " + "to point to an executable.%s" % (NODE_MIN_VERSION, MAYBE_FILE_A_BUG) + ) + + if require: + raise FatalCheckError(msg) + else: + log.warning(msg) + log.warning("(This will become an error in the near future.)") + return + + if not version: + msg = "NODEJS must point to node %s or newer; found node location: %s. %s" % ( + NODE_MIN_VERSION, + nodejs, + MAYBE_FILE_A_BUG, + ) + + if require: + raise FatalCheckError(msg) + else: + log.warning(msg) + return + + return namespace( + path=nodejs, + version=version, + str_version=".".join(str(v) for v in version), + ) + + +set_config("NODEJS", depends_if(nodejs)(lambda p: p.path)) diff --git a/build/moz.configure/nspr.configure b/build/moz.configure/nspr.configure new file mode 100644 index 0000000000..182a508b73 --- /dev/null +++ b/build/moz.configure/nspr.configure @@ -0,0 +1,116 @@ +# -*- 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/. + +# Top-level configure defaults to building NSPR from source. Standalone JS +# doesn't. +option( + "--enable-nspr-build", + when=js_standalone, + help="{Build|Do not build} NSPR from source tree", +) + + +@depends("--enable-nspr-build", when=js_standalone) +def enable_nspr_build(enable): + if enable: + return enable + + +system_lib_option("--with-system-nspr", help="Use system NSPR") + + +@depends(enable_nspr_build, "--with-system-nspr", js_standalone) +def build_nspr(nspr_build, system_nspr, js_standalone): + if nspr_build is not None and nspr_build.origin != "default": + if nspr_build and system_nspr: + die("Cannot use both --enable-nspr-build and --with-system-nspr") + if js_standalone: + return nspr_build + return not system_nspr + + +set_config("MOZ_BUILD_NSPR", True, when=build_nspr) +set_config("MOZ_SYSTEM_NSPR", True, when="--with-system-nspr") + + +@depends(build_nspr, "--with-system-nspr", js_standalone) +def js_without_nspr(build_nspr, system_nspr, js_standalone): + if js_standalone: + return not build_nspr and not system_nspr + + +set_config("JS_WITHOUT_NSPR", True, when=js_without_nspr) +set_define("JS_WITHOUT_NSPR", True, when=js_without_nspr) + + +@depends(js_standalone) +def nspr_minver(js_standalone): + if js_standalone: + return "nspr >= 4.10" + return "nspr >= 4.32" + + +nspr_pkg = pkg_check_modules("NSPR", nspr_minver, when="--with-system-nspr") + + +@depends_if(nspr_pkg) +def nspr_pkg(nspr_pkg): + def extract(prefix, list): + for item in list: + if item.startswith(prefix): + return item[len(prefix) :] + return "" + + include_dir = extract("-I", nspr_pkg.cflags) + lib_dir = extract("-L", nspr_pkg.libs) + return namespace( + cflags=nspr_pkg.cflags, + include_dir=include_dir, + libs=nspr_pkg.libs, + lib_dir=lib_dir, + ) + + +@depends("--with-system-nspr", nspr_minver) +def pkgconf_requires_private(system_nspr, nspr_minver): + if not system_nspr: + return "" + return "Requires.private: %s" % nspr_minver + + +set_config("PKGCONF_REQUIRES_PRIVATE", pkgconf_requires_private) + + +# pkg_check_modules takes care of NSPR_CFLAGS and NSPR_LIBS when using --with-system-nspr. +@depends(build_environment, c_compiler, fold_libs, when=build_nspr) +def nspr_config(build_env, c_compiler, fold_libs): + libs = ["nspr4", "plc4", "plds4"] + if c_compiler.type == "clang-cl": + lib_dir = os.path.join(build_env.dist, "lib") + libs = [os.path.join(lib_dir, "%s.lib" % lib) for lib in libs] + else: + lib_dir = os.path.join(build_env.dist, "lib" if fold_libs else "bin") + libs = ["-L%s" % lib_dir] + ["-l%s" % lib for lib in libs] + + include_dir = os.path.join(build_env.dist, "include", "nspr") + return namespace( + cflags=["-I%s" % include_dir], + include_dir=include_dir, + libs=libs, + lib_dir=lib_dir, + ) + + +set_config("NSPR_CFLAGS", nspr_config.cflags, when=nspr_config) +set_config("NSPR_LIBS", nspr_config.libs, when=nspr_config) + +set_config("NSPR_INCLUDE_DIR", nspr_config.include_dir, when=nspr_config) +set_config("NSPR_LIB_DIR", nspr_config.lib_dir, when=nspr_config) +set_config("NSPR_INCLUDE_DIR", nspr_pkg.include_dir, when=nspr_pkg) +set_config("NSPR_LIB_DIR", nspr_pkg.lib_dir, when=nspr_pkg) + +add_old_configure_assignment("NSPR_LIBS", nspr_config.libs, when=nspr_config) +add_old_configure_assignment("NSPR_LIBS", nspr_pkg.libs, when=nspr_pkg) diff --git a/build/moz.configure/nss.configure b/build/moz.configure/nss.configure new file mode 100644 index 0000000000..9e4802774a --- /dev/null +++ b/build/moz.configure/nss.configure @@ -0,0 +1,29 @@ +# -*- 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/. + +system_lib_option("--with-system-nss", help="Use system NSS") + +imply_option("--with-system-nspr", True, when="--with-system-nss") + +nss_pkg = pkg_check_modules( + "NSS", "nss >= 3.98", when="--with-system-nss", config=False +) + +set_config("MOZ_SYSTEM_NSS", True, when="--with-system-nss") + + +@depends(nss_pkg, build_environment) +def nss_config(nss_pkg, build_env): + cflags = ["-I%s" % os.path.join(build_env.dist, "include", "nss")] + libs = None + if nss_pkg: + cflags = list(nss_pkg.cflags) + cflags + libs = nss_pkg.libs + return namespace(cflags=cflags, libs=libs) + + +set_config("NSS_CFLAGS", nss_config.cflags) +set_config("NSS_LIBS", nss_config.libs) diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure new file mode 100644 index 0000000000..a37fd265a2 --- /dev/null +++ b/build/moz.configure/old.configure @@ -0,0 +1,394 @@ +# -*- 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/. + + +m4 = check_prog( + "M4", + ( + "gm4", + "m4", + ), + paths=prefer_mozillabuild_path, +) + + +@depends(mozconfig) +def prepare_mozconfig(mozconfig): + if mozconfig["path"]: + items = {} + for key, value in mozconfig["vars"]["added"].items(): + items[key] = (value, "added") + for key, (old, value) in mozconfig["vars"]["modified"].items(): + items[key] = (value, "modified") + for t in ("env", "vars"): + for key in mozconfig[t]["removed"].keys(): + items[key] = (None, "removed " + t) + return items + + +@depends("OLD_CONFIGURE", build_project) +def old_configure(old_configure, build_project): + if not old_configure: + die("The OLD_CONFIGURE environment variable must be set") + + # os.path.abspath in the sandbox will ensure forward slashes on Windows, + # which is actually necessary because this path actually ends up literally + # as $0, and backslashes there breaks autoconf's detection of the source + # directory. + old_configure = os.path.abspath(old_configure[0]) + if build_project == "js": + old_configure_dir = os.path.dirname(old_configure) + if not old_configure_dir.endswith("/js/src"): + old_configure = os.path.join( + old_configure_dir, "js", "src", os.path.basename(old_configure) + ) + return old_configure + + +@depends(prepare_mozconfig, old_configure_assignments) +@imports(_from="__builtin__", _import="open") +@imports(_from="__builtin__", _import="print") +@imports(_from="mozbuild.shellutil", _import="quote") +def prepare_configure(mozconfig, old_configure_assignments): + assignments = {} + + with open("old-configure.vars", "w") as out: + log.debug("Injecting the following to old-configure:") + + def inject(command): + print(command, file=out) # noqa Python 2vs3 + log.debug("| %s", command) + + if mozconfig: + inject("# start of mozconfig values") + for key, (value, action) in sorted(mozconfig.items()): + if action.startswith("removed "): + inject("unset %s # from %s" % (key, action[len("removed ") :])) + else: + inject("%s=%s # %s" % (key, quote(value), action)) + assignments[key] = value + + inject("# end of mozconfig values") + + for k, v in old_configure_assignments: + inject("%s=%s" % (k, quote(v))) + assignments[k] = v + + return namespace(assignments=assignments) + + +@template +def old_configure_options(*options): + for opt in options: + option(opt, nargs="*", help="Help missing for old configure options") + + @dependable + def all_options(): + return list(options) + + return depends( + host_for_sub_configure, target_for_sub_configure, all_options, *options + ) + + +@old_configure_options( + "--cache-file", + "--datadir", + "--enable-official-branding", + "--includedir", + "--libdir", + "--prefix", + "--with-branding", + "--with-distribution-id", + "--with-macbundlename-prefix", + "--x-includes", + "--x-libraries", +) +def prepare_configure_options(host, target, all_options, *options): + # old-configure only supports the options listed in @old_configure_options + # so we don't need to pass it every single option we've been passed. Only + # the ones that are not supported by python configure need to. + options = [ + value.format(name) + for name, value in zip(all_options, options) + if value.origin != "default" + ] + [host, target] + + return namespace(options=options, all_options=all_options) + + +@template +def old_configure_for(old_configure_path, extra_env=None): + if extra_env is None: + extra_env = dependable(None) + + @depends( + prepare_configure, + prepare_configure_options, + prefer_mozillabuild_path, + altered_path, + extra_env, + build_environment, + old_configure_path, + awk, + m4, + shell, + "--cache-file", + ) + @imports(_from="__builtin__", _import="compile") + @imports(_from="__builtin__", _import="open") + @imports(_from="__builtin__", _import="OSError") + @imports("glob") + @imports("itertools") + @imports("logging") + @imports("os") + @imports("re") + @imports("subprocess") + @imports("sys") + @imports(_from="mozbuild.shellutil", _import="quote") + @imports(_from="mozbuild.shellutil", _import="split") + @imports(_from="tempfile", _import="NamedTemporaryFile") + @imports(_from="subprocess", _import="CalledProcessError") + @imports(_from="__builtin__", _import="exec") + def old_configure( + prepare_configure, + prepare_configure_options, + prefer_mozillabuild_path, + altered_path, + extra_env, + build_env, + old_configure, + awk, + m4, + shell, + cache_file_option, + ): + if altered_path: + path = altered_path + else: + path = os.pathsep.join(prefer_mozillabuild_path) + + cxx = prepare_configure.assignments.get("CXX") + cc = prepare_configure.assignments.get("CC") + + if cc and cxx: + if cache_file_option: + config_cache = cache_file_option[0] + else: + config_cache = "config.cache" + + if os.path.exists(config_cache): + remove = False + with open(config_cache, "r") as cfg_cache: + cxx_pattern = re.compile( + r"^ac_cv_prog_CXX=\${ac_cv_prog_CXX='(.*)'}$" + ) + cc_pattern = re.compile(r"^ac_cv_prog_CC=\${ac_cv_prog_CC='(.*)'}$") + for line in cfg_cache: + m = cc_pattern.match(line) + if m and m.group(1) != cc: + remove = True + break + m = cxx_pattern.match(line) + if m and m.group(1) != cxx: + remove = True + break + + if remove: + log.info("invalidating config.cache") + os.remove(config_cache) + + refresh = True + if os.path.exists(old_configure): + mtime = os.path.getmtime(old_configure) + aclocal = os.path.join(build_env.topsrcdir, "build", "autoconf", "*.m4") + for input in itertools.chain( + ( + old_configure + ".in", + os.path.join(os.path.dirname(old_configure), "aclocal.m4"), + ), + glob.iglob(aclocal), + ): + if os.path.getmtime(input) > mtime: + break + else: + refresh = False + + if refresh: + autoconf = os.path.join( + build_env.topsrcdir, "build", "autoconf", "autoconf.sh" + ) + log.info("Refreshing %s with %s", old_configure, autoconf) + env = dict(os.environ) + env["M4"] = m4 + env["AWK"] = awk + env["AC_MACRODIR"] = os.path.join(build_env.topsrcdir, "build", "autoconf") + env["PATH"] = path + + try: + script = subprocess.check_output( + [ + shell, + autoconf, + "--localdir=%s" % os.path.dirname(old_configure), + old_configure + ".in", + ], + # Fix the working directory, so that when m4 is called, that + # includes of relative paths are deterministically resolved + # relative to the directory containing old-configure. + cwd=os.path.dirname(old_configure), + env=env, + ) + except CalledProcessError as exc: + die("autoconf exited with return code {}".format(exc.returncode)) + + if not script: + die( + "Generated old-configure is empty! Check that your autoconf 2.13 program works!" + ) + + # Make old-configure append to config.log, where we put our own log. + # This could be done with a m4 macro, but it's way easier this way + script = script.replace(b">./config.log", b">>${CONFIG_LOG=./config.log}") + + with NamedTemporaryFile( + mode="wb", + prefix=os.path.basename(old_configure), + dir=os.path.dirname(old_configure), + delete=False, + ) as fh: + fh.write(script) + + try: + os.rename(fh.name, old_configure) + except OSError: + try: + # Likely the file already existed (on Windows). Retry after removing it. + os.remove(old_configure) + os.rename(fh.name, old_configure) + except OSError as e: + die("Failed re-creating old-configure: %s" % e.message) + + cmd = [shell, old_configure] + prepare_configure_options.options + + env = dict(os.environ) + + # For debugging purpose, in case it's not what we'd expect. + log.debug("Running %s", quote(*cmd)) + + # Our logging goes to config.log, the same file old.configure uses. + # We can't share the handle on the file, so close it. + logger = logging.getLogger("moz.configure") + config_log = None + for handler in logger.handlers: + if isinstance(handler, logging.FileHandler): + config_log = handler + config_log.close() + logger.removeHandler(config_log) + env["CONFIG_LOG"] = config_log.baseFilename + log_size = os.path.getsize(config_log.baseFilename) + break + + env["PATH"] = path + + if extra_env: + env.update(extra_env) + + env["OLD_CONFIGURE_VARS"] = os.path.join( + build_env.topobjdir, "old-configure.vars" + ) + proc = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env + ) + while True: + line = proc.stdout.readline() + if not line: + break + log.info(line.rstrip()) + + ret = proc.wait() + if ret: + with log.queue_debug(): + if config_log: + with open(config_log.baseFilename, "r") as fh: + fh.seek(log_size) + for line in fh: + log.debug(line.rstrip()) + log.error("old-configure failed") + sys.exit(ret) + + if config_log: + # Create a new handler in append mode + handler = logging.FileHandler(config_log.baseFilename, mode="a", delay=True) + handler.setFormatter(config_log.formatter) + logger.addHandler(handler) + + raw_config = { + "split": split, + "unique_list": unique_list, + } + with open("config.data", "r") as fh: + code = compile(fh.read(), "config.data", "exec") + exec(code, raw_config) + + # Ensure all the flags known to old-configure appear in the + # @old_configure_options above. + all_options = set(prepare_configure_options.all_options) + for flag in raw_config["flags"]: + if flag not in all_options: + die( + "Missing option in `@old_configure_options` in %s: %s", + __file__, + flag, + ) + + # If the code execution above fails, we want to keep the file around for + # debugging. + os.remove("config.data") + + return namespace( + **{ + c: [ + (k[1:-1], v[1:-1] if isinstance(v, str) else v) + for k, v in raw_config[c] + # Eventually we'll want to filter out all lowercase keys. (bug 1869127) + # For now, we only filter out the most problematic one that + # we know is unused. + if k != " target_cpu " + ] + for c in ("substs", "defines") + } + ) + + return old_configure + + +old_configure = old_configure_for(old_configure) +set_config("OLD_CONFIGURE_SUBSTS", old_configure.substs) +set_config("OLD_CONFIGURE_DEFINES", old_configure.defines) + + +# Assuming no other option is declared after this function, handle the +# env options that were injected by mozconfig_options by creating dummy +# Option instances and having the sandbox's CommandLineHelper handle +# them. We only do so for options that haven't been declared so far, +# which should be a proxy for the options that old-configure handles +# and that we don't know anything about. +@depends("--help") +@imports("__sandbox__") +@imports(_from="mozbuild.configure.options", _import="Option") +def remaining_mozconfig_options(_): + helper = __sandbox__._helper + for arg in list(helper): + if helper._origins[arg] != "mozconfig": + continue + name = arg.split("=", 1)[0] + if name.isupper() and name not in __sandbox__._options: + option = Option(env=name, nargs="*", help=name) + helper.handle(option) + + +# Please do not add anything after remaining_mozconfig_options() diff --git a/build/moz.configure/pkg.configure b/build/moz.configure/pkg.configure new file mode 100644 index 0000000000..6beed205f1 --- /dev/null +++ b/build/moz.configure/pkg.configure @@ -0,0 +1,210 @@ +# -*- 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/. + + +@depends(toolchain_prefix, when=compile_environment) +def pkg_config(prefixes): + return tuple("{}pkg-config".format(p) for p in (prefixes or ()) + ("",)) + + +pkg_config = check_prog( + "PKG_CONFIG", + pkg_config, + bootstrap=depends(when=target_sysroot.bootstrapped)(lambda: "pkgconf"), + allow_missing=True, + when=compile_environment + & depends(target.os)(lambda os: os not in ("WINNT", "OSX", "Android")), +) + + +@depends_if(pkg_config) +@checking("for pkg-config version") +def pkg_config_version(pkg_config): + return Version(check_cmd_output(pkg_config, "--version").rstrip()) + + +@depends_if(pkg_config) +@checking("whether pkg-config is pkgconf") +def is_pkgconf(pkg_config): + return "pkgconf " in check_cmd_output(pkg_config, "--about", onerror=lambda: "") + + +@depends(is_pkgconf, pkg_config_version, target_sysroot.bootstrapped, when=pkg_config) +def pkg_config_base_flags(is_pkgconf, pkg_config_version, target_sysroot_bootstrapped): + # pkgconf 1.7.4 changed the default on Windows to use --static, but + # that doesn't work for us. + # Note: the --shared flag is not available before pkgconf 1.7 + flags = [] + if is_pkgconf and pkg_config_version >= "1.7.4": + flags.append("--shared") + # When pkg-config is in /usr things work fine by default, but when + # it is not, it defines prefix to be something else than /usr, which + # won't match what the .pc files actually say, and won't work in + # sysroots. + if target_sysroot_bootstrapped and ( + (is_pkgconf and pkg_config_version >= "1.2.0") + or (not is_pkgconf and pkg_config_version >= "0.29.0") + ): + flags.append("--dont-define-prefix") + return tuple(flags) + + +@depends(target, target_sysroot.path, target_multiarch_dir, when=pkg_config) +@imports(_from="os", _import="environ") +@imports(_from="os", _import="pathsep") +def pkg_config_vars(target, sysroot_path, multiarch_dir): + if sysroot_path and target.kernel != "Darwin": + pkgconfig_dirs = [ + "usr/lib/pkgconfig", + "usr/lib/{}/pkgconfig".format(multiarch_dir), + "usr/share/pkgconfig", + ] + if target.bitness == 64: + pkgconfig_dirs.insert(0, "usr/lib64/pkgconfig") + return namespace( + PKG_CONFIG_PATH="", + PKG_CONFIG_SYSROOT_DIR=sysroot_path, + PKG_CONFIG_LIBDIR=pathsep.join( + os.path.join(sysroot_path, d) for d in pkgconfig_dirs + ), + ) + + +@depends(pkg_config_vars) +@imports(_from="os", _import="environ") +def pkg_config_env(vars): + if vars: + env = dict(environ) + env["PKG_CONFIG_PATH"] = vars.PKG_CONFIG_PATH + env["PKG_CONFIG_SYSROOT_DIR"] = vars.PKG_CONFIG_SYSROOT_DIR + env["PKG_CONFIG_LIBDIR"] = vars.PKG_CONFIG_LIBDIR + return env + + +set_config("PKG_CONFIG_PATH", pkg_config_vars.PKG_CONFIG_PATH) +set_config("PKG_CONFIG_SYSROOT_DIR", pkg_config_vars.PKG_CONFIG_SYSROOT_DIR) +set_config("PKG_CONFIG_LIBDIR", pkg_config_vars.PKG_CONFIG_LIBDIR) + + +# Locates the given module using pkg-config. +# - `var` determines the name of variables to set when the package is found. +# <var>_CFLAGS and <var>_LIBS are set with corresponding values. +# - `package_desc` package name and version requirement string, list of +# strings describing packages to locate, or depends function that will +# resolve to such a string or list of strings. +# - `when` a depends function that will determine whether to perform +# any checks (default is to always perform checks). +# - `allow_missing` If set, failure to fulfill the package description +# will not result in an error or logged message, and any error message +# will be returned to the caller. +# Returns `True` when the package description is fulfilled. +@template +def pkg_check_modules( + var, package_desc, when=always, allow_missing=False, config=True, cflags_only=False +): + @depends(dependable(package_desc), when=when) + def package_desc(desc): + if isinstance(desc, str): + desc = [desc] + if not isinstance(desc, (tuple, list)): + configure_error( + "package_desc must be a string or a tuple or list of strings" + ) + + return " ".join(desc) + + allow_missing = dependable(allow_missing) + + @depends(when, "--enable-compile-environment") + def when_and_compile_environment(when, compile_environment): + return when and compile_environment + + @depends(pkg_config, pkg_config_version, when=when_and_compile_environment) + def check_pkg_config(pkg_config, version): + min_version = "0.9.0" + if pkg_config is None: + die( + "*** The pkg-config script could not be found. Make sure it is\n" + "*** in your path, or set the PKG_CONFIG environment variable\n" + "*** to the full path to pkg-config." + ) + if version < min_version: + die( + "*** Your version of pkg-config is too old. You need version %s or newer.", + min_version, + ) + + @depends( + pkg_config, + pkg_config_env, + package_desc, + allow_missing, + when=when_and_compile_environment, + ) + @imports("sys") + @imports(_from="mozbuild.configure.util", _import="LineIO") + def package(pkg_config, env, package_desc, allow_missing): + # package_desc may start as a depends function, so we can't use + # @checking here. + log.info("checking for %s... " % package_desc) + retcode, stdout, stderr = get_cmd_output( + pkg_config, + "--errors-to-stdout", + "--print-errors", + package_desc, + env=env, + ) + if retcode == 0: + log.info("yes") + return True + log.info("no") + log_writer = log.warning if allow_missing else log.error + with LineIO(lambda l: log_writer(l)) as o: + o.write(stdout) + if not allow_missing: + sys.exit(1) + + @depends( + pkg_config, pkg_config_env, package_desc, pkg_config_base_flags, when=package + ) + @checking("%s_CFLAGS" % var, callback=lambda t: " ".join(t)) + def pkg_cflags(pkg_config, env, package_desc, base_flags): + args = list(base_flags) + ["--cflags", package_desc] + flags = check_cmd_output(pkg_config, *args, env=env) + return tuple(flags.split()) + + if cflags_only: + + @depends(pkg_cflags, when=package) + def pkg_info(cflags): + return namespace(cflags=cflags) + + else: + + @depends( + pkg_config, + pkg_config_env, + package_desc, + pkg_config_base_flags, + when=package, + ) + @checking("%s_LIBS" % var, callback=lambda t: " ".join(t)) + def pkg_libs(pkg_config, env, package_desc, base_flags): + args = list(base_flags) + ["--libs", package_desc] + libs = check_cmd_output(pkg_config, *args, env=env) + # Remove evil flags like -Wl,--export-dynamic + return tuple(libs.replace("-Wl,--export-dynamic", "").split()) + + @depends(pkg_cflags, pkg_libs, when=package) + def pkg_info(cflags, libs): + return namespace(cflags=cflags, libs=libs) + + if config: + set_config("%s_CFLAGS" % var, pkg_cflags) + if not cflags_only: + set_config("%s_LIBS" % var, pkg_libs) + + return pkg_info diff --git a/build/moz.configure/rust.configure b/build/moz.configure/rust.configure new file mode 100644 index 0000000000..7a2fd1ae70 --- /dev/null +++ b/build/moz.configure/rust.configure @@ -0,0 +1,786 @@ +# -*- 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/. + + +# Rust is required by `rust_compiler` below. We allow_missing here +# to propagate failures to the better error message there. +option(env="RUSTC", nargs=1, help="Path to the rust compiler") +option(env="CARGO", nargs=1, help="Path to the Cargo package manager") + +rustc = check_prog( + "_RUSTC", + ["rustc"], + what="rustc", + paths=rust_search_path, + input="RUSTC", + allow_missing=True, +) +cargo = check_prog( + "_CARGO", + ["cargo"], + what="cargo", + paths=rust_search_path, + input="CARGO", + allow_missing=True, +) + + +@template +def unwrap_rustup(prog, name): + # rustc and cargo can either be rustup wrappers, or they can be the actual, + # plain executables. For cargo, on OSX, rustup sets DYLD_LIBRARY_PATH (at + # least until https://github.com/rust-lang/rustup.rs/pull/1752 is merged + # and shipped) and that can wreak havoc (see bug 1536486). Similarly, for + # rustc, rustup silently honors toolchain overrides set by vendored crates + # (see bug 1547196). + # + # In either case, we need to find the plain executables. + # + # To achieve that, try to run `PROG +stable`. When the rustup wrapper is in + # use, it either prints PROG's help and exits with status 0, or prints + # an error message (error: toolchain 'stable' is not installed) and exits + # with status 1. In the cargo case, when plain cargo is in use, it exits + # with a different error message (e.g. "error: no such subcommand: + # `+stable`"), and exits with status 101. + # + # Unfortunately, in the rustc case, when plain rustc is in use, + # `rustc +stable` will exit with status 1, complaining about a missing + # "+stable" file. We'll examine the error output to try and distinguish + # between failing rustup and failing rustc. + @depends(prog, dependable(name)) + @imports(_from="__builtin__", _import="open") + @imports("os") + def unwrap(prog, name): + if not prog: + return + + def from_rustup_which(): + out = check_cmd_output("rustup", "which", name, executable=prog).rstrip() + # If for some reason the above failed to return something, keep the + # PROG we found originally. + if out: + log.info("Actually using '%s'", out) + return out + + log.info("No `rustup which` output, using '%s'", prog) + return prog + + (retcode, stdout, stderr) = get_cmd_output(prog, "+stable") + + if name == "cargo" and retcode != 101: + prog = from_rustup_which() + elif name == "rustc": + if retcode == 0: + prog = from_rustup_which() + elif "+stable" in stderr: + # PROG looks like plain `rustc`. + pass + else: + # Assume PROG looks like `rustup`. This case is a little weird, + # insofar as the user doesn't have the "stable" toolchain + # installed, but go ahead and unwrap anyway: the user might + # have only certain versions, beta, or nightly installed, and + # we'll catch invalid versions later. + prog = from_rustup_which() + + return normalize_path(prog) + + return unwrap + + +rustc = unwrap_rustup(rustc, "rustc") +cargo = unwrap_rustup(cargo, "cargo") + + +set_config("CARGO", cargo) +set_config("RUSTC", rustc) + + +@depends_if(rustc) +@checking("rustc version", lambda info: info.version) +def rustc_info(rustc): + if not rustc: + return + out = check_cmd_output(rustc, "--version", "--verbose").splitlines() + info = dict((s.strip() for s in line.split(":", 1)) for line in out[1:]) + return namespace( + version=Version(info.get("release", "0")), + commit=info.get("commit-hash", "unknown"), + host=info["host"], + llvm_version=Version(info.get("LLVM version", "0")), + ) + + +set_config( + "RUSTC_VERSION", + depends(rustc_info)(lambda info: str(info.version) if info else None), +) + + +set_config( + "RUSTC_LLVM_VERSION", + depends(rustc_info)(lambda info: str(info.llvm_version) if info else None), +) + +set_config( + "MOZ_CLANG_NEWER_THAN_RUSTC_LLVM", + depends(c_compiler, rustc_info)( + lambda c_compiler, rustc_info: rustc_info + and c_compiler.type == "clang" + and c_compiler.version.major > rustc_info.llvm_version.major + ), +) + + +@depends_if(cargo) +@checking("cargo version", lambda info: info.version) +@imports("re") +def cargo_info(cargo): + if not cargo: + return + out = check_cmd_output(cargo, "--version", "--verbose").splitlines() + info = dict((s.strip() for s in line.split(":", 1)) for line in out[1:]) + version = info.get("release") + # Older versions of cargo didn't support --verbose, in which case, they + # only output a not-really-pleasant-to-parse output. Fortunately, they + # don't error out, so we can just try some regexp matching on the output + # we already got. + if version is None: + VERSION_FORMAT = r"^cargo (\d\.\d+\.\d+).*" + + m = re.search(VERSION_FORMAT, out[0]) + # Fail fast if cargo changes its output on us. + if not m: + die("Could not determine cargo version from output: %s", out) + version = m.group(1) + + return namespace( + version=Version(version), + ) + + +@depends(rustc_info, cargo_info, target) +@imports(_from="mozboot.util", _import="MINIMUM_RUST_VERSION") +@imports(_from="textwrap", _import="dedent") +def rust_compiler(rustc_info, cargo_info, target): + if not rustc_info: + die( + dedent( + """\ + Rust compiler not found. + To compile rust language sources, you must have 'rustc' in your path. + See https://www.rust-lang.org/ for more information. + + You can install rust by running './mach bootstrap' + or by directly running the installer from https://rustup.rs/ + """ + ) + ) + rustc_min_version = Version(MINIMUM_RUST_VERSION) + cargo_min_version = rustc_min_version + + version = rustc_info.version + is_nightly = "nightly" in version.version + is_version_number_match = ( + version.major == rustc_min_version.major + and version.minor == rustc_min_version.minor + and version.patch == rustc_min_version.patch + ) + + if version < rustc_min_version or (is_version_number_match and is_nightly): + die( + dedent( + """\ + Rust compiler {} is too old. + + To compile Rust language sources please install at least + version {} of the 'rustc' toolchain (or, if using nightly, + at least one version newer than {}) and make sure it is + first in your path. + + You can verify this by typing 'rustc --version'. + + If you have the 'rustup' tool installed you can upgrade + to the latest release by typing 'rustup update'. The + installer is available from https://rustup.rs/ + """.format( + version, rustc_min_version, rustc_min_version + ) + ) + ) + + if target.kernel == "WINNT" and (version.major, version.minor) == (1, 56): + die( + dedent( + """\ + Rust compiler 1.56.* is not supported for Windows builds. + + Use a newer or an older version. + + See https://github.com/rust-lang/rust/issues/88576. + """ + ) + ) + + if not cargo_info: + die( + dedent( + """\ + Cargo package manager not found. + To compile Rust language sources, you must have 'cargo' in your path. + See https://www.rust-lang.org/ for more information. + + You can install cargo by running './mach bootstrap' + or by directly running the installer from https://rustup.rs/ + """ + ) + ) + + version = cargo_info.version + if version < cargo_min_version: + die( + dedent( + """\ + Cargo package manager {} is too old. + + To compile Rust language sources please install at least + version {} of 'cargo' and make sure it is first in your path. + + You can verify this by typing 'cargo --version'. + """ + ).format(version, cargo_min_version) + ) + + return True + + +@depends(rustc, when=rust_compiler) +@imports(_from="__builtin__", _import="ValueError") +def rust_supported_targets(rustc): + out = check_cmd_output(rustc, "--print", "target-list").splitlines() + data = {} + for t in out: + try: + info = split_triplet(t, allow_wasi=True) + except ValueError: + if t.startswith("thumb"): + cpu, rest = t.split("-", 1) + retry = "-".join(("arm", rest)) + else: + continue + try: + info = split_triplet(retry, allow_wasi=True) + except ValueError: + continue + key = (info.cpu, info.endianness, info.os) + data.setdefault(key, []).append(namespace(rust_target=t, target=info)) + return data + + +def detect_rustc_target( + host_or_target, compiler_info, arm_target, rust_supported_targets +): + # Rust's --target options are similar to, but not exactly the same + # as, the autoconf-derived targets we use. An example would be that + # Rust uses distinct target triples for targetting the GNU C++ ABI + # and the MSVC C++ ABI on Win32, whereas autoconf has a single + # triple and relies on the user to ensure that everything is + # compiled for the appropriate ABI. We need to perform appropriate + # munging to get the correct option to rustc. + # We correlate the autoconf-derived targets with the list of targets + # rustc gives us with --print target-list. + candidates = rust_supported_targets.get( + (host_or_target.cpu, host_or_target.endianness, host_or_target.os), [] + ) + + def find_candidate(candidates): + if len(candidates) == 1: + return candidates[0].rust_target + elif not candidates: + return None + + # We have multiple candidates. There are two cases where we can try to + # narrow further down using extra information from the build system. + # - For windows targets, correlate with the C compiler type + if host_or_target.kernel == "WINNT": + if host_or_target.abi: + if host_or_target.abi == "msvc": + suffix = "windows-msvc" + elif host_or_target.abi == "mingw": + suffix = "windows-gnu" + elif compiler_info.type in ("gcc", "clang"): + suffix = "windows-gnu" + else: + suffix = "windows-msvc" + narrowed = [ + c for c in candidates if c.rust_target.endswith("-{}".format(suffix)) + ] + if len(narrowed) == 1: + return narrowed[0].rust_target + elif narrowed: + candidates = narrowed + + vendor_aliases = {"pc": ("w64", "windows")} + narrowed = [ + c + for c in candidates + if host_or_target.vendor in vendor_aliases.get(c.target.vendor, ()) + ] + + if len(narrowed) == 1: + return narrowed[0].rust_target + + # - For arm targets, correlate with arm_target + # we could be more thorough with the supported rust targets, but they + # don't support OSes that are supported to build Gecko anyways. + # Also, sadly, the only interface to check the rust target cpu features + # is --print target-spec-json, and it's unstable, so we have to rely on + # our own knowledge of what each arm target means. + if host_or_target.cpu == "arm" and host_or_target.endianness == "little": + prefixes = [] + if arm_target.arm_arch >= 7: + if arm_target.thumb2 and arm_target.fpu == "neon": + prefixes.append("thumbv7neon") + if arm_target.thumb2: + prefixes.append("thumbv7a") + prefixes.append("armv7") + if arm_target.arm_arch >= 6: + prefixes.append("armv6") + if host_or_target.os != "Android": + # arm-* rust targets are armv6... except arm-linux-androideabi + prefixes.append("arm") + if arm_target.arm_arch >= 5: + prefixes.append("armv5te") + if host_or_target.os == "Android": + # arm-* rust targets are armv6... except arm-linux-androideabi + prefixes.append("arm") + if arm_target.arm_arch >= 4: + prefixes.append("armv4t") + # rust freebsd targets are the only ones that don't have a 'hf' suffix + # for hard-float. Technically, that means if the float abi ever is not + # hard-float, this will pick a wrong target, but since rust only + # supports hard-float, let's assume that means freebsd only support + # hard-float. + if arm_target.float_abi == "hard" and host_or_target.os != "FreeBSD": + suffix = "hf" + else: + suffix = "" + for p in prefixes: + for c in candidates: + if c.rust_target.startswith( + "{}-".format(p) + ) and c.rust_target.endswith(suffix): + return c.rust_target + + # See if we can narrow down on the exact alias. + # We use the sub_configure_alias to keep support mingw32 triplets as input. + narrowed = [ + c + for c in candidates + if c.target.sub_configure_alias == host_or_target.sub_configure_alias + ] + if len(narrowed) == 1: + return narrowed[0].rust_target + elif narrowed: + candidates = narrowed + + # See if we can narrow down with the raw OS + narrowed = [c for c in candidates if c.target.raw_os == host_or_target.raw_os] + if len(narrowed) == 1: + return narrowed[0].rust_target + elif narrowed: + candidates = narrowed + + # See if we can narrow down with the raw OS and raw CPU + narrowed = [ + c + for c in candidates + if c.target.raw_os == host_or_target.raw_os + and c.target.raw_cpu == host_or_target.raw_cpu + ] + if len(narrowed) == 1: + return narrowed[0].rust_target + + # Finally, see if the vendor can be used to disambiguate. + narrowed = [c for c in candidates if c.target.vendor == host_or_target.vendor] + if len(narrowed) == 1: + return narrowed[0].rust_target + + return None + + rustc_target = find_candidate(candidates) + + if rustc_target is None: + die("Don't know how to translate {} for rustc".format(host_or_target.alias)) + + return rustc_target + + +@imports("os") +@imports(_from="tempfile", _import="mkstemp") +@imports(_from="textwrap", _import="dedent") +@imports(_from="mozbuild.configure.util", _import="LineIO") +def assert_rust_compile(host_or_target, rustc_target, rustc): + # Check to see whether our rustc has a reasonably functional stdlib + # for our chosen target. + target_arg = "--target=" + rustc_target + in_fd, in_path = mkstemp(prefix="conftest", suffix=".rs", text=True) + out_fd, out_path = mkstemp(prefix="conftest", suffix=".rlib") + os.close(out_fd) + try: + source = b'pub extern fn hello() { println!("Hello world"); }' + log.debug("Creating `%s` with content:", in_path) + with LineIO(lambda l: log.debug("| %s", l)) as out: + out.write(source) + + os.write(in_fd, source) + os.close(in_fd) + + cmd = [ + rustc, + "--crate-type", + "staticlib", + target_arg, + "-o", + out_path, + in_path, + ] + + def failed(): + die( + dedent( + """\ + Cannot compile for {} with {} + The target may be unsupported, or you may not have + a rust std library for that target installed. Try: + + rustup target add {} + """.format( + host_or_target.alias, rustc, rustc_target + ) + ) + ) + + check_cmd_output(*cmd, onerror=failed) + if not os.path.exists(out_path) or os.path.getsize(out_path) == 0: + failed() + finally: + os.remove(in_path) + os.remove(out_path) + + +@depends( + rustc, + host, + host_c_compiler, + rustc_info.host, + rust_supported_targets, + arm_target, + when=rust_compiler, +) +@checking("for rust host triplet") +@imports(_from="textwrap", _import="dedent") +def rust_host_triple( + rustc, host, compiler_info, rustc_host, rust_supported_targets, arm_target +): + rustc_target = detect_rustc_target( + host, compiler_info, arm_target, rust_supported_targets + ) + if rustc_target != rustc_host: + if host.alias == rustc_target: + configure_host = host.alias + else: + configure_host = "{}/{}".format(host.alias, rustc_target) + die( + dedent( + """\ + The rust compiler host ({rustc}) is not suitable for the configure host ({configure}). + + You can solve this by: + * Set your configure host to match the rust compiler host by editing your + mozconfig and adding "ac_add_options --host={rustc}". + * Or, install the rust toolchain for {configure}, if supported, by running + "rustup default stable-{rustc_target}" + """.format( + rustc=rustc_host, + configure=configure_host, + rustc_target=rustc_target, + ) + ) + ) + assert_rust_compile(host, rustc_target, rustc) + return rustc_target + + +@depends( + rustc, target, c_compiler, rust_supported_targets, arm_target, when=rust_compiler +) +@checking("for rust target triplet") +def rust_target_triple( + rustc, target, compiler_info, rust_supported_targets, arm_target +): + rustc_target = detect_rustc_target( + target, compiler_info, arm_target, rust_supported_targets + ) + assert_rust_compile(target, rustc_target, rustc) + return rustc_target + + +set_config("RUST_TARGET", rust_target_triple) +set_config("RUST_HOST_TARGET", rust_host_triple) + + +# This is used for putting source info into symbol files. +set_config("RUSTC_COMMIT", depends(rustc_info)(lambda i: i.commit)) + +# Rustdoc is required by Rust tests below. +option(env="RUSTDOC", nargs=1, help="Path to the rustdoc program") + +rustdoc = check_prog( + "RUSTDOC", + ["rustdoc"], + paths=rust_search_path, + input="RUSTDOC", + allow_missing=True, +) + +# This option is separate from --enable-tests because Rust tests are particularly +# expensive in terms of compile time (especially for code in libxul). +option( + "--enable-rust-tests", + help="Enable building and running of Rust tests during `make check`", +) + + +@depends("--enable-rust-tests", rustdoc) +def rust_tests(enable_rust_tests, rustdoc): + if enable_rust_tests and not rustdoc: + die("--enable-rust-tests requires rustdoc") + return bool(enable_rust_tests) + + +set_config("MOZ_RUST_TESTS", rust_tests) + + +@depends(target, c_compiler, rustc) +@imports("os") +def rustc_natvis_ldflags(target, compiler_info, rustc): + if target.kernel == "WINNT" and compiler_info.type == "clang-cl": + sysroot = check_cmd_output(rustc, "--print", "sysroot").strip() + etc = os.path.join(sysroot, "lib/rustlib/etc") + ldflags = [] + if os.path.isdir(etc): + for f in os.listdir(etc): + if f.endswith(".natvis"): + ldflags.append("-NATVIS:" + normsep(os.path.join(etc, f))) + return ldflags + + +set_config("RUSTC_NATVIS_LDFLAGS", rustc_natvis_ldflags) + + +option( + "--enable-rust-debug", + default=depends(when="--enable-debug")(lambda: True), + help="{Build|Do not build} Rust code with debug assertions turned " "on.", +) + + +@depends(when="--enable-rust-debug") +def debug_rust(): + return True + + +set_config("MOZ_DEBUG_RUST", debug_rust) +set_define("MOZ_DEBUG_RUST", debug_rust) + +# ============================================================== + +option(env="RUSTFLAGS", nargs=1, help="Rust compiler flags") +set_config("RUSTFLAGS", depends("RUSTFLAGS")(lambda flags: flags)) + + +# Rust compiler flags +# ============================================================== + + +@depends(moz_optimize) +def rustc_opt_level_default(moz_optimize): + return "2" if moz_optimize.optimize else "0" + + +option( + env="RUSTC_OPT_LEVEL", + default=rustc_opt_level_default, + nargs=1, + help="Rust compiler optimization level (-C opt-level=%s)", +) + + +@depends("RUSTC_OPT_LEVEL") +def rustc_opt_level(opt_level_option): + return opt_level_option[0] + + +set_config("CARGO_PROFILE_RELEASE_OPT_LEVEL", rustc_opt_level) +set_config("CARGO_PROFILE_DEV_OPT_LEVEL", rustc_opt_level) + + +@depends( + rustc_opt_level, + debug_rust, + target, + "--enable-debug-symbols", + "--enable-frame-pointers", + path_remapping, + path_remappings, +) +def rust_compile_flags( + opt_level, + debug_rust, + target, + debug_symbols, + frame_pointers, + path_remapping, + path_remappings, +): + # Cargo currently supports only two interesting profiles for building: + # development and release. Those map (roughly) to --enable-debug and + # --disable-debug in Gecko, respectively. + # + # But we'd also like to support an additional axis of control for + # optimization level. Since Cargo only supports 2 profiles, we're in + # a bit of a bind. + # + # Code here derives various compiler options given other configure options. + # The options defined here effectively override defaults specified in + # Cargo.toml files. + + debug_assertions = None + debug_info = None + + # opt-level=0 implies -C debug-assertions, which may not be desired + # unless Rust debugging is enabled. + if opt_level == "0" and not debug_rust: + debug_assertions = False + + if debug_symbols: + debug_info = "2" + + opts = [] + + if debug_assertions is not None: + opts.append("debug-assertions=%s" % ("yes" if debug_assertions else "no")) + if debug_info is not None: + opts.append("debuginfo=%s" % debug_info) + if frame_pointers: + opts.append("force-frame-pointers=yes") + # CFG for arm64 is crashy, see `def security_hardening_cflags`. + if target.kernel == "WINNT" and target.cpu != "aarch64": + opts.append("control-flow-guard=yes") + + flags = [] + for opt in opts: + flags.extend(["-C", opt]) + + if "rust" in path_remapping: + # rustc has supported --remap-path-prefix since version 1.26, well + # before our required minimum Rust version, so there's no need to + # feature-detect or gate on versions. + for old, new in path_remappings: + flags.append(f"--remap-path-prefix={old}={new}") + + return flags + + +# Rust incremental compilation +# ============================================================== + + +option("--disable-cargo-incremental", help="Disable incremental rust compilation.") + + +@depends( + developer_options, + debug_rust, + "MOZ_AUTOMATION", + code_coverage, + "--disable-cargo-incremental", + using_sccache, + "RUSTC_WRAPPER", +) +@imports("os") +def cargo_incremental( + developer_options, + debug_rust, + automation, + code_coverage, + enabled, + using_sccache, + rustc_wrapper, +): + """Return a value for the CARGO_INCREMENTAL environment variable.""" + + if not enabled: + return "0" + elif enabled.origin != "default": + return "1" + + # We never want to use incremental compilation in automation. sccache + # handles our automation use case much better than incremental compilation + # would. + if automation: + return "0" + + # Coverage instrumentation doesn't play well with incremental compilation + # https://github.com/rust-lang/rust/issues/50203. + if code_coverage: + return "0" + + # Incremental compilation doesn't work as well as it should, and if we're + # using sccache, it's better to use sccache than incremental compilation. + if not using_sccache and rustc_wrapper: + rustc_wrapper = os.path.basename(rustc_wrapper[0]) + if os.path.splitext(rustc_wrapper)[0].lower() == "sccache": + using_sccache = True + if using_sccache: + return "0" + + # Incremental compilation is automatically turned on for debug builds, so + # we don't need to do anything special here. + if debug_rust: + return + + # Don't enable on --enable-release builds, because of the runtime + # performance cost. + if not developer_options: + return + + # We're clear to use incremental compilation! + return "1" + + +set_config("CARGO_INCREMENTAL", cargo_incremental) + + +@depends(rust_compile_flags, "--enable-warnings-as-errors", rustc_info) +def rust_flags(compile_flags, warnings_as_errors, rustc_info): + warning_flags = [] + + # Note that cargo passes --cap-lints warn to rustc for third-party code, so + # we don't need a very complicated setup. + if warnings_as_errors: + warning_flags.append("-Dwarnings") + # Work around https://github.com/rust-lang/rust/issues/84428 + if rustc_info.version >= "1.52": + warning_flags.append("-Aproc-macro-back-compat") + else: + warning_flags.extend(("--cap-lints", "warn")) + + return compile_flags + warning_flags + + +set_config("MOZ_RUST_DEFAULT_FLAGS", rust_flags) diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure new file mode 100644 index 0000000000..a8ab8bd698 --- /dev/null +++ b/build/moz.configure/toolchain.configure @@ -0,0 +1,3290 @@ +# -*- 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/. + +# Code optimization +# ============================================================== + +option("--disable-optimize", nargs="?", help="Disable optimizations via compiler flags") + + +@depends("--enable-optimize") +def moz_optimize(option): + flags = None + + if len(option): + flags = option[0] + if "-O0" in flags: + val = None + else: + val = "2" + elif option: + val = "1" + else: + val = None + + return namespace( + optimize=val, + flags=flags, + ) + + +set_config("MOZ_OPTIMIZE", moz_optimize.optimize) +add_old_configure_assignment("MOZ_OPTIMIZE", moz_optimize.optimize) +add_old_configure_assignment("MOZ_CONFIGURE_OPTIMIZE_FLAGS", moz_optimize.flags) + +# Android NDK +# ============================================================== + + +@depends("--disable-compile-environment", target) +def compiling_android(compile_env, target): + return compile_env and target.os == "Android" + + +include("android-ndk.configure", when=compiling_android) + +with only_when(target_is_osx): + # MacOS deployment target version + # ============================================================== + # This needs to happen before any compilation test is done. + + option( + "--enable-macos-target", + env="MACOSX_DEPLOYMENT_TARGET", + nargs=1, + default=depends(target, developer_options) + # We continue to target 10.15 on Intel, but can target 11.0 for + # aarch64 since the earliest hardware was released alongside 11.0. + # For local builds, we want to target 10.15 regardless of the + # underlying platform to catch any errors or warnings that wouldn't + # show up when targeting 11.0, since these would later show up on + # CI for Intel builds. + (lambda t, d: "11.0" if (t.cpu == "aarch64" and not d) else "10.15"), + help="Set the minimum MacOS version needed at runtime{|}", + ) + + @depends_if("--enable-macos-target", developer_options) + def macos_target(value, _): + return value[0] + + +with only_when(host_is_osx | target_is_osx): + # MacOS SDK + # ========= + option( + "--with-macos-sdk", + env="MACOS_SDK_DIR", + nargs=1, + help="Location of platform SDK to use", + ) + + @imports("plistlib") + @imports(_from="__builtin__", _import="open") + @imports(_from="__builtin__", _import="Exception") + def get_sdk_version(sdk): + with open(os.path.join(sdk, "SDKSettings.plist"), "rb") as plist: + obj = plistlib.load(plist) + if not obj: + raise Exception( + "Error parsing SDKSettings.plist in the SDK directory: %s" % sdk + ) + if "Version" not in obj: + raise Exception( + "Error finding Version information in SDKSettings.plist from the SDK: %s" + % sdk + ) + return Version(obj["Version"]) + + def sdk_min_version(): + return "14.2" + + @depends( + "--with-macos-sdk", + host, + bootstrap_path( + "MacOSX{}.sdk".format(sdk_min_version()), + when=depends("--with-macos-sdk")(lambda x: not x), + allow_failure=True, + ), + ) + @imports(_from="__builtin__", _import="Exception") + @imports(_from="os.path", _import="isdir") + @imports(_from="os", _import="listdir") + def macos_sdk(sdk, host, bootstrapped): + if bootstrapped: + sdk = [bootstrapped] + if sdk: + sdk = sdk[0] + try: + version = get_sdk_version(sdk) + except Exception as e: + die(e) + elif host.os == "OSX": + sdk = check_cmd_output( + "xcrun", "--show-sdk-path", onerror=lambda: "" + ).rstrip() + if not sdk: + die( + "Could not find the macOS SDK. Please use --with-macos-sdk to give " + "the path to a macOS SDK." + ) + # Scan the parent directory xcrun returns for the most recent SDK. + sdk_dir = os.path.dirname(sdk) + versions = [] + for d in listdir(sdk_dir): + if d.lower().startswith("macos"): + try: + sdk = os.path.join(sdk_dir, d) + versions.append((get_sdk_version(sdk), sdk)) + except Exception: + pass + version, sdk = max(versions) + else: + die( + "Need a macOS SDK when targeting macOS. Please use --with-macos-sdk " + "to give the path to a macOS SDK." + ) + + if not isdir(sdk): + die( + "SDK not found in %s. When using --with-macos-sdk, you must specify a " + "valid SDK. SDKs are installed when the optional cross-development " + "tools are selected during the Xcode/Developer Tools installation." + % sdk + ) + if version < Version(sdk_min_version()): + die( + 'SDK version "%s" is too old. Please upgrade to at least %s. Try ' + "updating your system Xcode." % (version, sdk_min_version()) + ) + return sdk + + set_config("MACOS_SDK_DIR", macos_sdk) + + +with only_when(target_is_osx): + with only_when(cross_compiling): + option( + "--with-macos-private-frameworks", + env="MACOS_PRIVATE_FRAMEWORKS_DIR", + nargs=1, + help="Location of private frameworks to use", + ) + + @depends_if("--with-macos-private-frameworks") + @imports(_from="os.path", _import="isdir") + def macos_private_frameworks(value): + if value and not isdir(value[0]): + die( + "PrivateFrameworks not found not found in %s. When using " + "--with-macos-private-frameworks, you must specify a valid " + "directory", + value[0], + ) + return value[0] + + @depends(macos_private_frameworks, macos_sdk) + def macos_private_frameworks(value, sdk): + if value: + return value + return os.path.join(sdk or "/", "System/Library/PrivateFrameworks") + + set_config("MACOS_PRIVATE_FRAMEWORKS_DIR", macos_private_frameworks) + + +# GC rooting and hazard analysis. +# ============================================================== +option(env="MOZ_HAZARD", help="Build for the GC rooting hazard analysis") + + +@depends("MOZ_HAZARD") +def hazard_analysis(value): + if value: + return True + + +set_config("MOZ_HAZARD", hazard_analysis) + + +# Cross-compilation related things. +# ============================================================== +option( + "--with-toolchain-prefix", + env="TOOLCHAIN_PREFIX", + nargs=1, + help="Prefix for the target toolchain", +) + + +@depends("--with-toolchain-prefix", host, target, cross_compiling) +def toolchain_prefix(value, host, target, cross_compiling): + if value: + return tuple(value) + # We don't want a toolchain prefix by default when building on mac for mac. + if cross_compiling and not (target.os == "OSX" and host.os == "OSX"): + return ("%s-" % target.toolchain, "%s-" % target.alias) + + +@depends(toolchain_prefix, target) +def first_toolchain_prefix(toolchain_prefix, target): + # Pass TOOLCHAIN_PREFIX down to the build system if it was given from the + # command line/environment (in which case there's only one value in the tuple), + # or when cross-compiling for Android or OSX. + if toolchain_prefix and ( + target.os in ("Android", "OSX") or len(toolchain_prefix) == 1 + ): + return toolchain_prefix[0] + + +set_config("TOOLCHAIN_PREFIX", first_toolchain_prefix) +add_old_configure_assignment("TOOLCHAIN_PREFIX", first_toolchain_prefix) + + +# Compilers +# ============================================================== +include("compilers-util.configure") + + +def try_preprocess( + configure_cache, compiler, language, source, onerror=None, wrapper=[] +): + return try_invoke_compiler( + configure_cache, compiler, language, source, ["-E"], onerror, wrapper + ) + + +@imports(_from="mozbuild.configure.constants", _import="CompilerType") +@imports(_from="mozbuild.configure.constants", _import="CPU_preprocessor_checks") +@imports(_from="mozbuild.configure.constants", _import="kernel_preprocessor_checks") +@imports(_from="mozbuild.configure.constants", _import="OS_preprocessor_checks") +@imports(_from="textwrap", _import="dedent") +@imports(_from="__builtin__", _import="Exception") +def get_compiler_info(configure_cache, compiler, language): + """Returns information about the given `compiler` (command line in the + form of a list or tuple), in the given `language`. + + The returned information includes: + - the compiler type (clang-cl, clang or gcc) + - the compiler version + - the compiler supported language + - the compiler supported language version + """ + # Xcode clang versions are different from the underlying llvm version (they + # instead are aligned with the Xcode version). Fortunately, we can tell + # apart plain clang from Xcode clang, and convert the Xcode clang version + # into the more or less corresponding plain clang version. + check = dedent( + """\ + #if defined(_MSC_VER) && defined(__clang__) && defined(_MT) + %COMPILER "clang-cl" + %VERSION __clang_major__.__clang_minor__.__clang_patchlevel__ + #elif defined(__clang__) + %COMPILER "clang" + %VERSION __clang_major__.__clang_minor__.__clang_patchlevel__ + # ifdef __apple_build_version__ + %XCODE 1 + # endif + #elif defined(__GNUC__) && !defined(__MINGW32__) + %COMPILER "gcc" + %VERSION __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__ + #endif + + #if __cplusplus + %cplusplus __cplusplus + #elif __STDC_VERSION__ + %STDC_VERSION __STDC_VERSION__ + #endif + """ + ) + + # While we're doing some preprocessing, we might as well do some more + # preprocessor-based tests at the same time, to check the toolchain + # matches what we want. + for name, preprocessor_checks in ( + ("CPU", CPU_preprocessor_checks), + ("KERNEL", kernel_preprocessor_checks), + ("OS", OS_preprocessor_checks), + ): + for n, (value, condition) in enumerate(preprocessor_checks.items()): + check += dedent( + """\ + #%(if)s %(condition)s + %%%(name)s "%(value)s" + """ + % { + "if": "elif" if n else "if", + "condition": condition, + "name": name, + "value": value, + } + ) + check += "#endif\n" + + # Also check for endianness. The advantage of living in modern times is + # that all the modern compilers we support now have __BYTE_ORDER__ defined + # by the preprocessor. + check += dedent( + """\ + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + %ENDIANNESS "little" + #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + %ENDIANNESS "big" + #endif + """ + ) + + result = try_preprocess(configure_cache, compiler, language, check) + + if not result: + raise FatalCheckError("Unknown compiler or compiler not supported.") + + # Metadata emitted by preprocessors such as GCC with LANG=ja_JP.utf-8 may + # have non-ASCII characters. Treat the output as bytearray. + data = {} + for line in result.splitlines(): + if line.startswith("%"): + k, _, v = line.partition(" ") + k = k.lstrip("%") + data[k] = v.replace(" ", "").lstrip('"').rstrip('"') + log.debug("%s = %s", k, data[k]) + + try: + type = CompilerType(data["COMPILER"]) + except Exception: + raise FatalCheckError("Unknown compiler or compiler not supported.") + + cplusplus = int(data.get("cplusplus", "0L").rstrip("L")) + stdc_version = int(data.get("STDC_VERSION", "0L").rstrip("L")) + + version = data.get("VERSION") + if version: + version = Version(version) + if data.get("XCODE"): + # Derived from https://en.wikipedia.org/wiki/Xcode#Toolchain_versions + # with enough granularity for major.minor version checks further + # down the line + if version < "9.1": + version = Version("4.0.0.or.less") + elif version < "10.0": + version = Version("5.0.2") + elif version < "10.0.1": + version = Version("6.0.1") + elif version < "11.0": + version = Version("7.0.0") + elif version < "11.0.3": + version = Version("8.0.0") + elif version < "12.0": + version = Version("9.0.0") + elif version < "12.0.5": + version = Version("10.0.0") + elif version < "13.0": + version = Version("11.1.0") + elif version < "13.0.1": + version = Version("12.0.0") + elif version < "14.0": + version = Version("13.0.0") + elif version < "15.0": + version = Version("14.0.0") + else: + version = Version("14.0.0.or.more") + + return namespace( + type=type, + version=version, + cpu=data.get("CPU"), + kernel=data.get("KERNEL"), + endianness=data.get("ENDIANNESS"), + os=data.get("OS"), + language="C++" if cplusplus else "C", + language_version=cplusplus if cplusplus else stdc_version, + xcode=bool(data.get("XCODE")), + ) + + +def same_arch_different_bits(): + return ( + ("x86", "x86_64"), + ("ppc", "ppc64"), + ("sparc", "sparc64"), + ) + + +@imports(_from="mozbuild.shellutil", _import="quote") +@imports(_from="mozbuild.configure.constants", _import="OS_preprocessor_checks") +def check_compiler(configure_cache, compiler, language, target, android_version): + info = get_compiler_info(configure_cache, compiler, language) + + flags = [] + + # Check language standards + # -------------------------------------------------------------------- + if language != info.language: + raise FatalCheckError( + "`%s` is not a %s compiler." % (quote(*compiler), language) + ) + + # Note: We do a strict version check because there sometimes are backwards + # incompatible changes in the standard, and not all code that compiles as + # C99 compiles as e.g. C11 (as of writing, this is true of libnestegg, for + # example) + if info.language == "C" and info.language_version != 199901: + if info.type == "clang-cl": + flags.append("-Xclang") + flags.append("-std=gnu99") + + cxx17_version = 201703 + if info.language == "C++": + if info.language_version != cxx17_version: + # MSVC headers include C++17 features, but don't guard them + # with appropriate checks. + if info.type == "clang-cl": + flags.append("-Xclang") + flags.append("-std=c++17") + else: + flags.append("-std=gnu++17") + + # Check compiler target + # -------------------------------------------------------------------- + has_target = False + if target.os == "Android" and android_version: + # This makes clang define __ANDROID_API__ and use versioned library + # directories from the NDK. + toolchain = "%s%d" % (target.toolchain, android_version) + else: + toolchain = target.toolchain + + if info.type == "clang": + # Add the target explicitly when the target is aarch64 macosx, because + # the Xcode clang target is named differently, and we need to work around + # https://github.com/rust-lang/rust-bindgen/issues/1871 and + # https://github.com/alexcrichton/cc-rs/issues/542 so we always want + # the target on the command line, even if the compiler would default to + # that. + if info.xcode and target.os == "OSX" and target.cpu == "aarch64": + if "--target=arm64-apple-darwin" not in compiler: + flags.append("--target=arm64-apple-darwin") + has_target = True + + elif ( + not info.kernel + or info.kernel != target.kernel + or not info.endianness + or info.endianness != target.endianness + ): + flags.append("--target=%s" % toolchain) + has_target = True + + # Add target flag when there is an OS mismatch (e.g. building for Android on + # Linux). However, only do this if the target OS is in our whitelist, to + # keep things the same on other platforms. + elif target.os in OS_preprocessor_checks and ( + not info.os or info.os != target.os + ): + flags.append("--target=%s" % toolchain) + has_target = True + + if not has_target and (not info.cpu or info.cpu != target.cpu): + same_arch = same_arch_different_bits() + if (target.cpu, info.cpu) in same_arch: + flags.append("-m32") + elif (info.cpu, target.cpu) in same_arch: + flags.append("-m64") + elif info.type == "clang-cl" and target.cpu == "aarch64": + flags.append("--target=%s" % toolchain) + elif info.type == "clang": + flags.append("--target=%s" % toolchain) + + return namespace( + type=info.type, + version=info.version, + target_cpu=info.cpu, + target_kernel=info.kernel, + target_endianness=info.endianness, + target_os=info.os, + flags=flags, + ) + + +@imports(_from="__builtin__", _import="open") +@imports("json") +@imports("os") +def get_vc_paths(topsrcdir): + def vswhere(args): + program_files = os.environ.get("PROGRAMFILES(X86)") or os.environ.get( + "PROGRAMFILES" + ) + if not program_files: + return [] + vswhere = os.path.join( + program_files, "Microsoft Visual Studio", "Installer", "vswhere.exe" + ) + if not os.path.exists(vswhere): + return [] + return json.loads(check_cmd_output(vswhere, "-format", "json", *args)) + + for install in vswhere( + [ + "-products", + "*", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + ] + ): + path = install["installationPath"] + tools_version = ( + open( + os.path.join( + path, r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" + ), + "r", + ) + .read() + .strip() + ) + tools_path = os.path.join(path, r"VC\Tools\MSVC", tools_version) + yield (Version(install["installationVersion"]), tools_path) + + +@depends(target, host) +def is_windows(target, host): + return host.kernel == "WINNT" or target.kernel == "WINNT" + + +# Calling this a sysroot is a little weird, but it's the terminology clang went +# with with its -winsysroot flag. +option( + env="WINSYSROOT", + nargs=1, + when=is_windows, + help='Path to a Windows "sysroot" (directory containing MSVC, SDKs)', +) + + +@depends( + "WINSYSROOT", + bootstrap_path( + "vs", + when=depends("WINSYSROOT", when=is_windows)(lambda x: not x), + ), + when=is_windows, +) +def winsysroot(winsysroot, bootstrapped): + if bootstrapped: + return bootstrapped + if winsysroot: + return winsysroot[0] + + +option( + env="VC_PATH", + nargs=1, + when=is_windows, + help="Path to the Microsoft Visual C/C++ compiler", +) + + +@depends( + host, + build_environment, + "VC_PATH", + winsysroot, + when=is_windows, +) +@imports("os") +@imports(_from="operator", _import="itemgetter") +def vc_compiler_paths_for_version(host, env, vc_path, winsysroot): + if winsysroot: + if vc_path: + die("WINSYSROOT and VC_PATH cannot be set together.") + base_vc_path = os.path.join(winsysroot, "VC", "Tools", "MSVC") + versions = os.listdir(base_vc_path) + vc_path = [os.path.join(base_vc_path, str(max(Version(v) for v in versions)))] + if vc_path: + # Use an arbitrary version, it doesn't matter. + all_versions = [(Version("15"), vc_path[0])] + elif host.kernel != "WINNT": + # Don't try to do anything when VC_PATH is not set on cross-compiles. + return + else: + all_versions = sorted(get_vc_paths(env.topsrcdir), key=itemgetter(0)) + if not all_versions: + return + # Choose the newest version. + path = all_versions[-1][1] + host_dir = { + "x86_64": "Hostx64", + "x86": "Hostx86", + }.get(host.cpu) + if host_dir: + path = os.path.join(path, "bin", host_dir) + return { + "x64": [os.path.join(path, "x64")], + # The cross toolchains require DLLs from the native x64 toolchain. + "x86": [os.path.join(path, "x86"), os.path.join(path, "x64")], + "arm64": [os.path.join(path, "arm64"), os.path.join(path, "x64")], + } + + +@depends(target, host, vc_compiler_paths_for_version, when=is_windows) +def vc_compiler_path(target, host, paths): + cpu = target.cpu if target.os == "WINNT" else host.cpu + vc_target = { + "x86": "x86", + "x86_64": "x64", + "arm": "arm", + "aarch64": "arm64", + }.get(cpu) + if not paths: + return + return paths.get(vc_target) + + +@depends(vc_compiler_path, original_path) +@imports("os") +@imports(_from="os", _import="environ") +def vc_toolchain_search_path(vc_compiler_path, original_path): + result = list(original_path) + + if vc_compiler_path: + # The second item, if there is one, is necessary to have in $PATH for + # Windows to load the required DLLs from there. + if len(vc_compiler_path) > 1: + environ["PATH"] = os.pathsep.join(result + vc_compiler_path[1:]) + + # The first item is where the programs are going to be + result.append(vc_compiler_path[0]) + + return result + + +@depends_if(vc_compiler_path, when=is_windows) +def vc_compiler_version(vc_compiler_path): + version = Version( + os.path.basename( + os.path.dirname(os.path.dirname(os.path.dirname(vc_compiler_path[0]))) + ) + ) + # MSVC path with version 14.x is actually version 19.x + if version.major == 14: + return Version(f"19.{version.minor}") + + +@depends_if(vc_compiler_version) +def is_vs2019_or_more(vc_compiler_version): + return vc_compiler_version >= Version("19.20") + + +add_old_configure_assignment("IS_VS2019_OR_MORE", is_vs2019_or_more) + + +@depends_if(vc_compiler_version) +def msvs_version(vc_compiler_version): + # clang-cl emulates the same version scheme as cl. And MSVS_VERSION needs to + # be set for GYP on Windows. + if vc_compiler_version >= Version("19.30"): + return "2022" + if vc_compiler_version >= Version("19.20"): + return "2019" + if vc_compiler_version >= Version("19.10"): + return "2017" + + return "" + + +set_config("MSVS_VERSION", msvs_version) + + +clang_search_path = bootstrap_search_path("clang/bin") + + +@depends( + bootstrap_search_path("rustc/bin", when="MOZ_AUTOMATION"), + bootstrap_search_path_order, + original_path, +) +@imports("os") +@imports(_from="os", _import="environ") +def rust_search_path(rust_path, search_order, original_path): + result = list(rust_path or original_path) + # Also add the rustup install directory for cargo/rustc. + cargo_home = environ.get("CARGO_HOME", "") + if cargo_home: + cargo_home = os.path.abspath(cargo_home) + else: + cargo_home = os.path.expanduser(os.path.join("~", ".cargo")) + rustup_path = os.path.join(cargo_home, "bin") + if search_order == "prepend": + result.insert(0, rustup_path) + else: + result.append(rustup_path) + return result + + +# Prepend the mozilla-build msys2 path, since otherwise we can get mismatched +# cygwin dll errors during configure if we get called from another msys2 +# environment, see bug 1801826. +@depends( + mozillabuild_bin_paths, clang_search_path, rust_search_path, target, original_path +) +@imports("os") +def altered_path( + mozillabuild_bin_paths, clang_search_path, rust_search_path, target, original_path +): + altered_path = mozillabuild_bin_paths + if target.kernel == "Darwin": + # The rust compiler wants to execute dsymutil, but it does so in a + # non-configurable way (https://github.com/rust-lang/rust/issues/52728) + # so we add the clang path. + path = clang_search_path + else: + path = original_path + # cargo needs the rust search path to find cargo-$subcommand. + path += rust_search_path + for p in path: + if p not in altered_path: + altered_path.append(p) + return os.pathsep.join(altered_path) + + +set_config("PATH", altered_path) + + +# Compiler wrappers +# ============================================================== +option( + "--with-compiler-wrapper", + env="COMPILER_WRAPPER", + nargs=1, + help="Enable compiling with wrappers such as distcc and ccache", +) + +option("--with-ccache", env="CCACHE", nargs="?", help="Enable compiling with ccache") + + +@depends_if("--with-ccache") +def ccache(value): + if len(value): + return value + # If --with-ccache was given without an explicit value, we default to + # 'ccache'. + return "ccache" + + +ccache = check_prog( + "CCACHE", + progs=(), + input=ccache, + paths=bootstrap_search_path( + "sccache", when=depends("CCACHE")(lambda c: len(c) and c[0] == "sccache") + ), + allow_missing=True, +) + +option(env="CCACHE_PREFIX", nargs=1, help="Compiler prefix to use when using ccache") + +ccache_prefix = depends_if("CCACHE_PREFIX")(lambda prefix: prefix[0]) +set_config("CCACHE_PREFIX", ccache_prefix) + +# Distinguish ccache from sccache. + + +@depends_if(ccache) +def ccache_is_sccache(ccache): + return check_cmd_output(ccache, "--version").startswith("sccache") + + +@depends(ccache, ccache_is_sccache) +def using_ccache(ccache, ccache_is_sccache): + return ccache and not ccache_is_sccache + + +@depends_if(ccache, ccache_is_sccache) +def using_sccache(ccache, ccache_is_sccache): + return ccache and ccache_is_sccache + + +option(env="RUSTC_WRAPPER", nargs=1, help="Wrap rust compilation with given tool") + + +@depends(ccache, ccache_is_sccache, "RUSTC_WRAPPER") +@imports(_from="textwrap", _import="dedent") +@imports("os") +def check_sccache_version(ccache, ccache_is_sccache, rustc_wrapper): + sccache_min_version = Version("0.2.13") + + def check_version(path): + out = check_cmd_output(path, "--version") + version = Version(out.rstrip().split()[-1]) + if version < sccache_min_version: + die( + dedent( + """\ + sccache %s or later is required. sccache in use at %s has + version %s. + + Please upgrade or acquire a new version with |./mach bootstrap|. + """ + ), + sccache_min_version, + path, + version, + ) + + if ccache and ccache_is_sccache: + check_version(ccache) + + if rustc_wrapper and ( + os.path.splitext(os.path.basename(rustc_wrapper[0]))[0].lower() == "sccache" + ): + check_version(rustc_wrapper[0]) + + +set_config("MOZ_USING_CCACHE", using_ccache) +set_config("MOZ_USING_SCCACHE", using_sccache) + +option(env="SCCACHE_VERBOSE_STATS", help="Print verbose sccache stats after build") + + +@depends(using_sccache, "SCCACHE_VERBOSE_STATS") +def sccache_verbose_stats(using_sccache, verbose_stats): + return using_sccache and bool(verbose_stats) + + +set_config("SCCACHE_VERBOSE_STATS", sccache_verbose_stats) + + +@depends("--with-compiler-wrapper", ccache) +@imports(_from="mozbuild.shellutil", _import="split", _as="shell_split") +def compiler_wrapper(wrapper, ccache): + if wrapper: + raw_wrapper = wrapper[0] + wrapper = shell_split(raw_wrapper) + wrapper_program = find_program(wrapper[0]) + if not wrapper_program: + die( + "Cannot find `%s` from the given compiler wrapper `%s`", + wrapper[0], + raw_wrapper, + ) + wrapper[0] = wrapper_program + + if ccache: + if wrapper: + return tuple([ccache] + wrapper) + else: + return (ccache,) + elif wrapper: + return tuple(wrapper) + + +@depends_if(compiler_wrapper) +def using_compiler_wrapper(compiler_wrapper): + return True + + +set_config("MOZ_USING_COMPILER_WRAPPER", using_compiler_wrapper) + + +@dependable +def wasm(): + return split_triplet("wasm32-wasi", allow_wasi=True) + + +@template +def default_c_compilers(host_or_target, other_c_compiler=None): + """Template defining the set of default C compilers for the host and + target platforms. + `host_or_target` is either `host` or `target` (the @depends functions + from init.configure. + `other_c_compiler` is the `target` C compiler when `host_or_target` is `host`. + """ + assert host_or_target in {host, target, wasm} + + other_c_compiler = () if other_c_compiler is None else (other_c_compiler,) + + @depends(host_or_target, target, toolchain_prefix, *other_c_compiler) + def default_c_compilers( + host_or_target, target, toolchain_prefix, *other_c_compiler + ): + if host_or_target.kernel == "WINNT": + if host_or_target.abi: + if host_or_target.abi == "msvc": + supported = types = ("clang-cl",) + elif host_or_target.abi == "mingw": + supported = types = ("clang",) + else: + supported = types = ("clang-cl", "clang") + elif host_or_target.kernel == "Darwin": + types = ("clang",) + supported = ("clang", "gcc") + elif host_or_target.kernel == "WASI": + supported = types = ("clang",) + else: + supported = types = ("clang", "gcc") + + info = other_c_compiler[0] if other_c_compiler else None + if info and info.type in supported: + # When getting default C compilers for the host, we prioritize the + # same compiler as the target C compiler. + prioritized = info.compiler + if info.type == "gcc": + same_arch = same_arch_different_bits() + if ( + target.cpu != host_or_target.cpu + and (target.cpu, host_or_target.cpu) not in same_arch + and (host_or_target.cpu, target.cpu) not in same_arch + ): + # If the target C compiler is GCC, and it can't be used with + # -m32/-m64 for the host, it's probably toolchain-prefixed, + # so we prioritize a raw 'gcc' instead. + prioritized = info.type + if target.os != "WINNT" and host_or_target.os == "WINNT": + # When cross-compiling on Windows, don't prioritize. We'll fallback + # to checking for clang-cl first. + pass + else: + types = [prioritized] + [t for t in types if t != info.type] + + gcc = ("gcc",) + if toolchain_prefix and host_or_target is target: + gcc = tuple("%sgcc" % p for p in toolchain_prefix) + gcc + + result = [] + for type in types: + if type == "gcc": + result.extend(gcc) + else: + result.append(type) + + return tuple(result) + + return default_c_compilers + + +@template +def default_cxx_compilers(c_compiler, other_c_compiler=None, other_cxx_compiler=None): + """Template defining the set of default C++ compilers for the host and + target platforms. + `c_compiler` is the @depends function returning a Compiler instance for + the desired platform. + + Because the build system expects the C and C++ compilers to be from the + same compiler suite, we derive the default C++ compilers from the C + compiler that was found if none was provided. + + We also factor in the target C++ compiler when getting the default host + C++ compiler, using the target C++ compiler if the host and target C + compilers are the same. + """ + + assert (other_c_compiler is None) == (other_cxx_compiler is None) + if other_c_compiler is not None: + other_compilers = (other_c_compiler, other_cxx_compiler) + else: + other_compilers = () + + @depends(c_compiler, *other_compilers) + def default_cxx_compilers(c_compiler, *other_compilers): + if other_compilers: + other_c_compiler, other_cxx_compiler = other_compilers + if other_c_compiler.compiler == c_compiler.compiler: + return (other_cxx_compiler.compiler,) + + dir = os.path.dirname(c_compiler.compiler) + file = os.path.basename(c_compiler.compiler) + + if c_compiler.type == "gcc": + return (os.path.join(dir, file.replace("gcc", "g++")),) + + if c_compiler.type == "clang": + return (os.path.join(dir, file.replace("clang", "clang++")),) + + return (c_compiler.compiler,) + + return default_cxx_compilers + + +@template +def provided_program(env_var, when=None): + """Template handling cases where a program can be specified either as a + path or as a path with applicable arguments. + """ + + @depends_if(env_var, when=when) + @imports(_from="itertools", _import="takewhile") + @imports(_from="mozbuild.shellutil", _import="split", _as="shell_split") + def provided(cmd): + # Assume the first dash-prefixed item (and any subsequent items) are + # command-line options, the item before the dash-prefixed item is + # the program we're looking for, and anything before that is a wrapper + # of some kind (e.g. sccache). + cmd = shell_split(cmd[0]) + + without_flags = list(takewhile(lambda x: not x.startswith("-"), cmd)) + + return namespace( + wrapper=without_flags[:-1], + program=without_flags[-1], + flags=cmd[len(without_flags) :], + ) + + return provided + + +@template +def sysroot(host_or_target, target_sysroot=None): + assert target_sysroot or host_or_target is target + bootstrap_target_when = target_is_linux_or_wasi + if host_or_target is host: + host_or_target_str = "host" + opt = "--with-host-sysroot" + env = "HOST_SYSROOT" + when = depends(host)(lambda h: h.kernel == "Linux") + + # Only bootstrap a host sysroot when using a bootstrapped target sysroot + # or when the target doesn't use a bootstrapped sysroot in the first place. + @depends(when, bootstrap_target_when, target_sysroot.bootstrapped) + def bootstrap_when(when, bootstrap_target_when, bootstrapped): + return when and (bootstrapped or not bootstrap_target_when) + + else: + assert host_or_target is target + host_or_target_str = "target" + opt = "--with-sysroot" + env = "SYSROOT" + when = target_is_linux_or_wasi + bootstrap_when = bootstrap_target_when + + option( + opt, + env=env, + nargs=1, + when=when, + help="Use the given sysroot directory for %s build" % host_or_target_str, + ) + + sysroot_input = depends(opt, when=when)(lambda x: x) + bootstrap_sysroot = depends(bootstrap_when, sysroot_input)( + # Only bootstrap when no flag was explicitly given (either --with or --without) + lambda bootstrap, input: bootstrap + and not input + and input.origin == "default" + ) + + @depends( + sysroot_input, + host_or_target, + macos_sdk, + bootstrap_path( + depends(host_or_target)(lambda t: "sysroot-{}".format(t.toolchain)), + when=bootstrap_sysroot, + ), + ) + @imports("os") + def sysroot(sysroot_input, host_or_target, macos_sdk, path): + version = None + if sysroot_input: + path = sysroot_input[0] + elif host_or_target.kernel == "Darwin" and macos_sdk: + path = macos_sdk + if path: + # Find the version of libstdc++ headears in the sysroot + include = os.path.join(path, "usr/include/c++") + if os.path.isdir(include): + with os.scandir(include) as d: + version = max(Version(e.name) for e in d if e.is_dir()) + log.info("Using %s sysroot in %s", host_or_target_str, path) + return namespace( + path=path, + bootstrapped=bool(path and not sysroot_input), + stdcxx_version=version, + ) + + return sysroot + + +target_sysroot = sysroot(target) + + +# Use `system_lib_option` instead of `option` for options that enable building +# with a system library for which the development headers are not available in +# the bootstrapped sysroots. +@template +def system_lib_option(name, *args, **kwargs): + option(name, *args, **kwargs) + + @depends(name, target_sysroot.bootstrapped) + def no_system_lib_in_sysroot(value, bootstrapped): + if bootstrapped and value: + die( + "%s is not supported with bootstrapped sysroot. " + "Drop the option, or use --without-sysroot or --disable-bootstrap", + value.format(name), + ) + + +host_sysroot = sysroot(host, target_sysroot) + + +@template +def multiarch_dir(host_or_target): + sysroot = { + host: host_sysroot, + target: target_sysroot, + }[host_or_target] + + @depends(host_or_target, when=sysroot.path) + def multiarch_dir(target): + if target.cpu == "x86": + # Turn e.g. i686-linux-gnu into i386-linux-gnu + return target.toolchain.replace(target.raw_cpu, "i386") + return target.toolchain + + return multiarch_dir + + +target_multiarch_dir = multiarch_dir(target) +host_multiarch_dir = multiarch_dir(host) + + +def minimum_gcc_version(): + return Version("8.1.0") + + +@template +def compiler( + language, + host_or_target, + c_compiler=None, + other_compiler=None, + other_c_compiler=None, +): + """Template handling the generic base checks for the compiler for the + given `language` on the given platform (`host_or_target`). + `host_or_target` is either `host` or `target` (the @depends functions + from init.configure. + When the language is 'C++', `c_compiler` is the result of the `compiler` + template for the language 'C' for the same `host_or_target`. + When `host_or_target` is `host`, `other_compiler` is the result of the + `compiler` template for the same `language` for `target`. + When `host_or_target` is `host` and the language is 'C++', + `other_c_compiler` is the result of the `compiler` template for the + language 'C' for `target`. + """ + assert host_or_target in {host, target, wasm} + assert language in ("C", "C++") + assert language == "C" or c_compiler is not None + assert host_or_target is target or other_compiler is not None + assert language == "C" or host_or_target is target or other_c_compiler is not None + + host_or_target_str = { + host: "host", + target: "target", + wasm: "wasm", + }[host_or_target] + + sysroot = { + host: host_sysroot, + target: target_sysroot, + wasm: dependable(lambda: namespace(path=None)), + }[host_or_target] + + multiarch_dir = { + host: host_multiarch_dir, + target: target_multiarch_dir, + wasm: never, + }[host_or_target] + + var = { + ("C", target): "CC", + ("C++", target): "CXX", + ("C", host): "HOST_CC", + ("C++", host): "HOST_CXX", + ("C", wasm): "WASM_CC", + ("C++", wasm): "WASM_CXX", + }[language, host_or_target] + + default_compilers = { + "C": lambda: default_c_compilers(host_or_target, other_compiler), + "C++": lambda: default_cxx_compilers( + c_compiler, other_c_compiler, other_compiler + ), + }[language]() + + what = "the %s %s compiler" % (host_or_target_str, language) + + option(env=var, nargs=1, help="Path to %s" % what) + + # Handle the compiler given by the user through one of the CC/CXX/HOST_CC/ + # HOST_CXX variables. + provided_compiler = provided_program(var) + + # Normally, we'd use `var` instead of `_var`, but the interaction with + # old-configure complicates things, and for now, we a) can't take the plain + # result from check_prog as CC/CXX/HOST_CC/HOST_CXX and b) have to let + # old-configure AC_SUBST it (because it's autoconf doing it, not us) + compiler = check_prog( + "_%s" % var, + what=what, + progs=default_compilers, + input=provided_compiler.program, + paths=clang_search_path, + ) + + @depends( + configure_cache, + compiler, + provided_compiler, + compiler_wrapper, + host_or_target, + sysroot, + macos_target, + android_version, + vc_compiler_version, + multiarch_dir, + winsysroot, + host, + ) + @checking("whether %s can be used" % what, lambda x: bool(x)) + @imports(_from="mozbuild.shellutil", _import="quote") + @imports("os") + def valid_compiler( + configure_cache, + compiler, + provided_compiler, + compiler_wrapper, + host_or_target, + sysroot, + macos_target, + android_version, + vc_compiler_version, + multiarch_dir, + winsysroot, + host, + ): + wrapper = list(compiler_wrapper or ()) + flags = [] + if sysroot.path: + if host_or_target.kernel == "Darwin": + # While --sysroot and -isysroot are roughly equivalent, when not using + # -isysroot on mac, clang takes the SDKROOT environment variable into + # consideration, which may be set by python and break things. + flags.extend(("-isysroot", sysroot.path)) + else: + flags.extend(("--sysroot", sysroot.path)) + if provided_compiler: + wrapper.extend(provided_compiler.wrapper) + flags.extend(provided_compiler.flags) + + info = check_compiler( + configure_cache, + wrapper + [compiler] + flags, + language, + host_or_target, + android_version, + ) + + if host_or_target.os == "OSX" and macos_target: + flags.append("-mmacosx-version-min=%s" % macos_target) + + # When not given an explicit compatibility version, clang-cl tries + # to get one from MSVC, which might not even be the one used by the + # build. And when it can't find one, its default might also not match + # what the build is using. So if we were able to figure out the version + # we're building with, explicitly use that. + # This also means that, as a side effect, clang-cl will not try to find + # MSVC, which saves a little overhead. + if info.type == "clang-cl" and vc_compiler_version: + flags.append(f"-fms-compatibility-version={vc_compiler_version}") + + if info.type == "clang" and language == "C++" and host_or_target.os == "OSX": + flags.append("-stdlib=libc++") + + # Check that the additional flags we got are enough to not require any + # more flags. If we get an exception, just ignore it; it's liable to be + # invalid command-line flags, which means the compiler we're checking + # doesn't support those command-line flags and will fail one or more of + # the checks below. + try: + if info.flags: + flags += info.flags + info = check_compiler( + configure_cache, + wrapper + [compiler] + flags, + language, + host_or_target, + android_version, + ) + except FatalCheckError: + pass + + if not info.target_cpu or info.target_cpu != host_or_target.cpu: + raise FatalCheckError( + "%s %s compiler target CPU (%s) does not match --%s CPU (%s)" + % ( + host_or_target_str.capitalize(), + language, + info.target_cpu or "unknown", + host_or_target_str, + host_or_target.raw_cpu, + ) + ) + + if not info.target_kernel or (info.target_kernel != host_or_target.kernel): + raise FatalCheckError( + "%s %s compiler target kernel (%s) does not match --%s kernel (%s)" + % ( + host_or_target_str.capitalize(), + language, + info.target_kernel or "unknown", + host_or_target_str, + host_or_target.kernel, + ) + ) + + if not info.target_endianness or ( + info.target_endianness != host_or_target.endianness + ): + raise FatalCheckError( + "%s %s compiler target endianness (%s) does not match --%s " + "endianness (%s)" + % ( + host_or_target_str.capitalize(), + language, + info.target_endianness or "unknown", + host_or_target_str, + host_or_target.endianness, + ) + ) + + # Compiler version checks + # =================================================== + # Check the compiler version here instead of in `compiler_version` so + # that the `checking` message doesn't pretend the compiler can be used + # to then bail out one line later. + if info.type == "gcc": + if host_or_target.os == "Android": + raise FatalCheckError( + "GCC is not supported on Android.\n" + "Please use clang from the Android NDK instead." + ) + gcc_version = minimum_gcc_version() + if info.version < gcc_version: + raise FatalCheckError( + "Only GCC %d.%d or newer is supported (found version %s)." + % (gcc_version.major, gcc_version.minor, info.version) + ) + + # Force GCC to use the C++ headers from the sysroot, and to prefer the + # sysroot system headers to /usr/include. + # Non-Debian GCC also doesn't look at headers in multiarch directory. + if sysroot.bootstrapped and sysroot.stdcxx_version: + version = sysroot.stdcxx_version + for path in ( + "usr/include/c++/{}".format(version), + "usr/include/{}/c++/{}".format(multiarch_dir, version), + "usr/include/{}".format(multiarch_dir), + "usr/include", + ): + flags.extend(("-isystem", os.path.join(sysroot.path, path))) + + if info.type == "clang-cl": + if info.version < "9.0.0": + raise FatalCheckError( + "Only clang-cl 9.0 or newer is supported (found version %s)" + % info.version + ) + if winsysroot and host.os != "WINNT": + overlay = os.path.join(winsysroot, "overlay.yaml") + if os.path.exists(overlay): + overlay_flags = ["-Xclang", "-ivfsoverlay", "-Xclang", overlay] + if info.version >= "16.0" or ( + # clang-cl 15 normally doesn't support the root-relative + # overlay we use, but the bootstrapped clang-cl 15 is patched + # to support it, so check we're using a patched version. + info.version >= "15.0" + and try_preprocess( + configure_cache, + [compiler] + flags + overlay_flags, + language, + "", + onerror=lambda: False, + wrapper=wrapper, + ) + ): + flags.extend(overlay_flags) + + if (info.type, host_or_target.abi) in ( + ("clang", "msvc"), + ("clang-cl", "mingw"), + ): + raise FatalCheckError("Unknown compiler or compiler not supported.") + + # If you want to bump the version check here ensure the version + # is known for Xcode in get_compiler_info. + if info.type == "clang" and info.version < "8.0": + raise FatalCheckError( + "Only clang/llvm 8.0 or newer is supported (found version %s)." + % info.version + ) + + if host_or_target.kernel == "WASI": + if info.type != "clang": + raise FatalCheckError( + "Only clang is supported for %s" % host_or_target.alias + ) + if info.version < "8.0": + raise FatalCheckError( + "Only clang/llvm 8.0 or newer is supported for %s (found version %s)." + % (host_or_target.alias, info.version) + ) + + if host_or_target.os == "Android": + # Need at least clang 13 for compiler-rt/libunwind being the default. + if info.type == "clang" and info.version < "13.0": + raise FatalCheckError( + "Only clang/llvm 13.0 or newer is supported for %s (found version %s)." + % (host_or_target.alias, info.version) + ) + + if info.flags: + raise FatalCheckError("Unknown compiler or compiler not supported.") + + return namespace( + wrapper=wrapper, + compiler=compiler, + flags=flags, + type=info.type, + version=info.version, + language=language, + ) + + @depends(valid_compiler) + @checking("%s version" % what) + def compiler_version(compiler): + return compiler.version + + if language == "C++": + + @depends(valid_compiler, c_compiler) + def valid_compiler(compiler, c_compiler): + if compiler.type != c_compiler.type: + die( + "The %s C compiler is %s, while the %s C++ compiler is " + "%s. Need to use the same compiler suite.", + host_or_target_str, + c_compiler.type, + host_or_target_str, + compiler.type, + ) + + if compiler.version != c_compiler.version: + die( + "The %s C compiler is version %s, while the %s C++ " + "compiler is version %s. Need to use the same compiler " + "version.", + host_or_target_str, + c_compiler.version, + host_or_target_str, + compiler.version, + ) + return compiler + + # Set CC/CXX/HOST_CC/HOST_CXX for old-configure, which needs the wrapper + # and the flags that were part of the user input for those variables to + # be provided. + add_old_configure_assignment( + var, + depends_if(valid_compiler)( + lambda x: list(x.wrapper) + [x.compiler] + list(x.flags) + ), + ) + + if host_or_target is target: + add_old_configure_assignment( + "ac_cv_prog_%s" % var, + depends_if(valid_compiler)( + lambda x: list(x.wrapper) + [x.compiler] + list(x.flags) + ), + ) + # We check that it works in python configure already. + add_old_configure_assignment("ac_cv_prog_%s_works" % var.lower(), "yes") + add_old_configure_assignment( + "ac_cv_prog_%s_cross" % var.lower(), + depends(cross_compiling)(lambda x: "yes" if x else "no"), + ) + gcc_like = depends(valid_compiler.type)( + lambda x: "yes" if x in ("gcc", "clang") else "no" + ) + add_old_configure_assignment("ac_cv_prog_%s_g" % var.lower(), gcc_like) + if language == "C": + add_old_configure_assignment("ac_cv_prog_gcc", gcc_like) + if language == "C++": + add_old_configure_assignment("ac_cv_prog_gxx", gcc_like) + + # Set CC_TYPE/CC_VERSION/HOST_CC_TYPE/HOST_CC_VERSION to allow + # old-configure to do some of its still existing checks. + if language == "C": + set_config("%s_TYPE" % var, valid_compiler.type) + add_old_configure_assignment("%s_TYPE" % var, valid_compiler.type) + set_config( + "%s_VERSION" % var, depends(valid_compiler.version)(lambda v: str(v)) + ) + + valid_compiler = compiler_class(valid_compiler, host_or_target) + + def compiler_error(): + raise FatalCheckError( + "Failed compiling a simple %s source with %s" % (language, what) + ) + + valid_compiler.try_compile(check_msg="%s works" % what, onerror=compiler_error) + + set_config("%s_BASE_FLAGS" % var, valid_compiler.flags) + + # Set CPP/CXXCPP for both the build system and old-configure. We don't + # need to check this works for preprocessing, because we already relied + # on $CC -E/$CXX -E doing preprocessing work to validate the compiler + # in the first place. + if host_or_target is target: + pp_var = { + "C": "CPP", + "C++": "CXXCPP", + }[language] + + preprocessor = depends_if(valid_compiler)( + lambda x: list(x.wrapper) + [x.compiler, "-E"] + list(x.flags) + ) + + set_config(pp_var, preprocessor) + add_old_configure_assignment(pp_var, preprocessor) + + if language == "C": + linker_var = { + target: "LD", + host: "HOST_LD", + }.get(host_or_target) + + if linker_var: + + @deprecated_option(env=linker_var, nargs=1) + def linker(value): + if value: + return value[0] + + @depends(linker) + def unused_linker(linker): + if linker: + log.warning( + "The value of %s is not used by this build system." % linker_var + ) + + return valid_compiler + + +c_compiler = compiler("C", target) +cxx_compiler = compiler("C++", target, c_compiler=c_compiler) +host_c_compiler = compiler("C", host, other_compiler=c_compiler) +host_cxx_compiler = compiler( + "C++", + host, + c_compiler=host_c_compiler, + other_compiler=cxx_compiler, + other_c_compiler=c_compiler, +) + + +@template +def windows_abi(host_or_target, c_compiler): + @depends(host_or_target) + def windows_abi(host_or_target): + if host_or_target.os == "WINNT": + return host_or_target.abi + + @depends(host_or_target, windows_abi) + def need_windows_abi_from_compiler(host_or_target, windows_abi): + return host_or_target.os == "WINNT" and windows_abi is None + + @depends(host_or_target, c_compiler, when=need_windows_abi_from_compiler) + def windows_abi_from_compiler(host_or_target, c_compiler): + if host_or_target.os == "WINNT": + if c_compiler.type == "clang-cl": + return "msvc" + return "mingw" + + return windows_abi | windows_abi_from_compiler + + +target_windows_abi = windows_abi(target, c_compiler) +host_windows_abi = windows_abi(host, host_c_compiler) + + +# Generic compiler-based conditions. +building_with_gcc = depends(c_compiler)(lambda info: info.type == "gcc") + + +@depends(cxx_compiler, ccache_prefix) +@imports("os") +def cxx_is_icecream(info, ccache_prefix): + if ( + os.path.islink(info.compiler) + and os.path.basename(os.readlink(info.compiler)) == "icecc" + ): + return True + if ccache_prefix and os.path.basename(ccache_prefix) == "icecc": + return True + + +set_config("CXX_IS_ICECREAM", cxx_is_icecream) + + +# Libstdc++ compatibility hacks +# ============================================================== +# +@depends(target, host) +def target_or_host_is_linux(target, host): + return any(t.os == "GNU" and t.kernel == "Linux" for t in (target, host)) + + +option( + "--enable-stdcxx-compat", + env="MOZ_STDCXX_COMPAT", + help="Enable compatibility with older libstdc++", + when=target_or_host_is_linux, +) + + +@depends("--enable-stdcxx-compat", when=target_or_host_is_linux) +def stdcxx_compat(value): + if value: + return True + + +set_config("MOZ_STDCXX_COMPAT", True, when=stdcxx_compat) + + +# Linker detection +# ============================================================== +# The policy is as follows: +# For Windows: +# - the linker is picked via the LINKER environment variable per windows.configure, +# but ought to be lld-link in any case. +# For macOS: +# - the linker is lld if the clang used is >= 15 (per LLVM version, not Xcode version). +# - the linker is also lld on local developer builds if the clang used is >= 13 (per LLVM +# version, not Xcode version) +# - otherwise the linker is ld64, either from XCode on macOS, or from cctools-ports when +# cross-compiling. +# For other OSes: +# - on local developer builds: lld if present and the compiler is clang. Otherwise gold +# is used if present otherwise, whatever the compiler uses by default. +# - on release/official builds: whatever the compiler uses by default, except when the +# compiler is clang, in which case lld is preferred when it's new enough. +@template +def is_not_winnt_or_sunos(host_or_target): + @depends(host_or_target) + def is_not_winnt_or_sunos(host_or_target): + if host_or_target.kernel not in ("WINNT", "SunOS"): + return True + + return is_not_winnt_or_sunos + + +is_linker_option_enabled = is_not_winnt_or_sunos(target) + + +@deprecated_option("--enable-gold", env="MOZ_FORCE_GOLD", when=is_linker_option_enabled) +def enable_gold(value): + if value: + die("--enable-gold is deprecated, use --enable-linker=gold instead") + else: + die("--disable-gold is deprecated, use --enable-linker=something_else instead") + + +option( + "--enable-linker", + nargs=1, + help="Select the linker {bfd, gold, ld64, lld, lld-*, mold}", + when=is_linker_option_enabled, +) + + +# No-op to enable depending on --enable-linker from default_elfhack in +# toolkit/moz.configure. +@depends("--enable-linker", when=is_linker_option_enabled) +def enable_linker(linker): + return linker + + +@template +def select_linker_tmpl(host_or_target): + if host_or_target is target: + deps = depends( + "--enable-linker", + c_compiler, + developer_options, + extra_toolchain_flags, + target, + stdcxx_compat, + when=is_linker_option_enabled, + ) + host_or_target_str = "target" + else: + deps = depends( + dependable(None), + host_c_compiler, + developer_options, + dependable(None), + host, + stdcxx_compat, + when=is_not_winnt_or_sunos(host_or_target), + ) + host_or_target_str = "host" + + @deps + @checking(f"for {host_or_target_str} linker", lambda x: x.KIND) + @imports("os") + @imports("shutil") + def select_linker( + linker, c_compiler, developer_options, toolchain_flags, target, stdcxx_compat + ): + if linker: + linker = linker[0] + else: + linker = None + + def is_valid_linker(linker): + if target.kernel == "Darwin": + valid_linkers = ("ld64", "lld") + else: + valid_linkers = ("bfd", "gold", "lld", "mold") + if linker in valid_linkers: + return True + if "lld" in valid_linkers and linker.startswith("lld-"): + return True + return False + + if linker and not is_valid_linker(linker): + # Check that we are trying to use a supported linker + die("Unsupported linker " + linker) + + # Check the kind of linker + version_check = ["-Wl,--version"] + cmd_base = c_compiler.wrapper + [c_compiler.compiler] + c_compiler.flags + + def try_linker(linker): + # Generate the compiler flag + if linker == "ld64": + linker_flag = ["-fuse-ld=ld"] + elif linker: + linker_flag = ["-fuse-ld=" + linker] + else: + linker_flag = [] + cmd = cmd_base + linker_flag + version_check + if toolchain_flags: + cmd += toolchain_flags + + # ld64 doesn't have anything to print out a version. It does print out + # "ld64: For information on command line options please use 'man ld'." + # but that would require doing two attempts, one with --version, that + # would fail, and another with --help. + # Instead, abuse its LD_PRINT_OPTIONS feature to detect a message + # specific to it on stderr when it fails to process --version. + env = dict(os.environ) + env["LD_PRINT_OPTIONS"] = "1" + # Some locales might not print out the strings we are looking for, so + # ensure consistent output. + env["LC_ALL"] = "C" + retcode, stdout, stderr = get_cmd_output(*cmd, env=env) + if retcode == 1 and "Logging ld64 options" in stderr: + kind = "ld64" + + elif retcode != 0: + return None + + elif "mold" in stdout: + kind = "mold" + + elif "GNU ld" in stdout: + # We are using the normal linker + kind = "bfd" + + elif "GNU gold" in stdout: + kind = "gold" + + elif "LLD" in stdout: + kind = "lld" + + else: + kind = "unknown" + + if kind == "unknown" or is_valid_linker(kind): + return namespace( + KIND=kind, + LINKER_FLAG=linker_flag, + ) + + result = None + if linker: + result = try_linker(linker) + if result is None: + die("Could not use {} as linker".format(linker)) + + if ( + result is None + and c_compiler.type == "clang" + and ( + ( + target.kernel != "Darwin" + and ( + developer_options + or host_or_target_str == "host" + or c_compiler.version >= "15.0" + ) + ) + or ( + target.kernel == "Darwin" + and ( + (developer_options and c_compiler.version >= "13.0") + or c_compiler.version >= "15.0" + ) + ) + ) + ): + result = try_linker("lld") + + if result is None and developer_options and not stdcxx_compat: + result = try_linker("gold") + + if result is None: + result = try_linker(None) + + if result is None: + die("Failed to find an adequate linker") + + if stdcxx_compat and result.KIND == "gold": + die("--enable-stdcxx-compat is not compatible with the gold linker") + + # If an explicit linker was given, error out if what we found is different. + if linker and not linker.startswith(result.KIND): + die("Could not use {} as linker".format(linker)) + + return result + + return select_linker + + +select_linker = select_linker_tmpl(target) +set_config("LINKER_KIND", select_linker.KIND) + + +@template +def linker_ldflags_tmpl(host_or_target): + if host_or_target is target: + deps = depends_if( + select_linker, + target, + target_sysroot, + target_multiarch_dir, + android_sysroot, + android_version, + c_compiler, + developer_options, + ) + else: + deps = depends_if( + select_linker_tmpl(host), + host, + host_sysroot, + host_multiarch_dir, + dependable(None), + dependable(None), + host_c_compiler, + developer_options, + ) + + @deps + @imports("os") + def linker_ldflags( + linker, + target, + sysroot, + multiarch_dir, + android_sysroot, + android_version, + c_compiler, + developer_options, + ): + flags = list((linker and linker.LINKER_FLAG) or []) + # rpath-link is irrelevant to wasm, see for more info https://github.com/emscripten-core/emscripten/issues/11076. + if sysroot.path and multiarch_dir and target.os != "WASI": + for d in ("lib", "usr/lib"): + multiarch_lib_dir = os.path.join(sysroot.path, d, multiarch_dir) + if os.path.exists(multiarch_lib_dir): + # Non-Debian-patched binutils linkers (both BFD and gold) don't lookup + # in multi-arch directories. + flags.append("-Wl,-rpath-link,%s" % multiarch_lib_dir) + # GCC also needs -L. + if c_compiler.type == "gcc": + flags.append("-L%s" % multiarch_lib_dir) + if ( + c_compiler.type == "gcc" + and sysroot.bootstrapped + and sysroot.stdcxx_version + ): + flags.append( + "-L{}/usr/lib/gcc/{}/{}".format( + sysroot.path, multiarch_dir, sysroot.stdcxx_version + ) + ) + if android_sysroot: + # BFD/gold linkers need a manual --rpath-link for indirect + # dependencies. + flags += [ + "-Wl,--rpath-link={}/usr/lib/{}".format( + android_sysroot, target.toolchain + ), + "-Wl,--rpath-link={}/usr/lib/{}/{}".format( + android_sysroot, target.toolchain, android_version + ), + ] + if ( + developer_options + and linker + and linker.KIND == "lld" + and target.kernel != "WINNT" + ): + flags.append("-Wl,-O0") + return flags + + return linker_ldflags + + +linker_ldflags = linker_ldflags_tmpl(target) +add_old_configure_assignment("LINKER_LDFLAGS", linker_ldflags) + +host_linker_ldflags = linker_ldflags_tmpl(host) +add_old_configure_assignment("HOST_LINKER_LDFLAGS", host_linker_ldflags) + + +# There's a wrinkle with MinGW: linker configuration is not enabled, so +# `select_linker` is never invoked. Hard-code around it. +@depends(select_linker, target, c_compiler) +def gcc_use_gnu_ld(select_linker, target, c_compiler): + if select_linker is not None and target.kernel != "Darwin": + return select_linker.KIND in ("bfd", "gold", "lld", "mold") + if target.kernel == "WINNT" and c_compiler.type == "clang": + return True + return None + + +# GCC_USE_GNU_LD=1 means the linker is command line compatible with GNU ld. +set_config("GCC_USE_GNU_LD", gcc_use_gnu_ld) +add_old_configure_assignment("GCC_USE_GNU_LD", gcc_use_gnu_ld) + + +include("compile-checks.configure") +include("arm.configure", when=depends(target.cpu)(lambda cpu: cpu == "arm")) + + +@depends( + have_64_bit, + try_compile( + body='static_assert(sizeof(void *) == 8, "")', check_msg="for 64-bit OS" + ), +) +def check_have_64_bit(have_64_bit, compiler_have_64_bit): + if have_64_bit != compiler_have_64_bit: + configure_error( + "The target compiler does not agree with configure " + "about the target bitness." + ) + + +@depends(cxx_compiler, target) +def needs_libstdcxx_newness_check(cxx_compiler, target): + # We only have to care about this on Linux and MinGW. + if cxx_compiler.type == "clang-cl": + return + + if target.kernel not in ("Linux", "WINNT"): + return + + if target.os == "Android": + return + + return True + + +def die_on_old_libstdcxx(): + die( + "The libstdc++ in use is not new enough. Please run " + "./mach bootstrap to update your compiler, or update your system " + "libstdc++ installation." + ) + + +try_compile( + includes=["cstddef"], + body="\n".join( + [ + # _GLIBCXX_RELEASE showed up in libstdc++ 7. + "#if defined(__GLIBCXX__) && !defined(_GLIBCXX_RELEASE)", + "# error libstdc++ not new enough", + "#endif", + "#if defined(_GLIBCXX_RELEASE)", + "# if _GLIBCXX_RELEASE < %d" % minimum_gcc_version().major, + "# error libstdc++ not new enough", + "# else", + " (void) 0", + "# endif", + "#endif", + ] + ), + check_msg="for new enough STL headers from libstdc++", + when=needs_libstdcxx_newness_check, + onerror=die_on_old_libstdcxx, +) + + +@depends(c_compiler, target) +def default_debug_flags(compiler_info, target): + # Debug info is ON by default. + if compiler_info.type == "clang-cl": + return "-Z7" + elif target.kernel == "WINNT" and compiler_info.type == "clang": + return "-g -gcodeview" + # The oldest versions of supported compilers default to DWARF-4, but + # newer versions may default to DWARF-5 or newer (e.g. clang 14), which + # Valgrind doesn't support. Force-use DWARF-4. + return "-gdwarf-4" + + +option(env="MOZ_DEBUG_FLAGS", nargs=1, help="Debug compiler flags") + +imply_option("--enable-debug-symbols", depends_if("--enable-debug")(lambda v: v)) + +option( + "--disable-debug-symbols", + nargs="?", + help="Disable debug symbols using the given compiler flags", +) + +set_config("MOZ_DEBUG_SYMBOLS", depends_if("--enable-debug-symbols")(lambda _: True)) + + +@depends("MOZ_DEBUG_FLAGS", "--enable-debug-symbols", default_debug_flags) +def debug_flags(env_debug_flags, enable_debug_flags, default_debug_flags): + # If MOZ_DEBUG_FLAGS is set, and --enable-debug-symbols is set to a value, + # --enable-debug-symbols takes precedence. Note, the value of + # --enable-debug-symbols may be implied by --enable-debug. + if len(enable_debug_flags): + return enable_debug_flags[0] + if env_debug_flags: + return env_debug_flags[0] + return default_debug_flags + + +set_config("MOZ_DEBUG_FLAGS", debug_flags) +add_old_configure_assignment("MOZ_DEBUG_FLAGS", debug_flags) + + +@depends(c_compiler, host) +@imports( + _from="mach.logging", _import="enable_blessed", _as="_enable_ansi_escape_codes" +) +def color_cflags(info, host): + # We could test compiling with flags. By why incur the overhead when + # color support should always be present in a specific toolchain + # version? + + # Code for auto-adding this flag to compiler invocations needs to + # determine if an existing flag isn't already present. That is likely + # using exact string matching on the returned value. So if the return + # value changes to e.g. "<x>=always", exact string match may fail and + # multiple color flags could be added. So examine downstream consumers + # before adding flags to return values. + if info.type == "gcc": + return "-fdiagnostics-color" + elif info.type in ["clang", "clang-cl"]: + if host.os == "WINNT" and _enable_ansi_escape_codes(): + return "-fcolor-diagnostics -fansi-escape-codes" + else: + return "-fcolor-diagnostics" + else: + return "" + + +set_config("COLOR_CFLAGS", color_cflags) + +# Some standard library headers (notably bionic on Android) declare standard +# functions (e.g. getchar()) and also #define macros for those standard +# functions. libc++ deals with this by doing something like the following +# (explanatory comments added): +# +# #ifdef FUNC +# // Capture the definition of FUNC. +# inline _LIBCPP_INLINE_VISIBILITY int __libcpp_FUNC(...) { return FUNC(...); } +# #undef FUNC +# // Use a real inline definition. +# inline _LIBCPP_INLINE_VISIBILITY int FUNC(...) { return _libcpp_FUNC(...); } +# #endif +# +# _LIBCPP_INLINE_VISIBILITY is typically defined as: +# +# __attribute__((__visibility__("hidden"), __always_inline__)) +# +# Unfortunately, this interacts badly with our system header wrappers, as the: +# +# #pragma GCC visibility push(default) +# +# that they do prior to including the actual system header is treated by the +# compiler as an explicit declaration of visibility on every function declared +# in the header. Therefore, when the libc++ code above is encountered, it is +# as though the compiler has effectively seen: +# +# int FUNC(...) __attribute__((__visibility__("default"))); +# int FUNC(...) __attribute__((__visibility__("hidden"))); +# +# and the compiler complains about the mismatched visibility declarations. +# +# However, libc++ will only define _LIBCPP_INLINE_VISIBILITY if there is no +# existing definition. We can therefore define it to the empty string (since +# we are properly managing visibility ourselves) and avoid this whole mess. +# Note that we don't need to do this with gcc, as libc++ detects gcc and +# effectively does the same thing we are doing here. +# +# _LIBCPP_ALWAYS_INLINE needs a similar workarounds, since it too declares +# hidden visibility. +# +# _LIBCPP_HIDE_FROM_ABI is a macro in libc++ versions in NDKs >=r19. It too +# declares hidden visibility, but it also declares functions as excluded from +# explicit instantiation (roughly: the function can be unused in the current +# compilation, but does not then trigger an actual definition of the function; +# it is assumed the real definition comes from elsewhere). We need to replicate +# this setup. + + +@depends(c_compiler, target) +def libcxx_override_visibility(c_compiler, target): + if c_compiler.type == "clang" and target.os == "Android": + return namespace( + empty="", + hide_from_abi="__attribute__((__exclude_from_explicit_instantiation__))", + ) + + +set_define("_LIBCPP_INLINE_VISIBILITY", libcxx_override_visibility.empty) +set_define("_LIBCPP_ALWAYS_INLINE", libcxx_override_visibility.empty) + +set_define("_LIBCPP_HIDE_FROM_ABI", libcxx_override_visibility.hide_from_abi) + + +@depends(target, build_environment) +def visibility_flags(target, env): + if target.os != "WINNT": + if target.kernel == "Darwin": + return ("-fvisibility=hidden", "-fvisibility-inlines-hidden") + return ( + "-I%s/system_wrappers" % os.path.join(env.dist), + "-include", + "%s/config/gcc_hidden.h" % env.topsrcdir, + ) + + +@depends(target, visibility_flags) +def wrap_system_includes(target, visibility_flags): + if visibility_flags and target.kernel != "Darwin": + return True + + +set_define( + "HAVE_VISIBILITY_HIDDEN_ATTRIBUTE", + depends(visibility_flags)(lambda v: bool(v) or None), +) +set_define( + "HAVE_VISIBILITY_ATTRIBUTE", depends(visibility_flags)(lambda v: bool(v) or None) +) +set_config("WRAP_SYSTEM_INCLUDES", wrap_system_includes) +set_config("VISIBILITY_FLAGS", visibility_flags) + + +@template +def depend_cflags(host_or_target_c_compiler): + @depends(host_or_target_c_compiler) + def depend_cflags(host_or_target_c_compiler): + if host_or_target_c_compiler.type != "clang-cl": + return ["-MD", "-MP", "-MF $(MDDEPDIR)/$(@F).pp"] + else: + # clang-cl doesn't accept the normal -MD -MP -MF options that clang + # does, but the underlying cc1 binary understands how to generate + # dependency files. These options are based on analyzing what the + # normal clang driver sends to cc1 when given the "correct" + # dependency options. + return [ + "-Xclang", + "-MP", + "-Xclang", + "-dependency-file", + "-Xclang", + "$(MDDEPDIR)/$(@F).pp", + "-Xclang", + "-MT", + "-Xclang", + "$@", + ] + + return depend_cflags + + +set_config("_DEPEND_CFLAGS", depend_cflags(c_compiler)) +set_config("_HOST_DEPEND_CFLAGS", depend_cflags(host_c_compiler)) + + +@depends(c_compiler) +def preprocess_option(compiler): + # The uses of PREPROCESS_OPTION depend on the spacing for -o/-Fi. + if compiler.type in ("gcc", "clang"): + return "-E -o " + else: + return "-P -Fi" + + +set_config("PREPROCESS_OPTION", preprocess_option) + + +# We only want to include windows.configure when we are compiling on +# Windows, or for Windows. +include("windows.configure", when=is_windows) + + +# On Power ISA, determine compiler flags for VMX, VSX and VSX-3. + +set_config( + "PPC_VMX_FLAGS", + ["-maltivec"], + when=depends(target.cpu)(lambda cpu: cpu.startswith("ppc")), +) + +set_config( + "PPC_VSX_FLAGS", + ["-mvsx"], + when=depends(target.cpu)(lambda cpu: cpu.startswith("ppc")), +) + +set_config( + "PPC_VSX3_FLAGS", + ["-mvsx", "-mcpu=power9"], + when=depends(target.cpu)(lambda cpu: cpu.startswith("ppc")), +) + +# ASAN +# ============================================================== + +option("--enable-address-sanitizer", help="Enable Address Sanitizer") + + +@depends(when="--enable-address-sanitizer") +def asan(): + return True + + +add_old_configure_assignment("MOZ_ASAN", asan) + +# MSAN +# ============================================================== + +option("--enable-memory-sanitizer", help="Enable Memory Sanitizer") + + +@depends(when="--enable-memory-sanitizer") +def msan(): + return True + + +add_old_configure_assignment("MOZ_MSAN", msan) + +# TSAN +# ============================================================== + +option("--enable-thread-sanitizer", help="Enable Thread Sanitizer") + + +@depends(when="--enable-thread-sanitizer") +def tsan(): + return True + + +add_old_configure_assignment("MOZ_TSAN", tsan) + +# UBSAN +# ============================================================== + +option( + "--enable-undefined-sanitizer", nargs="*", help="Enable UndefinedBehavior Sanitizer" +) + + +@depends("--enable-undefined-sanitizer", moz_optimize.optimize) +def ubsan(options, optimize): + if not options: + return + + default_checks = [ + "bool", + "bounds", + "enum", + "function", + "integer-divide-by-zero", + "pointer-overflow", + "return", + "vla-bound", + ] + + # adding object-size generates a warning if -O0 is set + if optimize: + default_checks.append("object-size") + + checks = options if len(options) else default_checks + + return ",".join(checks) + + +add_old_configure_assignment("MOZ_UBSAN_CHECKS", ubsan) + + +option( + "--enable-signed-overflow-sanitizer", + help="Enable UndefinedBehavior Sanitizer (Signed Integer Overflow Parts)", +) + + +@depends(when="--enable-signed-overflow-sanitizer") +def ub_signed_overflow_san(): + return True + + +add_old_configure_assignment("MOZ_SIGNED_OVERFLOW_SANITIZE", ub_signed_overflow_san) + + +option( + "--enable-unsigned-overflow-sanitizer", + help="Enable UndefinedBehavior Sanitizer (Unsigned Integer Overflow Parts)", +) + + +@depends(when="--enable-unsigned-overflow-sanitizer") +def ub_unsigned_overflow_san(): + return True + + +add_old_configure_assignment("MOZ_UNSIGNED_OVERFLOW_SANITIZE", ub_unsigned_overflow_san) + + +# Security Hardening +# ============================================================== + +option( + "--enable-hardening", + env="MOZ_SECURITY_HARDENING", + help="Enables security hardening compiler options", +) + + +# This function is a bit confusing. It adds or removes hardening flags in +# three stuations: if --enable-hardening is passed; if --disable-hardening +# is passed, and if no flag is passed. +# +# At time of this comment writing, all flags are actually added in the +# default no-flag case; making --enable-hardening the same as omitting the +# flag. --disable-hardening will omit the security flags. (However, not all +# possible security flags will be omitted by --disable-hardening, as many are +# compiler-default options we do not explicitly enable.) +@depends( + "--enable-hardening", + "--enable-address-sanitizer", + "--enable-debug", + "--enable-optimize", + c_compiler, + target, +) +def security_hardening_cflags( + hardening_flag, asan, debug, optimize, c_compiler, target +): + compiler_is_gccish = c_compiler.type in ("gcc", "clang") + mingw_clang = c_compiler.type == "clang" and target.os == "WINNT" + + flags = [] + ldflags = [] + trivial_auto_var_init = [] + + # WASI compiler doesn't support security hardening cflags + if target.os == "WASI": + return + + # ---------------------------------------------------------- + # If hardening is explicitly enabled, or not explicitly disabled + if hardening_flag.origin == "default" or hardening_flag: + # FORTIFY_SOURCE ------------------------------------ + # Require optimization for FORTIFY_SOURCE. See Bug 1417452 + # Also, undefine it before defining it just in case a distro adds it, see Bug 1418398 + if compiler_is_gccish and optimize and not asan: + flags.append("-U_FORTIFY_SOURCE") + flags.append("-D_FORTIFY_SOURCE=2") + + # fstack-protector ------------------------------------ + # Enable only if hardening is not disabled and ASAN is + # not on as ASAN will catch the crashes for us + if compiler_is_gccish and not asan: + flags.append("-fstack-protector-strong") + ldflags.append("-fstack-protector-strong") + + if ( + c_compiler.type == "clang" + and c_compiler.version >= "11.0.1" + and target.os not in ("WINNT", "OSX", "OpenBSD") + and target.cpu in ("x86", "x86_64", "ppc64", "s390x") + ): + flags.append("-fstack-clash-protection") + ldflags.append("-fstack-clash-protection") + + # ftrivial-auto-var-init ------------------------------ + # Initialize local variables with a 0xAA pattern in clang builds. + # Linux32 fails some xpcshell tests with -ftrivial-auto-var-init + linux32 = target.kernel == "Linux" and target.cpu == "x86" + if ( + (c_compiler.type == "clang" or c_compiler.type == "clang-cl") + and c_compiler.version >= "8" + and not linux32 + ): + if c_compiler.type == "clang-cl": + trivial_auto_var_init.append("-Xclang") + trivial_auto_var_init.append("-ftrivial-auto-var-init=pattern") + # Always enable on debug builds. + if debug: + flags.extend(trivial_auto_var_init) + + # ASLR ------------------------------------------------ + # ASLR (dynamicbase) is enabled by default in clang-cl; but the + # mingw-clang build requires it to be explicitly enabled + if mingw_clang: + ldflags.append("-Wl,--dynamicbase") + + # Control Flow Guard (CFG) ---------------------------- + if ( + c_compiler.type == "clang-cl" + and c_compiler.version >= "8" + and (target.cpu != "aarch64" or c_compiler.version >= "8.0.1") + ): + if target.cpu == "aarch64" and c_compiler.version >= "10.0.0": + # The added checks in clang 10 make arm64 builds crash. (Bug 1639318) + flags.append("-guard:cf,nochecks") + else: + flags.append("-guard:cf") + # nolongjmp is needed because clang doesn't emit the CFG tables of + # setjmp return addresses https://bugs.llvm.org/show_bug.cgi?id=40057 + ldflags.append("-guard:cf,nolongjmp") + + # ---------------------------------------------------------- + # If ASAN _is_ on, disable FORTIFY_SOURCE just to be safe + if asan: + flags.append("-D_FORTIFY_SOURCE=0") + + # fno-common ----------------------------------------- + # Do not merge variables for ASAN; can detect some subtle bugs + if asan: + # clang-cl does not recognize the flag, it must be passed down to clang + if c_compiler.type == "clang-cl": + flags.append("-Xclang") + flags.append("-fno-common") + + return namespace( + flags=flags, + ldflags=ldflags, + trivial_auto_var_init=trivial_auto_var_init, + ) + + +set_config("MOZ_HARDENING_CFLAGS", security_hardening_cflags.flags) +set_config("MOZ_HARDENING_LDFLAGS", security_hardening_cflags.ldflags) +set_config( + "MOZ_TRIVIAL_AUTO_VAR_INIT", + security_hardening_cflags.trivial_auto_var_init, +) + + +# Intel Control-flow Enforcement Technology +# ============================================================== +# We keep this separate from the hardening flags above, because we want to be +# able to easily remove the flags in the build files for certain executables. +@depends(c_compiler, target) +def cet_ldflags(c_compiler, target): + ldflags = [] + if ( + c_compiler.type == "clang-cl" + and c_compiler.version >= "11" + and target.cpu == "x86_64" + ): + ldflags.append("-CETCOMPAT") + return ldflags + + +set_config("MOZ_CETCOMPAT_LDFLAGS", cet_ldflags) + + +# Frame pointers +# ============================================================== +@depends(c_compiler) +def frame_pointer_flags(compiler): + if compiler.type == "clang-cl": + return namespace( + enable=["-Oy-"], + disable=["-Oy"], + ) + return namespace( + enable=["-fno-omit-frame-pointer", "-funwind-tables"], + disable=["-fomit-frame-pointer", "-funwind-tables"], + ) + + +@depends( + moz_optimize.optimize, + moz_debug, + target, + "--enable-memory-sanitizer", + "--enable-address-sanitizer", + "--enable-undefined-sanitizer", +) +def frame_pointer_default(optimize, debug, target, msan, asan, ubsan): + return bool( + not optimize + or debug + or msan + or asan + or ubsan + or (target.os == "WINNT" and target.cpu in ("x86", "aarch64")) + or target.os == "OSX" + ) + + +option( + "--enable-frame-pointers", + default=frame_pointer_default, + help="{Enable|Disable} frame pointers", +) + + +@depends("--enable-frame-pointers", frame_pointer_flags) +def frame_pointer_flags(enable, flags): + if enable: + return flags.enable + return flags.disable + + +set_config("MOZ_FRAMEPTR_FLAGS", frame_pointer_flags) + + +# Stack unwinding without frame pointers +# ============================================================== + + +have_unwind = check_symbol( + "_Unwind_Backtrace", when=check_header("unwind.h", when=target_is_unix) +) + + +# Code Coverage +# ============================================================== + +option("--enable-coverage", env="MOZ_CODE_COVERAGE", help="Enable code coverage") + + +@depends("--enable-coverage") +def code_coverage(value): + if value: + return True + + +set_config("MOZ_CODE_COVERAGE", code_coverage) +set_define("MOZ_CODE_COVERAGE", code_coverage) + + +@depends(target, c_compiler, build_environment, when=code_coverage) +@imports("os") +@imports("re") +@imports(_from="__builtin__", _import="open") +def coverage_cflags(target, c_compiler, build_env): + cflags = ["--coverage"] + + # clang 11 no longer accepts this flag (its behavior became the default) + if c_compiler.type in ("clang", "clang-cl") and c_compiler.version < "11.0.0": + cflags += [ + "-Xclang", + "-coverage-no-function-names-in-data", + ] + + exclude = [] + if target.os == "WINNT" and c_compiler.type == "clang-cl": + # VS files + exclude.append("^.*[vV][sS]20[0-9]{2}.*$") + # Files in fetches directory. + exclude.append("^.*[\\\\/]fetches[\\\\/].*$") + elif target.os == "OSX": + # Files in fetches directory. + exclude.append("^.*/fetches/.*$") + elif target.os == "GNU": + # Files in fetches directory. + exclude.append("^.*/fetches/.*$") + # Files in /usr/ + exclude.append("^/usr/.*$") + + if exclude: + exclude = ";".join(exclude) + cflags += [ + f"-fprofile-exclude-files={exclude}", + ] + + response_file_path = os.path.join(build_env.topobjdir, "code_coverage_cflags") + + with open(response_file_path, "w") as f: + f.write(" ".join(cflags)) + + return ["@{}".format(response_file_path)] + + +set_config("COVERAGE_CFLAGS", coverage_cflags) + +# Assembler detection +# ============================================================== + +option(env="AS", nargs=1, help="Path to the assembler") + + +@depends(target, c_compiler) +def as_info(target, c_compiler): + if c_compiler.type == "clang-cl": + ml = { + "x86": "ml.exe", + "x86_64": "ml64.exe", + "aarch64": "armasm64.exe", + }.get(target.cpu) + return namespace(type="masm", names=(ml,)) + # When building with anything but clang-cl, we just use the C compiler as the assembler. + return namespace(type="gcc", names=(c_compiler.compiler,)) + + +# One would expect the assembler to be specified merely as a program. But in +# cases where the assembler is passed down into js/, it can be specified in +# the same way as CC: a program + a list of argument flags. We might as well +# permit the same behavior in general, even though it seems somewhat unusual. +# So we have to do the same sort of dance as we did above with +# `provided_compiler`. +provided_assembler = provided_program("AS") +assembler = check_prog( + "_AS", + input=provided_assembler.program, + what="the assembler", + progs=as_info.names, + paths=vc_toolchain_search_path, +) + + +@depends(as_info, assembler, provided_assembler, c_compiler) +def as_with_flags(as_info, assembler, provided_assembler, c_compiler): + if provided_assembler: + return provided_assembler.wrapper + [assembler] + provided_assembler.flags + + if as_info.type == "masm": + return assembler + + assert as_info.type == "gcc" + + # Need to add compiler wrappers and flags as appropriate. + return c_compiler.wrapper + [assembler] + c_compiler.flags + + +set_config("AS", as_with_flags) + + +@depends(assembler, c_compiler, extra_toolchain_flags) +@imports("subprocess") +@imports(_from="os", _import="devnull") +def gnu_as(assembler, c_compiler, toolchain_flags): + # clang uses a compatible GNU assembler. + if c_compiler.type == "clang": + return True + + if c_compiler.type == "gcc": + cmd = [assembler] + c_compiler.flags + if toolchain_flags: + cmd += toolchain_flags + cmd += ["-Wa,--version", "-c", "-o", devnull, "-x", "assembler", "-"] + # We don't actually have to provide any input on stdin, `Popen.communicate` will + # close the stdin pipe. + # clang will error if it uses its integrated assembler for this target, + # so handle failures gracefully. + if "GNU" in check_cmd_output(*cmd, stdin=subprocess.PIPE, onerror=lambda: ""): + return True + + +set_config("GNU_AS", gnu_as) + + +@depends(as_info, target) +def as_dash_c_flag(as_info, target): + # armasm64 doesn't understand -c. + if as_info.type == "masm" and target.cpu == "aarch64": + return "" + else: + return "-c" + + +set_config("AS_DASH_C_FLAG", as_dash_c_flag) + + +@depends(as_info, target) +def as_outoption(as_info, target): + # The uses of ASOUTOPTION depend on the spacing for -o/-Fo. + if as_info.type == "masm" and target.cpu != "aarch64": + return "-Fo" + + return "-o " + + +set_config("ASOUTOPTION", as_outoption) + +# clang plugin handling +# ============================================================== + +option( + "--enable-clang-plugin", + env="ENABLE_CLANG_PLUGIN", + help="Enable building with the Clang plugin (gecko specific static analyzers)", +) + +add_old_configure_assignment( + "ENABLE_CLANG_PLUGIN", depends_if("--enable-clang-plugin")(lambda _: True) +) + + +@depends(host_c_compiler, c_compiler, when="--enable-clang-plugin") +def llvm_config(host_c_compiler, c_compiler): + clang = None + for compiler in (host_c_compiler, c_compiler): + if compiler and compiler.type == "clang": + clang = compiler.compiler + break + elif compiler and compiler.type == "clang-cl": + clang = os.path.join(os.path.dirname(compiler.compiler), "clang") + break + + if not clang: + die("Cannot --enable-clang-plugin when not building with clang") + llvm_config = "llvm-config" + out = check_cmd_output(clang, "--print-prog-name=llvm-config", onerror=lambda: None) + if out: + llvm_config = out.rstrip() + return (llvm_config,) + + +llvm_config = check_prog( + "LLVM_CONFIG", + llvm_config, + what="llvm-config", + when="--enable-clang-plugin", + paths=clang_search_path, +) + +add_old_configure_assignment("LLVM_CONFIG", llvm_config) + + +option( + "--enable-clang-plugin-alpha", + env="ENABLE_CLANG_PLUGIN_ALPHA", + help="Enable static analysis with clang-plugin alpha checks.", +) + + +@depends("--enable-clang-plugin", "--enable-clang-plugin-alpha") +def check_clang_plugin_alpha(enable_clang_plugin, enable_clang_plugin_alpha): + if enable_clang_plugin_alpha: + if enable_clang_plugin: + return True + die("Cannot enable clang-plugin alpha checkers without --enable-clang-plugin.") + + +add_old_configure_assignment("ENABLE_CLANG_PLUGIN_ALPHA", check_clang_plugin_alpha) +set_define("MOZ_CLANG_PLUGIN_ALPHA", check_clang_plugin_alpha) + +option( + "--enable-mozsearch-plugin", + env="ENABLE_MOZSEARCH_PLUGIN", + help="Enable building with the mozsearch indexer plugin", +) + +add_old_configure_assignment( + "ENABLE_MOZSEARCH_PLUGIN", depends_if("--enable-mozsearch-plugin")(lambda _: True) +) + +# Use the old libstdc++ ABI +# ============================================================== +add_flag( + "-D_GLIBCXX_USE_CXX11_ABI=0", + cxx_compiler, + when=stdcxx_compat, +) +add_flag( + "-D_GLIBCXX_USE_CXX11_ABI=0", + host_cxx_compiler, + when=stdcxx_compat, +) + + +# Support various fuzzing options +# ============================================================== +option("--enable-fuzzing", help="Enable fuzzing support") + + +@depends(build_project) +def js_build(build_project): + return build_project == "js" + + +option( + "--enable-js-fuzzilli", + when=js_build, + help="Enable fuzzilli support for the JS engine", +) + + +option( + "--enable-snapshot-fuzzing", + help="Enable experimental snapshot fuzzing support", +) + + +imply_option("--enable-fuzzing", True, when="--enable-snapshot-fuzzing") + + +@depends("--enable-snapshot-fuzzing") +def enable_snapshot_fuzzing(value): + if value: + return True + + +@depends("--enable-fuzzing", enable_snapshot_fuzzing) +def enable_fuzzing(value, snapshot_fuzzing): + if value or snapshot_fuzzing: + return True + + +@depends("--enable-js-fuzzilli", when=js_build) +def enable_js_fuzzilli(value): + if value: + return True + + +@depends(enable_fuzzing, enable_snapshot_fuzzing) +def check_aflfuzzer(fuzzing, snapshot_fuzzing): + if fuzzing and not snapshot_fuzzing: + return True + + +@depends( + try_compile( + body="__AFL_COMPILER;", check_msg="for AFL compiler", when=check_aflfuzzer + ) +) +def enable_aflfuzzer(afl): + if afl: + return True + + +@depends(enable_fuzzing, enable_aflfuzzer, enable_snapshot_fuzzing, c_compiler, target) +def enable_libfuzzer(fuzzing, afl, snapshot_fuzzing, c_compiler, target): + if ( + fuzzing + and not afl + and not snapshot_fuzzing + and c_compiler.type == "clang" + and target.os != "Android" + ): + return True + + +@depends(enable_fuzzing, enable_aflfuzzer, enable_libfuzzer, enable_js_fuzzilli) +def enable_fuzzing_interfaces(fuzzing, afl, libfuzzer, enable_js_fuzzilli): + if fuzzing and (afl or libfuzzer) and not enable_js_fuzzilli: + return True + + +set_config("FUZZING", enable_fuzzing) +set_define("FUZZING", enable_fuzzing) + +set_config("LIBFUZZER", enable_libfuzzer) +set_define("LIBFUZZER", enable_libfuzzer) +add_old_configure_assignment("LIBFUZZER", enable_libfuzzer) + +set_config("AFLFUZZ", enable_aflfuzzer) +set_define("AFLFUZZ", enable_aflfuzzer) + +set_config("FUZZING_INTERFACES", enable_fuzzing_interfaces) +set_define("FUZZING_INTERFACES", enable_fuzzing_interfaces) +add_old_configure_assignment("FUZZING_INTERFACES", enable_fuzzing_interfaces) + +set_config("FUZZING_JS_FUZZILLI", enable_js_fuzzilli) +set_define("FUZZING_JS_FUZZILLI", enable_js_fuzzilli) + +set_config("FUZZING_SNAPSHOT", enable_snapshot_fuzzing) +set_define("FUZZING_SNAPSHOT", enable_snapshot_fuzzing) + + +@depends( + c_compiler.try_compile( + flags=["-fsanitize=fuzzer-no-link"], + when=enable_fuzzing, + check_msg="whether the C compiler supports -fsanitize=fuzzer-no-link", + ), + tsan, + enable_js_fuzzilli, +) +def libfuzzer_flags(value, tsan, enable_js_fuzzilli): + if tsan: + # With ThreadSanitizer, we should not use any libFuzzer instrumentation because + # it is incompatible (e.g. there are races on global sanitizer coverage counters). + # Instead we use an empty set of flags here but still build the fuzzing targets. + # With this setup, we can still run files through these targets in TSan builds, + # e.g. those obtained from regular fuzzing. + # This code can be removed once libFuzzer has been made compatible with TSan. + # + # Also, this code needs to be kept in sync with certain gyp files, currently: + # - dom/media/webrtc/transport/third_party/nICEr/nicer.gyp + return namespace(no_link_flag_supported=False, use_flags=[]) + + if enable_js_fuzzilli: + # Fuzzilli comes with its own trace-pc interceptors and flag requirements. + no_link_flag_supported = False + use_flags = ["-fsanitize-coverage=trace-pc-guard", "-g"] + elif value: + no_link_flag_supported = True + # recommended for (and only supported by) clang >= 6 + use_flags = ["-fsanitize=fuzzer-no-link"] + else: + no_link_flag_supported = False + use_flags = ["-fsanitize-coverage=trace-pc-guard,trace-cmp"] + + return namespace( + no_link_flag_supported=no_link_flag_supported, + use_flags=use_flags, + ) + + +set_config("HAVE_LIBFUZZER_FLAG_FUZZER_NO_LINK", libfuzzer_flags.no_link_flag_supported) +set_config("LIBFUZZER_FLAGS", libfuzzer_flags.use_flags) +add_old_configure_assignment("LIBFUZZER_FLAGS", libfuzzer_flags.use_flags) + +# Shared library building +# ============================================================== + + +# XXX: The use of makefile constructs in these variables is awful. +@depends(target, c_compiler) +def make_shared_library(target, compiler): + if target.os == "WINNT": + if compiler.type == "gcc": + return namespace( + mkshlib=["$(CXX)", "$(DSO_LDOPTS)", "-o", "$@"], + mkcshlib=["$(CC)", "$(DSO_LDOPTS)", "-o", "$@"], + ) + elif compiler.type == "clang": + return namespace( + mkshlib=[ + "$(CXX)", + "$(DSO_LDOPTS)", + "-Wl,-pdb,$(LINK_PDBFILE)", + "-o", + "$@", + ], + mkcshlib=[ + "$(CC)", + "$(DSO_LDOPTS)", + "-Wl,-pdb,$(LINK_PDBFILE)", + "-o", + "$@", + ], + ) + else: + linker = [ + "$(LINKER)", + "-NOLOGO", + "-DLL", + "-OUT:$@", + "-PDB:$(LINK_PDBFILE)", + "$(DSO_LDOPTS)", + ] + return namespace( + mkshlib=linker, + mkcshlib=linker, + ) + + cc = ["$(CC)", "$(COMPUTED_C_LDFLAGS)"] + cxx = ["$(CXX)", "$(COMPUTED_CXX_LDFLAGS)"] + flags = ["$(DSO_LDOPTS)"] + output = ["-o", "$@"] + + if target.kernel == "Darwin": + soname = [] + elif target.os == "NetBSD": + soname = ["-Wl,-soname,$(DSO_SONAME)"] + else: + assert compiler.type in ("gcc", "clang") + + soname = ["-Wl,-h,$(DSO_SONAME)"] + + return namespace( + mkshlib=cxx + flags + soname + output, + mkcshlib=cc + flags + soname + output, + ) + + +set_config("MKSHLIB", make_shared_library.mkshlib) +set_config("MKCSHLIB", make_shared_library.mkcshlib) + + +@depends(c_compiler, toolchain_prefix, when=target_is_windows) +def rc_names(c_compiler, toolchain_prefix): + if c_compiler.type in ("gcc", "clang"): + return tuple("%s%s" % (p, "windres") for p in ("",) + (toolchain_prefix or ())) + return ("llvm-rc",) + + +check_prog("RC", rc_names, paths=clang_search_path, when=target_is_windows) + + +@template +def ar_config(c_compiler, toolchain_prefix=None): + if not toolchain_prefix: + toolchain_prefix = dependable(None) + + @depends(toolchain_prefix, c_compiler) + def ar_config(toolchain_prefix, c_compiler): + if c_compiler.type == "clang-cl": + return namespace( + names=("llvm-lib",), + flags=("-llvmlibthin", "-out:$@"), + ) + + names = tuple("%s%s" % (p, "ar") for p in (toolchain_prefix or ()) + ("",)) + if c_compiler.type == "clang": + # Get the llvm-ar path as per the output from clang --print-prog-name=llvm-ar + # so that we directly get the one under the clang directory, rather than one + # that might be in /usr/bin and that might point to one from a different version + # of clang. + out = check_cmd_output( + c_compiler.compiler, "--print-prog-name=llvm-ar", onerror=lambda: None + ) + llvm_ar = out.rstrip() if out else "llvm-ar" + names = (llvm_ar,) + names + + return namespace( + names=names, + flags=("crs", "$@"), + ) + + return ar_config + + +target_ar_config = ar_config(c_compiler, toolchain_prefix) + +target_ar = check_prog("AR", target_ar_config.names, paths=clang_search_path) + +set_config("AR_FLAGS", target_ar_config.flags) + + +@depends(c_compiler, extra_toolchain_flags, target_ar, target_ar_config) +@checking("whether ar supports response files") +@imports("os") +@imports(_from="tempfile", _import="mkstemp") +@imports(_from="__builtin__", _import="FileNotFoundError") +@imports(_from="mozbuild.configure.util", _import="LineIO") +def ar_supports_response_files(c_compiler, extra_toolchain_flags, ar, ar_config): + lib_path = list_path = None + try: + fd, obj_path = mkstemp(prefix="conftest.", suffix=".o") + os.close(fd) + if ( + try_invoke_compiler( + # No configure_cache because it would not create the + # expected output file. + None, + [c_compiler.compiler] + c_compiler.flags, + c_compiler.language, + "void foo() {}", + ["-c", "-o", obj_path] + (extra_toolchain_flags or []), + wrapper=c_compiler.wrapper, + onerror=lambda: None, + ) + is not None + ): + fd, list_path = mkstemp(prefix="conftest.", suffix=".list") + with os.fdopen(fd, "w") as list: + list.write(obj_path) + log.debug("Creating `%s` with content:", list_path) + log.debug("| %s", obj_path) + fd, lib_path = mkstemp(prefix="conftest.", suffix=".a") + os.close(fd) + os.remove(lib_path) + ar_command = ( + [ar] + + [x.replace("$@", lib_path) for x in ar_config.flags] + + ["@" + list_path] + ) + result = check_cmd_output(*ar_command, onerror=lambda: None) + return result is not None + finally: + for cleanup_path in (obj_path, list_path, lib_path): + if cleanup_path: + try: + os.remove(cleanup_path) + except FileNotFoundError: + pass + + +set_config("AR_SUPPORTS_RESPONSE_FILE", True, when=ar_supports_response_files) + +host_ar_config = ar_config(host_c_compiler) + +check_prog("HOST_AR", host_ar_config.names, paths=clang_search_path) + + +@depends(toolchain_prefix, c_compiler) +def nm_names(toolchain_prefix, c_compiler): + names = tuple("%s%s" % (p, "nm") for p in (toolchain_prefix or ()) + ("",)) + if c_compiler.type == "clang": + # Get the llvm-nm path as per the output from clang --print-prog-name=llvm-nm + # so that we directly get the one under the clang directory, rather than one + # that might be in /usr/bin and that might point to one from a different version + # of clang. + out = check_cmd_output( + c_compiler.compiler, "--print-prog-name=llvm-nm", onerror=lambda: None + ) + llvm_nm = out.rstrip() if out else "llvm-nm" + names = (llvm_nm,) + names + + return names + + +check_prog("NM", nm_names, paths=clang_search_path, when=target_has_linux_kernel) + + +option("--enable-cpp-rtti", help="Enable C++ RTTI") + +add_old_configure_assignment("_MOZ_USE_RTTI", "1", when="--enable-cpp-rtti") + + +option( + "--enable-path-remapping", + nargs="*", + choices=("c", "rust"), + help="Enable remapping source and object paths in compiled outputs.", +) + + +@depends("--enable-path-remapping") +def path_remapping(value): + if len(value): + return value + if bool(value): + return ["c", "rust"] + return [] + + +@depends( + target, + build_environment, + target_sysroot.path, + valid_windows_sdk_dir, + vc_path, + when="--enable-path-remapping", +) +def path_remappings(target, build_env, sysroot_path, windows_sdk_dir, vc_path): + win = target.kernel == "WINNT" + + # The prefix maps are processed in the order they're specified on the + # command line. Therefore, to accommodate object directories in the source + # directory, it's important that we map the topobjdir before the topsrcdir, + # 'cuz we might have /src/obj/=/o/ and /src/=/s/. The various other + # directories might be subdirectories of topsrcdir as well, so they come + # earlier still. + + path_remappings = [] + + # We will have only one sysroot or SDK, so all can have the same mnemonic: K + # for "kit" (since S is taken for "source"). See + # https://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html + # for how to use the Windows `subst` command to map these in debuggers and + # IDEs. + if sysroot_path: + path_remappings.append((sysroot_path, "k:/" if win else "/sysroot/")) + if windows_sdk_dir: + path_remappings.append( + (windows_sdk_dir.path, "k:/" if win else "/windows_sdk/") + ) + if vc_path: + path_remappings.append((vc_path, "v:/" if win else "/vc/")) + + path_remappings += [ + (build_env.topobjdir, "o:/" if win else "/topobjdir/"), + (build_env.topsrcdir, "s:/" if win else "/topsrcdir/"), + ] + + path_remappings = [ + (normsep(old).rstrip("/") + "/", new) for old, new in path_remappings + ] + + # It is tempting to sort these, but we want the order to be the same across + # machines so that we can share cache hits. Therefore we reject bad + # configurations rather than trying to make the configuration good. + for i in range(len(path_remappings) - 1): + p = path_remappings[i][0] + for q, _ in path_remappings[i + 1 :]: + if q.startswith(p): + die(f"Cannot remap paths because {p} is an ancestor of {q}") + + return path_remappings + + +set_config("MMX_FLAGS", ["-mmmx"]) +set_config("SSE_FLAGS", ["-msse"]) +set_config("SSE2_FLAGS", ["-msse2"]) +set_config("SSSE3_FLAGS", ["-mssse3"]) +set_config("SSE4_2_FLAGS", ["-msse4.2"]) +set_config("FMA_FLAGS", ["-mfma"]) +set_config("AVX2_FLAGS", ["-mavx2"]) +set_config( + "AVXVNNI_FLAGS", + ["-mavxvnni"], + try_compile(check_msg="for -mavxvnni support", flags=["-mavxvnni"]), +) +set_config( + "AVX512BW_FLAGS", + ["-mavx512bw", "-mavx512f", "-mavx512dq", "-mavx512cd"], + try_compile( + check_msg="for -mavx512bw support", + flags=["-mavx512bw", "-mavx512f", "-mavx512dq", "-mavx512cd"], + ), +) + +# AVX512VNNI can be based on either avx512bw or avx512vbmi. We choose the +# former. +set_config( + "AVX512VNNI_FLAGS", + ["-mavx512vnni", "-mavx512bw", "-mavx512f", "-mavx512dq", "-mavx512cd"], + try_compile( + check_msg="for -mavx512vnni support", + flags=["-mavx512vnni", "-mavx512bw", "-mavx512f", "-mavx512dq", "-mavx512cd"], + ), +) diff --git a/build/moz.configure/update-programs.configure b/build/moz.configure/update-programs.configure new file mode 100644 index 0000000000..3be098308d --- /dev/null +++ b/build/moz.configure/update-programs.configure @@ -0,0 +1,198 @@ +# -*- 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/. + + +# Updater +# ============================================================== +@depends(build_project) +def updater_default(build_project): + return build_project != "mobile/android" + + +option( + "--enable-updater", + default=updater_default, + help="{Enable|Disable} building the updater", +) + +set_config("MOZ_UPDATER", True, when="--enable-updater") +set_define("MOZ_UPDATER", True, when="--enable-updater") + +# Updates that do not verify signatures +# ============================================================== + +option( + "--enable-unverified-updates", + default=False, + help="Enable application update without verifying MAR or updater binary signatures", +) + + +@depends("--enable-unverified-updates", "--enable-compile-environment") +def disable_unverified_updates(unverified_updates, compile_environment): + if unverified_updates: + if not compile_environment: + die("--enable-unverified-updates requires --enable-compile-environment") + return not unverified_updates + + +set_define( + "MOZ_VERIFY_MAR_SIGNATURE", + depends_if(disable_unverified_updates)(lambda _: True), +) +set_config( + "MOZ_VERIFY_MAR_SIGNATURE", + True, + depends_if(disable_unverified_updates)(lambda _: True), +) + +set_config( + "DISABLE_UPDATER_AUTHENTICODE_CHECK", + True, + depends_if("--enable-unverified-updates")(lambda _: True), +) + +# Use NSS for MAR signatures even on platforms where system libraries are +# supported (currently Windows and macOS). +# ============================================================== + +can_toggle_nss_mar = target_is_windows | target_is_osx + +option( + "--enable-nss-mar", + when=can_toggle_nss_mar, + help="Enable using NSS to check MAR signatures instead of system crypto.", +) + + +@depends( + depends("--enable-nss-mar", when=can_toggle_nss_mar)(lambda x: x), + can_toggle_nss_mar, +) +def enable_nss_mar(enabled, can_toggle_nss_mar): + return enabled or not can_toggle_nss_mar + + +set_config("MOZ_USE_NSS_FOR_MAR", True, when=enable_nss_mar) + +# Maintenance service (Windows only) +# ============================================================== + + +@depends("--enable-updater") +def maintenance_service_default(updater): + return bool(updater) + + +option( + "--enable-maintenance-service", + when=target_is_windows, + default=maintenance_service_default, + help="{Enable|Disable} building of maintenance service", +) + +set_define( + "MOZ_MAINTENANCE_SERVICE", + depends_if("--enable-maintenance-service", when=target_is_windows)(lambda _: True), +) +set_config( + "MOZ_MAINTENANCE_SERVICE", + depends_if("--enable-maintenance-service", when=target_is_windows)(lambda _: True), +) + + +@depends("--enable-maintenance-service", "--enable-updater", when=target_is_windows) +def check_maintenance_service(mainteance_service, updater): + if mainteance_service and not updater: + die("--enable-updater is required to --enable-maintenance-service") + return mainteance_service + + +# Update agent (currently Windows and macOS only) +# This is an independent task that runs on a schedule to +# check for, download, and install updates. +# ============================================================== + + +@depends("--enable-backgroundtasks", "--enable-updater", build_project) +def update_agent_default(backgroundtasks, updater, build_project): + return bool(backgroundtasks) and bool(updater) and build_project == "browser" + + +option( + "--disable-update-agent", + when=target_is_windows | target_is_osx, + default=update_agent_default, + help="{Enable|Disable} building update agent", +) + +set_config( + "MOZ_UPDATE_AGENT", + depends_if("--enable-update-agent", when=target_is_windows | target_is_osx)( + lambda _: True + ), +) + + +@depends( + "--enable-update-agent", + "--enable-backgroundtasks", + "--enable-updater", + when=target_is_windows | target_is_osx, +) +def check_update_agent(update_agent, backgroundtasks, updater): + if update_agent and not backgroundtasks: + die("--enable-backgroundtasks is required to --enable-update-agent") + if update_agent and not updater: + die("--enable-updater is required to --enable-update-agent") + return update_agent + + +# Enable or disable the default browser agent, which monitors the user's default +# browser setting on Windows. +# ============================================================================== + + +@depends(target, build_project) +def default_browser_agent_default(target, build_project): + return target.os == "WINNT" and build_project == "browser" + + +option( + "--enable-default-browser-agent", + default=default_browser_agent_default, + help="{Enable|Disable} building the default browser agent", +) + + +@depends("--enable-default-browser-agent", when=target_is_windows) +def default_agent_flag(enabled): + if enabled: + return True + + +set_config("MOZ_DEFAULT_BROWSER_AGENT", default_agent_flag) + + +# Enable or disable the notification server, which allows Windows native +# notifications to persist when the application is not running and relaunch as +# necessary. +# ============================================================================== +@depends(target, build_project) +def notification_server_default(target, build_project): + return target.os == "WINNT" and build_project in ( + "browser", + "comm/mail", + ) + + +option( + "--disable-notification-server", + when=notification_server_default, + help="Disable building the notification server", +) + +set_config("MOZ_NOTIFICATION_SERVER", True, when="--enable-notification-server") diff --git a/build/moz.configure/util.configure b/build/moz.configure/util.configure new file mode 100644 index 0000000000..d93b91fcdd --- /dev/null +++ b/build/moz.configure/util.configure @@ -0,0 +1,550 @@ +# -*- 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/. + + +@imports("sys") +def die(*args): + "Print an error and terminate configure." + log.error(*args) + sys.exit(1) + + +@imports(_from="mozbuild.configure", _import="ConfigureError") +def configure_error(message): + """Raise a programming error and terminate configure. + Primarily for use in moz.configure templates to sanity check + their inputs from moz.configure usage.""" + raise ConfigureError(message) + + +# A wrapper to obtain a process' output and return code. +# Returns a tuple (retcode, stdout, stderr). +@imports("os") +@imports("subprocess") +@imports(_from="mozbuild.shellutil", _import="quote") +@imports(_from="mozbuild.util", _import="system_encoding") +def get_cmd_output(*args, **kwargs): + log.debug("Executing: `%s`", quote(*args)) + proc = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + # On Python 2 on Windows, close_fds prevents the process from inheriting + # stdout/stderr. Elsewhere, it simply prevents it from inheriting extra + # file descriptors, which is what we want. + close_fds=os.name != "nt", + encoding=system_encoding, + errors="replace", + **kwargs, + ) + stdout, stderr = proc.communicate() + return proc.wait(), stdout, stderr + + +# A wrapper to obtain a process' output that returns the output generated +# by running the given command if it exits normally, and streams that +# output to log.debug and calls die or the given error callback if it +# does not. +@imports(_from="mozbuild.configure.util", _import="LineIO") +@imports(_from="mozbuild.shellutil", _import="quote") +def check_cmd_output(*args, **kwargs): + onerror = kwargs.pop("onerror", None) + + with log.queue_debug(): + retcode, stdout, stderr = get_cmd_output(*args, **kwargs) + if retcode == 0: + with LineIO(lambda l: log.debug("| %s", l)) as o: + o.write(stderr) + return stdout + + log.debug("The command returned non-zero exit status %d.", retcode) + for out, desc in ((stdout, "output"), (stderr, "error output")): + if out: + log.debug("Its %s was:", desc) + with LineIO(lambda l: log.debug("| %s", l)) as o: + o.write(out) + if onerror: + return onerror() + die("Command `%s` failed with exit status %d." % (quote(*args), retcode)) + + +@imports("os") +def is_absolute_or_relative(path): + if os.altsep and os.altsep in path: + return True + return os.sep in path + + +@imports(_import="mozpack.path", _as="mozpath") +def normsep(path): + return mozpath.normsep(path) + + +@imports("ctypes") +@imports(_from="ctypes", _import="wintypes") +@imports(_from="mozbuild.configure.constants", _import="WindowsBinaryType") +def windows_binary_type(path): + """Obtain the type of a binary on Windows. + + Returns WindowsBinaryType constant. + """ + GetBinaryTypeW = ctypes.windll.kernel32.GetBinaryTypeW + GetBinaryTypeW.argtypes = [wintypes.LPWSTR, ctypes.POINTER(wintypes.DWORD)] + GetBinaryTypeW.restype = wintypes.BOOL + + bin_type = wintypes.DWORD() + res = GetBinaryTypeW(path, ctypes.byref(bin_type)) + if not res: + die("could not obtain binary type of %s" % path) + + if bin_type.value == 0: + return WindowsBinaryType("win32") + elif bin_type.value == 6: + return WindowsBinaryType("win64") + # If we see another binary type, something is likely horribly wrong. + else: + die("unsupported binary type on %s: %s" % (path, bin_type)) + + +@imports("ctypes") +@imports(_from="ctypes", _import="wintypes") +def get_GetShortPathNameW(): + GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW + GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD] + GetShortPathNameW.restype = wintypes.DWORD + return GetShortPathNameW + + +@template +@imports("ctypes") +@imports("platform") +@imports(_from="mozbuild.shellutil", _import="quote") +def normalize_path(): + # Until the build system can properly handle programs that need quoting, + # transform those paths into their short version on Windows (e.g. + # c:\PROGRA~1...). + if platform.system() == "Windows": + GetShortPathNameW = get_GetShortPathNameW() + + def normalize_path(path): + path = normsep(path) + if quote(path) == path: + return path + size = 0 + while True: + out = ctypes.create_unicode_buffer(size) + needed = GetShortPathNameW(path, out, size) + if size >= needed: + if " " in out.value: + die( + "GetShortPathName returned a long path name: `%s`. " + "Use `fsutil file setshortname' " + "to create a short name " + "for any components of this path " + "that have spaces.", + out.value, + ) + return normsep(out.value) + size = needed + + else: + + def normalize_path(path): + return normsep(path) + + return normalize_path + + +normalize_path = normalize_path() + + +# Locates the given program using which, or returns the given path if it +# exists. +# The `paths` parameter may be passed to search the given paths instead of +# $PATH. +@imports("sys") +@imports(_from="os", _import="pathsep") +@imports(_from="os", _import="environ") +@imports(_from="mozfile", _import="which") +def find_program(file, paths=None, allow_spaces=False): + def which_normalize(file, path, exts): + path = which(file, path=path, exts=exts) + if not path: + return None + if not allow_spaces: + return normalize_path(path) + return normsep(path) + + # The following snippet comes from `which` itself, with a slight + # modification to use lowercase extensions, because it's confusing rustup + # (on top of making results not really appealing to the eye). + + # Windows has the concept of a list of extensions (PATHEXT env var). + if sys.platform.startswith("win"): + exts = [e.lower() for e in environ.get("PATHEXT", "").split(pathsep)] + # If '.exe' is not in exts then obviously this is Win9x and + # or a bogus PATHEXT, then use a reasonable default. + if ".exe" not in exts: + exts = [".com", ".exe", ".bat"] + else: + exts = None + + if is_absolute_or_relative(file): + return which_normalize( + os.path.basename(file), path=os.path.dirname(file), exts=exts + ) + + if paths: + if not isinstance(paths, (list, tuple)): + die( + "Paths provided to find_program must be a list of strings, " "not %r", + paths, + ) + paths = pathsep.join(paths) + + return which_normalize(file, path=paths, exts=exts) + + +@imports("os") +@imports(_from="mozbuild.configure.util", _import="LineIO") +@imports(_from="tempfile", _import="mkstemp") +@imports(_import="subprocess") +def try_invoke_compiler( + configure_cache, compiler, language, source, flags=None, onerror=None, wrapper=[] +): + compiler_path = compiler[0] + compiler = wrapper + compiler + use_cache = configure_cache is not None + + if use_cache and compiler_path not in configure_cache.version_checked_compilers: + try: + version_info = subprocess.check_output( + [compiler_path, "--version"], + encoding="UTF-8", + ).strip() + except subprocess.CalledProcessError: + # There's no sane way to use the cache without the version details, so + # we need to avoid both reads from and writes to the cache. + use_cache = False + pass + + if use_cache: + if version_info != configure_cache.setdefault(compiler_path, {}).get( + "version" + ): + configure_cache[compiler_path].clear() + + configure_cache[compiler_path]["version"] = version_info + configure_cache.version_checked_compilers.add(compiler_path) + + flags = flags or [] + + if use_cache: + key = " ".join(compiler) + language + source + (" ".join(flags) or "") + + if key in configure_cache[compiler_path]: + return configure_cache[compiler_path][key] + + if not isinstance(flags, (list, tuple)): + die("Flags provided to try_compile must be a list of strings, " "not %r", flags) + + suffix = { + "C": ".c", + "C++": ".cpp", + }[language] + + fd, path = mkstemp(prefix="conftest.", suffix=suffix, text=True) + try: + source = source.encode("ascii", "replace") + + log.debug("Creating `%s` with content:", path) + with LineIO(lambda l: log.debug("| %s", l)) as out: + out.write(source) + + os.write(fd, source) + os.close(fd) + cmd = compiler + [path] + list(flags) + kwargs = {"onerror": onerror} + val = check_cmd_output(*cmd, **kwargs) + if use_cache: + configure_cache[compiler_path][key] = val + return val + finally: + os.remove(path) + + +def unique_list(l): + result = [] + for i in l: + if l not in result: + result.append(i) + return result + + +# Get values out of the Windows registry. This function can only be called on +# Windows. +# The `pattern` argument is a string starting with HKEY_ and giving the full +# "path" of the registry key to get the value for, with backslash separators. +# The string can contains wildcards ('*'). +# The result of this functions is an enumerator yielding tuples for each +# match. Each of these tuples contains the key name matching wildcards +# followed by the value. +# +# The `get_32_and_64_bit` argument is a boolean, if True then it will return the +# values from the 32-bit and 64-bit registry views. This defaults to False, +# which will return the view depending on the bitness of python. +# +# Examples: +# get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\' +# r'Windows Kits\Installed Roots\KitsRoot*') +# yields e.g.: +# ('KitsRoot81', r'C:\Program Files (x86)\Windows Kits\8.1\') +# ('KitsRoot10', r'C:\Program Files (x86)\Windows Kits\10\') +# +# get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\' +# r'Windows Kits\Installed Roots\KitsRoot8.1') +# yields e.g.: +# (r'C:\Program Files (x86)\Windows Kits\8.1\',) +# +# get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\' +# r'Windows Kits\Installed Roots\KitsRoot8.1', +# get_32_and_64_bit=True) +# yields e.g.: +# (r'C:\Program Files (x86)\Windows Kits\8.1\',) +# (r'C:\Program Files\Windows Kits\8.1\',) +# +# get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\' +# r'Windows Kits\*\KitsRoot*') +# yields e.g.: +# ('Installed Roots', 'KitsRoot81', +# r'C:\Program Files (x86)\Windows Kits\8.1\') +# ('Installed Roots', 'KitsRoot10', +# r'C:\Program Files (x86)\Windows Kits\10\') +# +# get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\' +# r'VisualStudio\VC\*\x86\*\Compiler') +# yields e.g.: +# ('19.0', 'arm', r'C:\...\amd64_arm\cl.exe') +# ('19.0', 'x64', r'C:\...\amd64\cl.exe') +# ('19.0', 'x86', r'C:\...\amd64_x86\cl.exe') +@imports(_import="winreg") +@imports(_from="__builtin__", _import="WindowsError") +@imports(_from="fnmatch", _import="fnmatch") +def get_registry_values(pattern, get_32_and_64_bit=False): + def enum_helper(func, key): + i = 0 + while True: + try: + yield func(key, i) + except WindowsError: + break + i += 1 + + def get_keys(key, pattern, access_mask): + try: + s = winreg.OpenKey(key, "\\".join(pattern[:-1]), 0, access_mask) + except WindowsError: + return + for k in enum_helper(winreg.EnumKey, s): + if fnmatch(k, pattern[-1]): + try: + yield k, winreg.OpenKey(s, k, 0, access_mask) + except WindowsError: + pass + + def get_values(key, pattern, access_mask): + try: + s = winreg.OpenKey(key, "\\".join(pattern[:-1]), 0, access_mask) + except WindowsError: + return + for k, v, t in enum_helper(winreg.EnumValue, s): + if fnmatch(k, pattern[-1]): + yield k, v + + def split_pattern(pattern): + subpattern = [] + for p in pattern: + subpattern.append(p) + if "*" in p: + yield subpattern + subpattern = [] + if subpattern: + yield subpattern + + def get_all_values(keys, pattern, access_mask): + for i, p in enumerate(pattern): + next_keys = [] + for base_key in keys: + matches = base_key[:-1] + base_key = base_key[-1] + if i == len(pattern) - 1: + want_name = "*" in p[-1] + for name, value in get_values(base_key, p, access_mask): + yield matches + ((name, value) if want_name else (value,)) + else: + for name, k in get_keys(base_key, p, access_mask): + next_keys.append(matches + (name, k)) + keys = next_keys + + pattern = pattern.split("\\") + assert pattern[0].startswith("HKEY_") + keys = [(getattr(winreg, pattern[0]),)] + pattern = list(split_pattern(pattern[1:])) + if get_32_and_64_bit: + for match in get_all_values( + keys, pattern, winreg.KEY_READ | winreg.KEY_WOW64_32KEY + ): + yield match + for match in get_all_values( + keys, pattern, winreg.KEY_READ | winreg.KEY_WOW64_64KEY + ): + yield match + else: + for match in get_all_values(keys, pattern, winreg.KEY_READ): + yield match + + +@imports(_from="mozbuild.configure.util", _import="Version", _as="_Version") +def Version(v): + "A version number that can be compared usefully." + return _Version(v) + + +# Denotes a deprecated option. Combines option() and @depends: +# @deprecated_option('--option') +# def option(value): +# ... +# @deprecated_option() takes the same arguments as option(), except `help`. +# The function may handle the option like a typical @depends function would, +# but it is recommended it emits a deprecation error message suggesting an +# alternative option to use if there is one. +@template +def deprecated_option(*args, **kwargs): + assert "help" not in kwargs + kwargs["help"] = "Deprecated" + opt = option(*args, **kwargs) + kwargs = {k: v for k, v in kwargs.items() if k == "when"} + + def decorator(func): + @depends(opt.option, **kwargs) + def deprecated(value): + if value.origin != "default": + return func(value) + + return deprecated + + return decorator + + +# Turn an object into an object that can be used as an argument to @depends. +# The given object can be a literal value, a function that takes no argument, +# or, for convenience, a @depends function. +@template +@imports(_from="mozbuild.configure", _import="SandboxDependsFunction") +def dependable(obj): + if isinstance(obj, SandboxDependsFunction): + return obj + return depends(when=True)(obj) + + +always = dependable(True) +never = dependable(False) + + +# Create a decorator that will only execute the body of a function +# if the passed function returns True when passed all positional +# arguments. +@template +def depends_tmpl(eval_args_fn, *args, **kwargs): + if kwargs: + assert len(kwargs) == 1 + when = kwargs["when"] + else: + when = None + + def decorator(func): + @depends(*args, when=when) + def wrapper(*args): + if eval_args_fn(args): + return func(*args) + + return wrapper + + return decorator + + +# Like @depends, but the decorated function is only called if one of the +# arguments it would be called with has a positive value (bool(value) is True) +@template +def depends_if(*args, **kwargs): + return depends_tmpl(any, *args, **kwargs) + + +# Like @depends, but the decorated function is only called if all of the +# arguments it would be called with have a positive value. +@template +def depends_all(*args, **kwargs): + return depends_tmpl(all, *args, **kwargs) + + +# A template providing a shorthand for setting a variable. The created +# option will only be settable with imply_option. +# It is expected that a project-specific moz.configure will call imply_option +# to set a value other than the default. +# If required, the set_as_define argument will additionally cause the variable +# to be set using set_define. +@template +def project_flag(env=None, set_as_define=False, **kwargs): + if not env: + configure_error("A project_flag must be passed a variable name to set.") + + opt = option(env=env, possible_origins=("implied",), **kwargs) + + @depends(opt.option) + def option_implementation(value): + if value: + if len(value): + return value + return bool(value) + + set_config(env, option_implementation) + if set_as_define: + set_define(env, option_implementation) + + +@template +@imports(_from="mozbuild.configure.constants", _import="RaiseErrorOnUse") +def obsolete_config(name, *, replacement): + set_config(name, RaiseErrorOnUse(f"{name} is obsolete. Use {replacement} instead.")) + + +# Hacks related to old-configure +# ============================== + + +@dependable +def old_configure_assignments(): + return [] + + +@template +def add_old_configure_assignment(var, value, when=None): + var = dependable(var) + value = dependable(value) + + @depends(old_configure_assignments, var, value, when=when) + @imports(_from="mozbuild.shellutil", _import="quote") + def add_assignment(assignments, var, value): + if var is None or value is None: + return + if value is True: + assignments.append((var, "1")) + elif value is False: + assignments.append((var, "")) + else: + if isinstance(value, (list, tuple)): + value = quote(*value) + assignments.append((var, str(value))) diff --git a/build/moz.configure/warnings.configure b/build/moz.configure/warnings.configure new file mode 100644 index 0000000000..9340c9e6ab --- /dev/null +++ b/build/moz.configure/warnings.configure @@ -0,0 +1,324 @@ +# -*- 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/. + +option( + "--enable-warnings-as-errors", + env="MOZ_ENABLE_WARNINGS_AS_ERRORS", + default=depends("MOZ_AUTOMATION")(lambda x: bool(x)), + help="{Enable|Disable} treating warnings as errors", +) + + +@depends("--enable-warnings-as-errors") +def warnings_as_errors(warnings_as_errors): + if not warnings_as_errors: + return "" + + return "-Werror" + + +set_config("WARNINGS_AS_ERRORS", warnings_as_errors) + +not_clang_cl = depends(c_compiler)(lambda c: c.type != "clang-cl") + +# GCC/Clang warnings: +# https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html +# https://clang.llvm.org/docs/DiagnosticsReference.html + +# Lots of useful warnings +add_warning("-Wall", when=not_clang_cl) +# In clang-cl, -Wall actually means -Weverything. -W3 does mean -Wall. +add_warning("-W3", when=depends(c_compiler)(lambda c: c.type == "clang-cl")) + +# catch implicit truncation of enum values assigned to smaller bit fields +check_and_add_warning("-Wbitfield-enum-conversion") + +# catches deprecated implicit capture of `this` in lambdas. +check_and_add_warning("-Wdeprecated-this-capture", cxx_compiler) + +# catches bugs, e.g. "if (c); foo();", few false positives +add_warning("-Wempty-body") + +# catches mismatched printf integer sizes. +check_and_add_warning("-Wformat-type-confusion") + +# catches return types with qualifiers like const +add_warning("-Wignored-qualifiers") + +# catches pointer arithmetic using NULL or sizeof(void) +add_warning("-Wpointer-arith") + +# catch modifying constructor parameter that shadows member variable +check_and_add_warning("-Wshadow-field-in-constructor-modified") + +# catches comparing signed/unsigned ints +add_warning("-Wsign-compare") + +# catches comparisons of values and sized types are always true or false +check_and_add_warning("-Wtautological-constant-in-range-compare") + +# catches overflow bugs, few false positives +add_warning("-Wtype-limits") + +# This can be triggered by certain patterns used deliberately in portable code +check_and_add_warning("-Wno-error=tautological-type-limit-compare") + +# catches some dead code +add_warning("-Wunreachable-code") +check_and_add_warning("-Wunreachable-code-return") + +# catches parameters that are set but not read +# Only enable on clang because gcc reports false positives. +check_and_add_warning( + "-Wunused-but-set-parameter", + when=depends(c_compiler)(lambda c: c.type in ("clang", "clang-cl")), +) + +# turned on by -Wall, but we use offsetof on non-POD types frequently +add_warning("-Wno-invalid-offsetof", cxx_compiler) + +# catches objects passed by value to variadic functions. +check_and_add_warning("-Wclass-varargs") + +# catches empty if/switch/for initialization statements that have no effect +check_and_add_warning("-Wempty-init-stmt", cxx_compiler) + +# catches some implicit conversion of floats to ints +check_and_add_warning("-Wfloat-overflow-conversion") +check_and_add_warning("-Wfloat-zero-conversion") + +# catches issues around loops +check_and_add_warning("-Wloop-analysis") +# But, disable range-loop-analysis because it can raise unhelpful false +# positives. +check_and_add_warning("-Wno-range-loop-analysis") + +# Enable some C++20 compat warnings. We can remove these flags after we compile +# as C++20 (bug 1768116), because they will be enabled by default: +check_and_add_warning("-Wc++2a-compat", cxx_compiler) +check_and_add_warning("-Wcomma-subscript", cxx_compiler) +check_and_add_warning("-Wenum-compare-conditional") +check_and_add_warning("-Wenum-float-conversion") +check_and_add_warning("-Wvolatile", cxx_compiler) + +# Downgrade some C++20 warnings-as-errors to warnings that we can fix after we +# compile as C++20 (bug 1768116). They don't need to block upgrading to C++20. +check_and_add_warning("-Wno-error=deprecated", cxx_compiler) +check_and_add_warning("-Wno-error=deprecated-anon-enum-enum-conversion", cxx_compiler) +check_and_add_warning("-Wno-error=deprecated-enum-enum-conversion", cxx_compiler) +check_and_add_warning("-Wno-error=deprecated-pragma", cxx_compiler) +check_and_add_warning("-Wno-error=deprecated-this-capture", cxx_compiler) + +# catches possible misuse of the comma operator +check_and_add_warning("-Wcomma", cxx_compiler) + +# catches duplicated conditions in if-else-if chains +check_and_add_warning("-Wduplicated-cond") + +# catches unintentional switch case fallthroughs +check_and_add_warning("-Wimplicit-fallthrough", cxx_compiler) + +# Warn about suspicious uses of logical operators in expressions. +check_and_add_warning("-Wlogical-op") + +# Enable some ObjC diagnostics that are only relevant when targeting macOS: +with only_when(depends(target)(lambda t: t.kernel == "Darwin")): + # catch redeclaration of ObjC method parameter name + check_and_add_warning("-Wduplicate-method-arg") + + # catch multiple declarations of ObjC method found + check_and_add_warning("-Wduplicate-method-match") + + # catch ObjC method with no return type specified + check_and_add_warning("-Wmissing-method-return-type") + + # catch implicit conversions between ObjC BOOL and int + check_and_add_warning("-Wobjc-signed-char-bool") + + # catch semicolon before ObjC method body + check_and_add_warning("-Wsemicolon-before-method-body") + + # catch ObjC method parameter type not matching super class method + check_and_add_warning("-Wsuper-class-method-mismatch") + +# catches string literals used in boolean expressions +check_and_add_warning("-Wstring-conversion") + +# we inline 'new' and 'delete' in mozalloc +check_and_add_warning("-Wno-inline-new-delete", cxx_compiler) + +# Prevent the following GCC warnings from being treated as errors: +# too many false positives +check_and_add_warning("-Wno-error=maybe-uninitialized") + +# we don't want our builds held hostage when a platform-specific API +# becomes deprecated. +check_and_add_warning("-Wno-error=deprecated-declarations") + +# false positives depending on optimization +check_and_add_warning("-Wno-error=array-bounds") + +# false positives depending on optimizations +check_and_add_warning("-Wno-error=free-nonheap-object") + +# Would be a pain to fix all occurrences, for very little gain +check_and_add_warning("-Wno-multistatement-macros") + +# Disable the -Werror for -Wclass-memaccess as we have a long +# tail of issues to fix +check_and_add_warning("-Wno-error=class-memaccess") + +# -Watomic-alignment is a new warning in clang 7 that seems way too broad. +# https://bugs.llvm.org/show_bug.cgi?id=38593 +check_and_add_warning("-Wno-error=atomic-alignment") + +# New warning with clang 15. Catches uses of deprecated builtins in abseil-cpp. +# https://bugzilla.mozilla.org/show_bug.cgi?id=1779528 +check_and_add_warning("-Wno-error=deprecated-builtins") + +# catches format/argument mismatches with printf +c_format_warning, cxx_format_warning = check_and_add_warning( + "-Wformat", when=depends(target)(lambda t: t.kernel != "WINNT") +) + +# Add compile-time warnings for unprotected functions and format functions +# that represent possible security problems. Enable this only when -Wformat +# is enabled, otherwise it is an error +check_and_add_warning("-Wformat-security", when=c_format_warning & cxx_format_warning) +check_and_add_warning("-Wformat-overflow=2", when=c_format_warning & cxx_format_warning) + +# Other Windows specific things +with only_when(target_is_windows): + # When compiling for Windows with gcc, we encounter lots of "#pragma warning"'s + # which is an MSVC-only pragma that GCC does not recognize. + # With clang-cl, as it claims to be MSVC it would be difficult to add + # #if defined(_MSC_VER) && !defined(__clang__) everywhere we use such pragmas, + # so just ignore them. + check_and_add_warning("-Wno-unknown-pragmas") + + with only_when(depends(c_compiler)(lambda c: c.type == "clang-cl")): + # We get errors about various #pragma intrinsic directives from + # clang-cl, and we don't need to hear about those. + check_and_add_warning("-Wno-ignored-pragmas") + + # clang-cl's Intrin.h marks things like _ReadWriteBarrier as + # __attribute((__deprecated__)). This is nice to know, but since we don't + # get the equivalent warning from MSVC, let's just ignore it. + check_and_add_warning("-Wno-deprecated-declarations") + + # This warns for reasonable things like: + # enum { X = 0xffffffffU }; + # which is annoying for IDL headers. + check_and_add_warning("-Wno-microsoft-enum-value", cxx_compiler) + + # This warns for cases that would be reached by the Microsoft + # #include rules, but also currently warns on cases that would + # *also* be reached by standard C++ include rules. That + # behavior doesn't seem useful, so we turn it off. + check_and_add_warning("-Wno-microsoft-include", cxx_compiler) + + # We use a function like: + # __declspec(noreturn) __inline void f() {} + # which -Winvalid-noreturn complains about. Again, MSVC seems + # OK with it, so let's silence the warning. + check_and_add_warning("-Wno-invalid-noreturn") + + # Missing |override| on virtual function declarations isn't + # something that MSVC currently warns about. + check_and_add_warning("-Wno-inconsistent-missing-override", cxx_compiler) + + # We use -DHAS_EXCEPTIONS=0, which removes the |throw()| + # declaration on |operator delete(void*)|. However, clang-cl + # must internally declare |operator delete(void*)| differently, + # which causes this warning for virtually every file in the + # tree. clang-cl doesn't support -fno-exceptions or equivalent, + # so there doesn't seem to be any way to convince clang-cl to + # declare |delete| differently. Therefore, suppress this + # warning. + check_and_add_warning("-Wno-implicit-exception-spec-mismatch", cxx_compiler) + + # Macros like STDMETHOD() and IFACEMETHOD() can declare + # __attribute__((nothrow)) on their respective method declarations, + # while the definitions are left without the matching attribute. + check_and_add_warning("-Wno-microsoft-exception-spec", cxx_compiler) + + # At least one MSVC header and several headers in-tree have + # unused typedefs, so turn this on. + check_and_add_warning("-Wno-unused-local-typedef", cxx_compiler) + + # jemalloc uses __declspec(allocator) as a profiler hint, + # which clang-cl doesn't understand. + check_and_add_warning("-Wno-ignored-attributes", cxx_compiler) + + # __attribute__((unused)) really means "might be unused" and + # we use it to avoid warnings about things that are unused + # in some compilation units, but used in many others. This + # warning insists on complaining about the latter case, which + # is annoying, and rather noisy. + check_and_add_warning("-Wno-used-but-marked-unused", cxx_compiler) + + with only_when(depends(c_compiler)(lambda c: c.type != "clang-cl")): + # When compiling for Windows with gcc, gcc throws false positives and true + # positives where the callsite is ifdef-ed out + check_and_add_warning("-Wno-unused-function") + + # When compiling for Windows with gcc, gcc cannot produce this warning + # correctly: it mistakes DWORD_PTR and ULONG_PTR as types you cannot + # give NULL to. (You can in fact do that.) + check_and_add_warning("-Wno-conversion-null") + + # Throughout the codebase we regularly have switch statements off of enums + # without covering every value in the enum. We don't care about these warnings. + check_and_add_warning("-Wno-switch") + + # Another code pattern we have is using start and end constants in enums of + # different types. We do this for safety, but then when comparing it throws + # an error, which we would like to ignore. This seems to only affect the MinGW + # build, but we're not sure why. + check_and_add_warning("-Wno-enum-compare") + +# Make it an error to be missing function declarations for C code. +check_and_add_warning("-Werror=implicit-function-declaration", c_compiler) + +# New in clang 11. We can't really do anything about this warning. +check_and_add_warning("-Wno-psabi") + +# Disable broken missing-braces warning on old clang versions +check_and_add_warning( + "-Wno-missing-braces", + when=depends(c_compiler)(lambda c: c.type == "clang" and c.version < "6.0"), +) + +# Turn on clang thread-safety analysis +# Older clangs don't support AutoUnlock, and have other issues +check_and_add_warning( + "-Wthread-safety", + when=depends(c_compiler)( + lambda c: c.type in ("clang", "clang-cl") and c.version >= "8.0" + ), +) + +# Warn if APIs are used without available() checks on macOS. +check_and_add_warning("-Werror=unguarded-availability-new", when=target_is_osx) + +# clang 17 warns about builtins being redefined and... well, we do that in +# multiple places, some of which are third-party. Until the situation is +# fixed, disable the new warning. +check_and_add_warning("-Wno-error=builtin-macro-redefined") + +# clang 18 has a new warning about VLAs being an extension in C++, but we +# have a number of them. +check_and_add_warning("-Wno-vla-cxx-extension", cxx_compiler) + +# Please keep the following last in this file + +# Avoid requiring complicated logic for extra warning flags in moz.build files. +check_and_add_warning("-Wno-unknown-warning-option") + +set_config("WARNINGS_CFLAGS", warnings_flags.cflags) +set_config("WARNINGS_CXXFLAGS", warnings_flags.cxxflags) +set_config("WARNINGS_HOST_CFLAGS", warnings_flags.host_cflags) +set_config("WARNINGS_HOST_CXXFLAGS", warnings_flags.host_cxxflags) diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure new file mode 100644 index 0000000000..f23aa2a499 --- /dev/null +++ b/build/moz.configure/windows.configure @@ -0,0 +1,481 @@ +# -*- 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/. + +option( + "--with-windows-version", + nargs=1, + default="603", + help="Windows SDK version to target. Win 8.1 (603) is currently" + "the minimum supported version.", +) + + +@depends("--with-windows-version") +@imports(_from="__builtin__", _import="ValueError") +def valid_windows_version(value): + if not value: + die("Cannot build with --without-windows-version") + try: + version = int(value[0], 16) + if version in (0x603,): + return version + except ValueError: + pass + + die("Invalid value for --with-windows-version (%s)", value[0]) + + +option(env="WINDOWSSDKDIR", nargs=1, help="Directory containing the Windows SDK") + + +@depends( + "WINDOWSSDKDIR", "WINSYSROOT", winsysroot, target_windows_abi, host_windows_abi +) +def windows_sdk_dir( + value, winsysroot_env, winsysroot, target_windows_abi, host_windows_abi +): + if value: + if winsysroot_env: + die("WINDOWSSDKDIR and WINSYSROOT cannot be set together.") + if winsysroot: + die("WINDOWSSDKDIR cannot be set when using the bootstrapped WINSYSROOT") + return value + if target_windows_abi != "msvc" and host_windows_abi != "msvc": + return () + + if winsysroot: + return [os.path.join(winsysroot, "Windows Kits", "10")] + + return set( + normalize_path(x[1]) + for x in get_registry_values( + r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots" + r"\KitsRoot*", + get_32_and_64_bit=True, + ) + ) + + +@imports("glob") +def get_sdk_dirs(sdk, subdir): + def get_dirs_containing(sdk, stem, subdir): + return [ + os.path.dirname(p) for p in glob.glob(os.path.join(sdk, stem, "*", subdir)) + ] + + def categorize(dirs): + return {os.path.basename(d): d for d in dirs} + + include_dirs = categorize(get_dirs_containing(sdk, "Include", subdir)) + lib_dirs = categorize(get_dirs_containing(sdk, "Lib", subdir)) + + valid_versions = sorted(set(include_dirs) & set(lib_dirs), reverse=True) + return [ + namespace( + path=sdk, + lib=lib_dirs[vv], + include=include_dirs[vv], + ) + for vv in valid_versions + ] + + +@imports(_from="mozbuild.shellutil", _import="quote") +def valid_windows_sdk_dir_result(value): + if value: + return "0x%04x in %s" % (value.version, quote(value.path)) + + +@depends( + target_windows_abi, + host_windows_abi, + windows_sdk_dir, + valid_windows_version, + "WINDOWSSDKDIR", +) +@checking("for Windows SDK", valid_windows_sdk_dir_result) +@imports(_from="__builtin__", _import="Exception") +@imports(_from="__builtin__", _import="open") +def valid_windows_sdk_dir( + target_windows_abi, + host_windows_abi, + windows_sdk_dir, + target_version, + windows_sdk_dir_env, +): + if target_windows_abi != "msvc" and host_windows_abi != "msvc": + return None + if windows_sdk_dir_env: + windows_sdk_dir_env = windows_sdk_dir_env[0] + sdks = {} + for d in windows_sdk_dir: + sdklist = get_sdk_dirs(d, "um") + for sdk in sdklist: + maxver = None + winsdkver = os.path.join(sdk.include, "um", "winsdkver.h") + with open(winsdkver) as fh: + for line in fh.readlines(): + if line.startswith("#define"): + line = line.split(None, 2) + assert line.pop(0) == "#define" + if line.pop(0) == "WINVER_MAXVER": + maxver = line.pop(0) + break + + if maxver: + try: + maxver = int(maxver, 0) + except Exception: + pass + else: + sdks[d] = maxver, sdk + break + + if d == windows_sdk_dir_env and d not in sdks: + raise FatalCheckError( + "Error while checking the version of the SDK in " + "WINDOWSSDKDIR (%s). Please verify it contains a valid and " + "complete SDK installation." % windows_sdk_dir_env + ) + + valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True) + if valid_sdks: + biggest_version, sdk = sdks[valid_sdks[0]] + if not valid_sdks or biggest_version < target_version: + if windows_sdk_dir_env: + raise FatalCheckError( + "You are targeting Windows version 0x%04x, but your SDK only " + "supports up to version 0x%04x. Install and use an updated SDK, " + "or target a lower version using --with-windows-version. " + "Alternatively, try running the Windows SDK Configuration Tool " + "and selecting a newer SDK. See " + "https://developer.mozilla.org/En/Windows_SDK_versions for " + "details on fixing this." % (target_version, biggest_version) + ) + + raise FatalCheckError( + "Cannot find a Windows SDK for version >= 0x%04x." % target_version + ) + + return namespace( + path=sdk.path, + include=sdk.include, + lib=sdk.lib, + version=biggest_version, + ) + + +@imports(_from="mozbuild.shellutil", _import="quote") +def valid_ucrt_sdk_dir_result(value): + if value: + return "%s in %s" % (value.version, quote(value.path)) + + +@depends(windows_sdk_dir, "WINDOWSSDKDIR", target_windows_abi, host_windows_abi) +@checking("for Universal CRT SDK", valid_ucrt_sdk_dir_result) +@imports("os") +@imports(_import="mozpack.path", _as="mozpath") +def valid_ucrt_sdk_dir( + windows_sdk_dir, windows_sdk_dir_env, target_windows_abi, host_windows_abi +): + if target_windows_abi != "msvc" and host_windows_abi != "msvc": + return None + if windows_sdk_dir_env: + windows_sdk_dir_env = windows_sdk_dir_env[0] + sdks = {} + for d in windows_sdk_dir: + sdklist = get_sdk_dirs(d, "ucrt") + for sdk in sdklist: + version = os.path.basename(sdk.include) + # We're supposed to always find a version in the directory, because + # the 8.1 SDK, which doesn't have a version in the directory, doesn't + # contain the Universal CRT SDK. When the main SDK is 8.1, there + # is, however, supposed to be a reduced install of the SDK 10 + # with the UCRT. + if version != "include": + sdks[d] = Version(version), sdk + break + + if d == windows_sdk_dir_env and d not in sdks: + # When WINDOWSSDKDIR is set in the environment and we can't find the + # Universal CRT SDK, chances are this is a start-shell-msvc*.bat + # setup, where INCLUDE and LIB already contain the UCRT paths. + ucrt_includes = [ + p + for p in os.environ.get("INCLUDE", "").split(";") + if os.path.basename(p).lower() == "ucrt" + ] + ucrt_libs = [ + p + for p in os.environ.get("LIB", "").split(";") + if os.path.basename(os.path.dirname(p)).lower() == "ucrt" + ] + if ucrt_includes and ucrt_libs: + # Pick the first of each, since they are the ones that the + # compiler would look first. Assume they contain the SDK files. + include = os.path.dirname(ucrt_includes[0]) + lib = os.path.dirname(os.path.dirname(ucrt_libs[0])) + path = os.path.dirname(os.path.dirname(include)) + version = os.path.basename(include) + if version != "include" and mozpath.basedir(lib, [path]): + sdks[d] = ( + Version(version), + namespace( + path=path, + include=include, + lib=lib, + ), + ) + continue + raise FatalCheckError( + "The SDK in WINDOWSSDKDIR (%s) does not contain the Universal " + "CRT." % windows_sdk_dir_env + ) + + valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True) + if not valid_sdks: + raise FatalCheckError( + "Cannot find the Universal CRT SDK. " "Please install it." + ) + + version, sdk = sdks[valid_sdks[0]] + minimum_ucrt_version = Version("10.0.17134.0") + if version < minimum_ucrt_version: + raise FatalCheckError( + "Latest Universal CRT SDK version found %s" + " and minimum required is %s. This or a later" + " version can be installed using the Visual" + " Studio installer." % (version, minimum_ucrt_version) + ) + + return namespace( + path=sdk.path, + include=sdk.include, + lib=sdk.lib, + version=version, + ) + + +@depends(target_windows_abi, host_windows_abi, vc_toolchain_search_path) +@imports("os") +def vc_path(target_windows_abi, host_windows_abi, vc_toolchain_search_path): + if target_windows_abi != "msvc" and host_windows_abi != "msvc": + return + + # In clang-cl builds, we need the headers and libraries from an MSVC installation. + vc_program = find_program("cl.exe", paths=vc_toolchain_search_path) + if not vc_program: + die("Cannot find a Visual C++ install for e.g. ATL headers.") + + result = os.path.dirname(vc_program) + while True: + next, p = os.path.split(result) + if next == result: + die( + "Cannot determine the Visual C++ directory the compiler (%s) " + "is in" % vc_program + ) + result = next + if p.lower() == "bin": + break + return os.path.normpath(result) + + +@depends(vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir) +@imports("os") +def include_path(vc_path, windows_sdk_dir, ucrt_sdk_dir): + if not vc_path: + return + atlmfc_dir = os.path.join(vc_path, "atlmfc", "include") + if not os.path.isdir(atlmfc_dir): + die( + "Cannot find the ATL/MFC headers in the Visual C++ directory (%s). " + "Please install them." % vc_path + ) + + winrt_dir = os.path.join(windows_sdk_dir.include, "winrt") + if not os.path.isdir(winrt_dir): + die( + "Cannot find the WinRT headers in the Windows SDK directory (%s). " + "Please install them." % windows_sdk_dir.path + ) + + cppwinrt_dir = os.path.join(windows_sdk_dir.include, "cppwinrt") + if not os.path.isdir(cppwinrt_dir): + die( + "Cannot find the C++/WinRT headers in the Windows SDK directory (%s). " + "Please install them." % windows_sdk_dir.path + ) + + includes = [] + include_env = os.environ.get("INCLUDE") + if include_env: + includes.append(include_env) + includes.extend( + ( + os.path.join(vc_path, "include"), + atlmfc_dir, + os.path.join(windows_sdk_dir.include, "shared"), + os.path.join(windows_sdk_dir.include, "um"), + winrt_dir, + cppwinrt_dir, + os.path.join(ucrt_sdk_dir.include, "ucrt"), + ) + ) + # Set in the environment for old-configure + includes = ";".join(includes) + os.environ["INCLUDE"] = includes + return includes + + +set_config("INCLUDE", include_path) + +# cppwinrt requires this on clang because of no coroutine support, which is okay +set_define("_SILENCE_CLANG_COROUTINE_MESSAGE", "") + + +@template +def lib_path_for(host_or_target): + @depends( + host_or_target, + dependable(host_or_target is host), + vc_path, + valid_windows_sdk_dir, + valid_ucrt_sdk_dir, + c_compiler, + ) + @imports("os") + def lib_path(target, is_host, vc_path, windows_sdk_dir, ucrt_sdk_dir, compiler): + if not vc_path or target.os != "WINNT": + return + sdk_target = { + "x86": "x86", + "x86_64": "x64", + "arm": "arm", + "aarch64": "arm64", + }.get(target.cpu) + + # MSVC2017 switched to use the same target naming as the sdk. + atlmfc_dir = os.path.join(vc_path, "atlmfc", "lib", sdk_target) + if not os.path.isdir(atlmfc_dir): + die( + "Cannot find the ATL/MFC libraries in the Visual C++ directory " + "(%s). Please install them." % vc_path + ) + + libs = [] + lib_env = os.environ.get("LIB") + if lib_env and not is_host: + libs.extend(lib_env.split(";")) + libs.extend( + ( + os.path.join(vc_path, "lib", sdk_target), + atlmfc_dir, + os.path.join(windows_sdk_dir.lib, "um", sdk_target), + os.path.join(ucrt_sdk_dir.lib, "ucrt", sdk_target), + ) + ) + if compiler.type == "clang-cl": + runtime_dir = check_cmd_output( + compiler.compiler, + "/clang:--print-runtime-dir", + *compiler.flags, + onerror=lambda: None + ).strip() + if runtime_dir and os.path.exists(runtime_dir): + # Put the clang runtime directory first, in case there is + # a different version in some of the other directories (notably, + # some versions of MSVC come with clang runtimes) + libs.insert(0, runtime_dir) + return libs + + return lib_path + + +@depends_if(lib_path_for(target), when=target_is_windows) +@imports("os") +def lib_path(libs): + # Set in the environment for old-configure + libs = ";".join(libs) + os.environ["LIB"] = libs + return libs + + +set_config("LIB", lib_path) + + +lib_path_for_host = lib_path_for(host) + + +@depends_if(lib_path_for_host, when=host_is_windows) +@imports(_from="mozbuild.shellutil", _import="quote") +def host_linker_libpaths(libs): + return ["-LIBPATH:%s" % quote(l) for l in libs] + + +@depends_if(lib_path_for_host, when=host_is_windows) +@imports(_from="mozbuild.shellutil", _import="quote") +def host_linker_libpaths_bat(libs): + # .bat files need a different style of quoting. Batch quoting is actually + # not defined, and up to applications to handle, so it's not really clear + # what should be escaped and what not, but most paths should work just + # fine without escaping. And we don't care about double-quotes possibly + # having to be escaped because they're not allowed in file names on + # Windows. + return ['"-LIBPATH:%s"' % l for l in libs] + + +set_config("HOST_LINKER_LIBPATHS", host_linker_libpaths) +set_config("HOST_LINKER_LIBPATHS_BAT", host_linker_libpaths_bat) + + +@depends(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host) +@imports(_from="os", _import="environ") +def sdk_bin_path(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host): + if not valid_windows_sdk_dir: + return + + vc_host = { + "x86": "x86", + "x86_64": "x64", + }.get(host.cpu) + + # From version 10.0.15063.0 onwards the bin path contains the version number. + versioned_bin = ( + "bin" + if valid_ucrt_sdk_dir.version < "10.0.15063.0" + else os.path.join("bin", str(valid_ucrt_sdk_dir.version)) + ) + result = [ + environ["PATH"], + os.path.join(valid_windows_sdk_dir.path, versioned_bin, vc_host), + ] + if vc_host == "x64": + result.append(os.path.join(valid_windows_sdk_dir.path, versioned_bin, "x86")) + return result + + +option(env="LINKER", nargs=1, when=target_is_windows, help="Path to the linker") + +link = check_prog( + "LINKER", + ("lld-link",), + input="LINKER", + when=target_is_windows, + paths=clang_search_path, +) + +option(env="HOST_LINKER", nargs=1, when=host_is_windows, help="Path to the host linker") + +host_link = check_prog( + "HOST_LINKER", + ("lld-link",), + input="HOST_LINKER", + when=host_is_windows, + paths=clang_search_path, +) + +add_old_configure_assignment("LINKER", link) diff --git a/build/mozconfig.artifact b/build/mozconfig.artifact new file mode 100644 index 0000000000..8a4d725714 --- /dev/null +++ b/build/mozconfig.artifact @@ -0,0 +1,7 @@ +# Common options for testing artifact builds in automation. + +# Enable the artifact build. +ac_add_options --enable-artifact-builds +ac_add_options --enable-artifact-build-symbols + +. "$topsrcdir/build/mozconfig.no-compile" diff --git a/build/mozconfig.artifact.automation b/build/mozconfig.artifact.automation new file mode 100644 index 0000000000..fed5866b68 --- /dev/null +++ b/build/mozconfig.artifact.automation @@ -0,0 +1,6 @@ +# Common options for artifact builds to set automation steps. +# This gets included before mozconfig.automation. + +MOZ_AUTOMATION_BUILD_SYMBOLS=0 +MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES=0 +MOZ_AUTOMATION_ARTIFACT_BUILDS=1 diff --git a/build/mozconfig.automation b/build/mozconfig.automation new file mode 100644 index 0000000000..0f2ea935ae --- /dev/null +++ b/build/mozconfig.automation @@ -0,0 +1,22 @@ +# 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/. + +# Common mozconfig for automation builds. +# +# We export MOZ_AUTOMATION_* variables here to trigger various steps in +# automation builds. For example, if MOZ_AUTOMATION_PACKAGE is set, then the +# package step will run. This file contains the default settings, which can be +# overridden by setting them earlier in the appropriate mozconfig. + +mk_add_options "export MOZ_AUTOMATION_BUILD_SYMBOLS=${MOZ_AUTOMATION_BUILD_SYMBOLS-1}" +mk_add_options "export MOZ_AUTOMATION_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}" +mk_add_options "export MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES=${MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES-1}" +mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}" +mk_add_options "export MOZ_AUTOMATION_CHECK=${MOZ_AUTOMATION_CHECK-1}" + +# The following variables are expected to be exported by Taskcluster +# configuration files rather than mozconfig files +mk_add_options "export MOZ_AUTOMATION_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-0}" + +export MOZ_AUTOMATION_MOZCONFIG=1 diff --git a/build/mozconfig.cache b/build/mozconfig.cache new file mode 100644 index 0000000000..33092c9861 --- /dev/null +++ b/build/mozconfig.cache @@ -0,0 +1,93 @@ +# 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/. + +# Setup for build cache + +# Thunderbird builds will set prior to including this file +aws_prefix=${aws_prefix:-taskcluster} +gcp_prefix=${gcp_prefix:-sccache} + +if test -n "$SCCACHE_DISABLE" -a -n "$USE_SCCACHE"; then + echo "SetupError: SCCACHE_DISABLE and USE_SCCACHE should not be set at the same time" >&2 + exit 1 +fi + +# builds where buildprops didn't have the data (eg: taskcluster) and without sccache disabled: +if test -z "$bucket" -a -z "$SCCACHE_DISABLE"; then + + # prevent rerun if az is set, or wget is not available + if test -z "$availability_zone" -a -x "$(command -v wget)"; then + if test -n "$TASKCLUSTER_WORKER_LOCATION" -a -x "$(command -v jq)"; then + cloud=$(echo $TASKCLUSTER_WORKER_LOCATION | jq .cloud | tr -d \") + case $cloud in + aws|google) + availability_zone=$(echo $TASKCLUSTER_WORKER_LOCATION | jq .availabilityZone | tr -d \") + region=$(echo $TASKCLUSTER_WORKER_LOCATION | jq .region | tr -d \") + ;; + esac + fi + if test -z "$availability_zone" -o -z "$region"; then + if test -n "${TASKCLUSTER_WORKER_GROUP}"; then + # TASKCLUSTER_WORKER_GROUP is just the region now, so + # stick an extra character on to make the already-convoluted logic + # here simpler. + availability_zone="${TASKCLUSTER_WORKER_GROUP}x" + elif [ -n "${SCCACHE_GCS_KEY_PATH}" ]; then + # gcp availability_zone is of the form <region>-<letter> where region is e.g. us-west2, and az is us-west2-a + gcp_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/computeMetadata/v1beta1/instance/zone || true) + availability_zone=${gcp_zone##*/} + else + # timeout after 1 second, and don't retry (failure indicates instance is not in ec2 or network issue) + # ec2 availability_zone is of the form <region><letter> where region is e.g. us-west-2, and az is us-west-2a + availability_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone || true) + fi + fi + if test -z "$availability_zone" -o "$availability_zone" = "not-ec2"; then + availability_zone=not-ec2 + elif test -n "$cloud"; then + case $cloud in + google) + bucket=${gcp_prefix}-l${MOZ_SCM_LEVEL}-${region} + ;; + aws) + bucket=${aws_prefix}-level-${MOZ_SCM_LEVEL}-sccache-${region} + ;; + esac + elif [ -n "${SCCACHE_GCS_KEY_PATH}" ]; then + # gcp region is az with last two letters trimmed + if test -z "$region"; then + region=${availability_zone::${#availability_zone}-2} + fi + bucket=${aws_prefix}-level-${MOZ_SCM_LEVEL}-sccache-${region} + else + # ec2 region is az with last letter trimmed + if test -z "$region"; then + region=${availability_zone%?} + fi + bucket=${aws_prefix}-level-${MOZ_SCM_LEVEL}-sccache-${region} + fi + fi +fi + +if test -n "$bucket"; then + if test "$cloud" = "google"; then + mk_add_options "export SCCACHE_GCS_BUCKET=$bucket" + mk_add_options "export SCCACHE_GCS_RW_MODE=READ_WRITE" + mk_add_options "export SCCACHE_GCS_CREDENTIALS_URL=http://taskcluster/auth/v1/gcp/credentials/$SCCACHE_GCS_PROJECT/${bucket}@$SCCACHE_GCS_PROJECT.iam.gserviceaccount.com" + elif [ -n "${SCCACHE_GCS_KEY_PATH}" ]; then + mk_add_options "export SCCACHE_GCS_BUCKET=$bucket" + else + mk_add_options "export SCCACHE_BUCKET=$bucket" + # instruct sccache to fetch the credentials from the Auth service's awsS3Credentials endpoint, via the Taskcluster proxy. + mk_add_options "export AWS_IAM_CREDENTIALS_URL=http://taskcluster/auth/v1/aws/s3/read-write/${bucket}/?format=iam-role-compat" + fi + export CCACHE="sccache" + export SCCACHE_VERBOSE_STATS=1 + # Workaround for https://github.com/mozilla/sccache/issues/459#issuecomment-618756635 + mk_add_options "export SCCACHE_MAX_FRAME_LENGTH=50000000" + mk_add_options MOZBUILD_MANAGE_SCCACHE_DAEMON=${MOZ_FETCHES_DIR}/sccache/sccache +elif test -n "$USE_SCCACHE"; then + echo "SetupError: sccache is enabled but there is no shared storage set up for it?" >&2 + exit 1 +fi diff --git a/build/mozconfig.clang-cl b/build/mozconfig.clang-cl new file mode 100644 index 0000000000..4ea7a59a09 --- /dev/null +++ b/build/mozconfig.clang-cl @@ -0,0 +1,21 @@ +if test -d "$MOZ_FETCHES_DIR/clang/bin"; then + CLANG_DIR=`cd "$MOZ_FETCHES_DIR/clang/bin" ; pwd` + export PATH="${CLANG_DIR}:${PATH}" +fi + +export CC=clang-cl +export CXX=clang-cl +export ENABLE_CLANG_PLUGIN=1 + +if [ -n "$UPLOAD_PATH" ]; then + case "$(uname -s)" in + MINGW*|MSYS*) + DIAGNOSTICS_DIR="$(cmd.exe //e:on //c if not exist ${UPLOAD_PATH} mkdir ${UPLOAD_PATH} && cd ${UPLOAD_PATH} && pwd)" + ;; + *) + DIAGNOSTICS_DIR="${UPLOAD_PATH}" + ;; + esac + export CFLAGS="$CFLAGS -fcrash-diagnostics-dir=${DIAGNOSTICS_DIR}" + export CXXFLAGS="$CXXFLAGS -fcrash-diagnostics-dir=${DIAGNOSTICS_DIR}" +fi diff --git a/build/mozconfig.common b/build/mozconfig.common new file mode 100644 index 0000000000..a67407ce4c --- /dev/null +++ b/build/mozconfig.common @@ -0,0 +1,30 @@ +# 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/. + +# Common mozconfig for official builds. +# +# Add options to this file that will be inherited by all in-tree mozconfigs. +# This is useful for eg try builds with nondefault options that apply to all +# architectures, though note that if you want to override options set in +# another mozconfig file, you'll need to use mozconfig.common.override instead +# of this file. + +if test -n "$USE_ARTIFACT"; then +. "$topsrcdir/build/mozconfig.artifact.automation" +fi + +mk_add_options AUTOCLOBBER=1 + +ac_add_options --enable-js-shell + +. "$topsrcdir/build/mozconfig.automation" +. "$topsrcdir/build/mozconfig.rust" +. "$topsrcdir/build/mozconfig.cache" + +if [ -n "$TASKCLUSTER_PGO_PROFILE_USE" -a -z "$USE_ARTIFACT" ]; then + export MOZ_LTO=cross + ac_add_options --enable-profile-use=cross + ac_add_options --with-pgo-jarlog="${MOZ_FETCHES_DIR}/en-US.log" + ac_add_options --with-pgo-profile-path="${MOZ_FETCHES_DIR}/merged.profdata" +fi diff --git a/build/mozconfig.common.override b/build/mozconfig.common.override new file mode 100644 index 0000000000..b3feefa5ec --- /dev/null +++ b/build/mozconfig.common.override @@ -0,0 +1,15 @@ +# 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/. + +# Common mozconfig for all users +# +# Add options to this file that will be inherited by all in-tree mozconfigs. +# This file is included at the *end* of the mozconfigs, and so may be used +# to override anything done previously. +# +# The common expected usage is for try builds with nondefault options. + +if test -n "$USE_ARTIFACT"; then +. "$topsrcdir/build/mozconfig.artifact" +fi diff --git a/build/mozconfig.lld-link b/build/mozconfig.lld-link new file mode 100644 index 0000000000..89f91930e7 --- /dev/null +++ b/build/mozconfig.lld-link @@ -0,0 +1,6 @@ +if test -d "$MOZ_FETCHES_DIR/clang/bin"; then + CLANG_DIR=`cd "$MOZ_FETCHES_DIR/clang/bin" ; pwd` + export PATH="${CLANG_DIR}:${PATH}" +fi + +export LINKER=lld-link diff --git a/build/mozconfig.no-compile b/build/mozconfig.no-compile new file mode 100644 index 0000000000..68dc06fb12 --- /dev/null +++ b/build/mozconfig.no-compile @@ -0,0 +1,31 @@ +ac_add_options --disable-compile-environment + +# In case mozconfig.cache was already included +unset CCACHE +unset SCCACHE_VERBOSE_STATS +# In case it wasn't +NO_CACHE=1 + +# Override any toolchain defines we've inherited from other mozconfigs. +unset CC +unset CXX +unset HOST_CC +unset HOST_CXX +unset LINKER +unset RUSTFLAGS +unset TOOLCHAIN_PREFIX +unset BINDGEN_CFLAGS +unset ENABLE_CLANG_PLUGIN +unset MACOS_SDK_DIR +unset MACOS_PRIVATE_FRAMEWORKS_DIR +unset WINSYSROOT +unset MOZ_LTO + +unset MOZ_STDCXX_COMPAT +unset MOZ_NO_PIE_COMPAT + +# Don't unset this on Linux artifact builds so the artifact builds correctly +# package any Wasm sandboxed shared libraries. +if test `uname -s` != Linux; then + unset WASM_SANDBOXED_LIBRARIES +fi diff --git a/build/mozconfig.rust b/build/mozconfig.rust new file mode 100644 index 0000000000..b7ab4d0219 --- /dev/null +++ b/build/mozconfig.rust @@ -0,0 +1 @@ +ac_add_options --enable-rust-simd diff --git a/build/mozconfig.win-common b/build/mozconfig.win-common new file mode 100644 index 0000000000..6fbe8159b2 --- /dev/null +++ b/build/mozconfig.win-common @@ -0,0 +1,3 @@ +# 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/. diff --git a/build/non-unified-compat b/build/non-unified-compat new file mode 100644 index 0000000000..7f9bb3e0b3 --- /dev/null +++ b/build/non-unified-compat @@ -0,0 +1,126 @@ +accessible/android/ +accessible/aom/ +accessible/atk/ +accessible/base/ +accessible/generic/ +accessible/html/ +accessible/interfaces/ +accessible/ipc/ +accessible/mac/ +accessible/other/ +accessible/tests/ +accessible/windows/ +accessible/xpcom/ +accessible/xul/ +docshell/base/ +docshell/build/ +docshell/resources/ +docshell/shistory/ +dom/abort/ +dom/animation/ +dom/audiochannel/ +dom/base/ +dom/battery/ +dom/bindings/ +dom/broadcastchannel/ +dom/browser-element/ +dom/cache/ +dom/canvas/ +dom/clients/ +dom/commandhandler/ +dom/console/ +dom/credentialmanagement/ +dom/crypto/ +dom/debugger/ +dom/docs/ +dom/encoding/ +dom/events/ +dom/fetch/ +dom/file/ +dom/filehandle/ +dom/filesystem/ +dom/flex/ +dom/gamepad/ +dom/geolocation/ +dom/grid/ +dom/html/ +dom/imptests/ +dom/indexedDB/ +dom/interfaces/ +dom/ipc/ +dom/jsurl/ +dom/l10n/ +dom/locales/ +dom/localstorage/ +dom/manifest/ +dom/mathml/ +dom/media/ +dom/messagechannel/ +dom/midi/ +dom/network/ +dom/notification/ +dom/offline/ +dom/payments/ +dom/performance/ +dom/permission/ +dom/plugins/ +dom/power/ +dom/quota/ +dom/reporting/ +dom/res/ +dom/script/ +dom/security/ +dom/serviceworkers/ +dom/simpledb/ +dom/smil/ +dom/storage/ +dom/svg/ +dom/system/ +dom/tests/ +dom/u2f/ +dom/url/ +dom/vr/ +dom/webauthn/ +dom/webbrowserpersist/ +dom/webgpu/ +dom/webidl/ +dom/webshare/ +dom/websocket/ +dom/workers/ +dom/worklet/ +dom/xhr/ +dom/xml/ +dom/xslt/ +dom/xul/ +editor/composer/ +editor/libeditor/ +editor/reftests/ +editor/spellchecker/ +editor/txmgr/ +extensions/auth/ +extensions/permissions/ +extensions/pref/ +extensions/spellcheck/ +extensions/universalchardet/ +gfx/2d/ +gfx/config/ +gfx/gl/ +gfx/ipc/ +gfx/layers/ +gfx/ots/ +gfx/qcms/ +gfx/sfntly/ +gfx/src/ +gfx/tests/ +gfx/thebes/ +gfx/vr/ +gfx/webrender_bindings/ +gfx/wgpu_bindings/ +gfx/wr/ +gfx/ycbcr/ +hal/ +image/ +ipc/glue/ +mozglue/baseprofiler +netwerk/cache2/ +tools/profiler diff --git a/build/package/mac_osx/make-diskimage b/build/package/mac_osx/make-diskimage new file mode 100755 index 0000000000..c214ceb59c --- /dev/null +++ b/build/package/mac_osx/make-diskimage @@ -0,0 +1,47 @@ +#!/bin/sh +# 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/. + +# Create a read-only disk image of the contents of a folder +# +# Usage: make-diskimage <image_file> +# <src_folder> +# <volume_name> +# <eula_resource_file> +# <.dsstore_file> +# <background_image_file> +# +# tip: use '-null-' for <eula-resource-file> if you only want to +# provide <.dsstore_file> and <background_image_file> + +DMG_PATH=$1 +SRC_FOLDER=$2 +VOLUME_NAME=$3 + +# optional arguments +EULA_RSRC=$4 +DMG_DSSTORE=$5 +DMG_BKGND_IMG=$6 + +EXTRA_ARGS= + +if test -n "$EULA_RSRC" && test "$EULA_RSRC" != "-null-" ; then + EXTRA_ARGS="--resource $EULA_RSRC" +fi + +if test -n "$DMG_DSSTORE" ; then + EXTRA_ARGS="$EXTRA_ARGS --copy $DMG_DSSTORE:/.DS_Store" +fi + +if test -n "$DMG_BKGND_IMG" ; then + EXTRA_ARGS="$EXTRA_ARGS --mkdir /.background --copy $DMG_BKGND_IMG:/.background" +fi + +echo `dirname $0`/pkg-dmg --target "$DMG_PATH" --source "$SRC_FOLDER" \ + --volname "$VOLUME_NAME" $EXTRA_ARGS + +`dirname $0`/pkg-dmg --target "$DMG_PATH" --source "$SRC_FOLDER" \ + --volname "$VOLUME_NAME" $EXTRA_ARGS + +exit $? diff --git a/build/package/mac_osx/mozilla-background.jpg b/build/package/mac_osx/mozilla-background.jpg Binary files differnew file mode 100644 index 0000000000..adb4df036e --- /dev/null +++ b/build/package/mac_osx/mozilla-background.jpg diff --git a/build/package/mac_osx/mozilla.dsstore b/build/package/mac_osx/mozilla.dsstore Binary files differnew file mode 100644 index 0000000000..520eb08d6f --- /dev/null +++ b/build/package/mac_osx/mozilla.dsstore diff --git a/build/package/mac_osx/requirements.plist b/build/package/mac_osx/requirements.plist new file mode 100644 index 0000000000..dd904f0496 --- /dev/null +++ b/build/package/mac_osx/requirements.plist @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>arch</key> + <array> + <string>x86_64</string> + <string>arm64</string> + </array> +</dict> +</plist> diff --git a/build/package/mac_osx/unpack-diskimage b/build/package/mac_osx/unpack-diskimage new file mode 100755 index 0000000000..3ba977805e --- /dev/null +++ b/build/package/mac_osx/unpack-diskimage @@ -0,0 +1,54 @@ +#!/bin/bash +# 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/. + +# Unpack a disk image to a specified target folder +# +# Usage: unpack-diskimage <image_file> +# <mountpoint> +# <target_path> + +DMG_PATH=$1 +MOUNTPOINT=$2 +TARGETPATH=$3 + +# How long to wait before giving up waiting for the mount to finish (seconds) +TIMEOUT=90 + +# If mnt already exists, then the previous run may not have cleaned up +# properly. We should try to umount and remove the mnt directory. +if [ -d $MOUNTPOINT ]; then + echo "mnt already exists, trying to clean up" + hdiutil detach $MOUNTPOINT -force + rm -rdfv $MOUNTPOINT +fi + +# Install an on-exit handler that will unmount and remove the '$MOUNTPOINT' directory +trap "{ if [ -d $MOUNTPOINT ]; then hdiutil detach $MOUNTPOINT -force; rm -rdfv $MOUNTPOINT; fi; }" EXIT + +mkdir -p $MOUNTPOINT + +hdiutil attach -verbose -noautoopen -mountpoint $MOUNTPOINT "$DMG_PATH" +# Wait for files to show up +# hdiutil uses a helper process, diskimages-helper, which isn't always done its +# work by the time hdiutil exits. So we wait until something shows up in the +# mnt directory. Due to the async nature of diskimages-helper, the best thing +# we can do is to make sure the glob() rsync is making can find files. +i=0 +while [ "$(echo $MOUNTPOINT/*)" == "$MOUNTPOINT/*" ]; do + if [ $i -gt $TIMEOUT ]; then + echo "No files found, exiting" + exit 1 + fi + sleep 1 + i=$(expr $i + 1) +done +# Now we can copy everything out of the $MOUNTPOINT directory into the target directory +rsync -av $MOUNTPOINT/* $MOUNTPOINT/.DS_Store $MOUNTPOINT/.background $MOUNTPOINT/.VolumeIcon.icns $TARGETPATH/. +hdiutil detach $MOUNTPOINT +rm -rdf $MOUNTPOINT +# diskimage-helper prints messages to stdout asynchronously as well, sleep +# for a bit to ensure they don't disturb following commands in a script that +# might parse stdout messages +sleep 5 diff --git a/build/pgo/blueprint/LICENSE b/build/pgo/blueprint/LICENSE new file mode 100644 index 0000000000..d7474100a9 --- /dev/null +++ b/build/pgo/blueprint/LICENSE @@ -0,0 +1,314 @@ +Blueprint CSS Framework License +---------------------------------------------------------------- + +Copyright (c) 2007-2008 Olav Bjorkoy (olav at bjorkoy.com) + +The Blueprint CSS Framework is available for use in all personal or +commercial projects, under both the (modified) MIT and the GPL license. You +may choose the one that fits your project. + + +The (modified) MIT License +---------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice, and every other copyright notice found in this +software, and all the attributions in every file, and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +The GPL License +---------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES.
\ No newline at end of file diff --git a/build/pgo/blueprint/elements.html b/build/pgo/blueprint/elements.html new file mode 100644 index 0000000000..8749953761 --- /dev/null +++ b/build/pgo/blueprint/elements.html @@ -0,0 +1,350 @@ +<!-- 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/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Blueprint HTML Elements Tests</title> + + <!-- Framework CSS --> + <link + rel="stylesheet" + href="screen.css" + type="text/css" + media="screen, projection" + /> + <link rel="stylesheet" href="print.css" type="text/css" media="print" /> + <!--[if IE + ]><link + rel="stylesheet" + href="ie.css" + type="text/css" + media="screen, projection" + /><![endif]--> + </head> + <body> + <div class="container showgrid"> + <h2>Tests for common HTML elements</h2> + <hr /> + + <h5>PARAGRAPHS <span class="alt">&</span> BOXES</h5> + + <div class="span-8"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + </p> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor <sub>sub text</sub> ut labore et + <sup>sup text</sup> magna aliqua. Ut enim ad minim veniam, quis + nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat + cupidatat non proident, sunt in culpa qui officia deserunt mollit anim + id est laborum. + </p> + </div> + + <div class="span-8"> + <p class="small"> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. + </p> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + <p class="large"> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-8 last"> + <div class="box"> + <p class="last"> + Aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + </p> + </div> + <blockquote> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. + </p> + </blockquote> + </div> + <hr /> + + <h5>LISTS</h5> + + <div class="span-8"> + <ul> + <li>Unordered list test</li> + <li> + Another list element. Lorem ipsum dolor sit amet, consectetur + adipisicing elit. + </li> + <li>Yet another element in the list</li> + <li> + Some long text. Lorem ipsum dolor sit amet, consectetur adipisicing + elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit. + </li> + </ul> + <ol> + <li>Ordered list test</li> + <li>Another list element</li> + <li>Yet another element in the list</li> + </ol> + </div> + + <div class="span-8"> + <ol> + <li>Ordered list</li> + <li> + Here's a nested unordered list + <ul> + <li>Nested Unordered list</li> + <li> + Nested ordered list + <ol> + <li>The first</li> + <li>And the second</li> + </ol> + </li> + </ul> + </li> + <li>Ordered List item</li> + <li> + Nested Ordered list + <ol> + <li>Some point</li> + <li> + Nested Unordered list + <ul> + <li>The first</li> + <li>And the second</li> + </ul> + </li> + </ol> + </li> + </ol> + </div> + + <div class="span-8 last"> + <dl> + <dt>definition list dt</dt> + <dd>definition list dd</dd> + <dt>definition list dt</dt> + <dd>definition list dd</dd> + <dt> + Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing + elit adipisicing elit + </dt> + <dd> + Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing + elit adipisicing elit + </dd> + <dt> + Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing + elit adipisicing elit + </dt> + <dd> + Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing + elit adipisicing elit + </dd> + </dl> + </div> + <hr /> + + <h5>HEADINGS</h5> + + <div class="span-8"> + <h1>H1: Lorem ipsum dolor sit amet</h1> + <h2>H2: Lorem ipsum dolor sit amet, consectetur elit</h2> + <h3>H3: Lorem ipsum dolor sit amet, consectetur adipisicing elit</h3> + <h4> + H4: Lorem ipsum dolor sit amet, consectetur adipisicing elit adipis + </h4> + <h5> + H5: Lorem ipsum dolor sit amet, consectetur adipisicing elit + adipisicing elit adipisicing elit + </h5> + <h6> + H6: Lorem ipsum dolor sit amet, consectetur adipisicing elit + adipisicing elit adipisicing elit + </h6> + </div> + + <div class="span-8"> + <h1>Heading 1</h1> + <hr /> + <h2>Heading 2</h2> + <hr /> + <h3>Heading 3</h3> + <hr /> + <h4>Heading 4</h4> + <hr /> + <h5>Heading 5</h5> + <hr /> + <h6>Heading 6</h6> + </div> + + <div class="span-8 last"> + <h1>Heading 1</h1> + <h2>Heading 2</h2> + <h3>Heading 3</h3> + <h4>Heading 4</h4> + <h5>Heading 5</h5> + <h6>Heading 6</h6> + </div> + <hr /> + + <h5>MISC ELEMENTS</h5> + + <div class="span-8"> + <p> + <strong><strong></strong><br /> + <del><del> deleted</del><br /> + <dfn><dfn> dfn</dfn><br /> + <em><em> emphasis</em> + </p> + <p> + <a><a> anchor</a><br /> + <a href="http://www.google.com"><a> a + href</a> + </p> + <p> + <abbr title="extended abbr text should show when mouse over" + ><abbr> abbr - extended text when mouseover.</abbr + ><br /> + <acronym title="extended acronym text should show when mouse over" + ><acronym> acronym - extended text when mouseover.</acronym + > + </p> + <address> + <address><br /> + Donald Duck<br /> + Box 555<br /> + Disneyland + </address> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore dolore. + </p> + </div> + + <div class="span-8"> + <table + summary="This is the summary text for this table." + border="0" + cellspacing="0" + cellpadding="0" + > + <caption> + <em>A standard test table with a caption, tr, td elements</em> + </caption> + <tr> + <th class="span-4">Table Header One</th> + <th class="span-4 last">Table Header Two</th> + </tr> + <tr> + <td>TD One</td> + <td>TD Two</td> + </tr> + <tr> + <td colspan="2">TD colspan 2</td> + </tr> + </table> + + <table + summary="This is the summary text for this table." + border="0" + cellspacing="0" + cellpadding="0" + > + <caption> + <em>A test table with a thead, tfoot, and tbody elements</em> + </caption> + <thead> + <tr> + <th class="span-4">Table Header One</th> + <th class="span-4 last">Table Header Two</th> + </tr> + </thead> + <tfoot> + <tr> + <td colspan="2">tfoot footer</td> + </tr> + </tfoot> + <tbody> + <tr> + <td>TD One</td> + <td>TD Two</td> + </tr> + <tr> + <td>TD One</td> + <td>TD Two</td> + </tr> + </tbody> + <tbody> + <tr> + <td>TD One</td> + <td>TD Two</td> + </tr> + <tr> + <td>TD One</td> + <td>TD Two</td> + </tr> + </tbody> + </table> + </div> + + <div class="span-8 last"> + <pre> +<pre> +pre space1 +pre space1 +pre space2 +pre space2 +pre tab +pre tab</pre + > + + <code><code> Not indented indent1 indent1 indent2 indent3</code> + + <tt + ><tt> This tt text should be monospaced and wrap as if one line + of text even though the code has newlines, spaces, and tabs. It should + be the same size as <p> text. + </tt> + </div> + <hr /> + + <p> + <a href="http://validator.w3.org/check?uri=referer"> + <img + src="valid.png" + alt="Valid HTML 4.01 Strict" + height="31" + width="88" + class="top" + /></a> + </p> + </div> + </body> +</html> diff --git a/build/pgo/blueprint/fancytype-screen.css b/build/pgo/blueprint/fancytype-screen.css new file mode 100644 index 0000000000..0d3feb77f7 --- /dev/null +++ b/build/pgo/blueprint/fancytype-screen.css @@ -0,0 +1,75 @@ +/* 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/. */ + +/* -------------------------------------------------------------- + + fancy-type.css + * Lots of pretty advanced classes for manipulating text. + + See the Readme file in this folder for additional instructions. + +-------------------------------------------------------------- */ + +/* Indentation instead of line shifts for sibling paragraphs. */ + p + p { text-indent:2em; margin-top:-1.5em; } + form p + p { text-indent: 0; } /* Don't want this in forms. */ + + +/* For great looking type, use this code instead of asdf: + <span class="alt">asdf</span> + Best used on prepositions and ampersands. */ + +.alt { + color: #666; + font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif; + font-style: italic; + font-weight: normal; +} + + +/* For great looking quote marks in titles, replace "asdf" with: + <span class="dquo">“</span>asdf” + (That is, when the title starts with a quote mark). + (You may have to change this value depending on your font size). */ + +.dquo { margin-left: -.5em; } + + +/* Reduced size type with incremental leading + (http://www.markboulton.co.uk/journal/comments/incremental_leading/) + + This could be used for side notes. For smaller type, you don't necessarily want to + follow the 1.5x vertical rhythm -- the line-height is too much. + + Using this class, it reduces your font size and line-height so that for + every four lines of normal sized type, there is five lines of the sidenote. eg: + + New type size in em's: + 10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems) + + New line-height value: + 12px x 1.5 = 18px (old line-height) + 18px x 4 = 72px + 72px / 5 = 14.4px (new line height) + 14.4px / 10px = 1.44 (new line height in em's) */ + +p.incr, .incr p { + font-size: 10px; + line-height: 1.44em; + margin-bottom: 1.5em; +} + + +/* Surround uppercase words and abbreviations with this class. + Based on work by Jørgen Arnor Gårdsø Lom [http://twistedintellect.com/] */ + +.caps { + font-variant: small-caps; + letter-spacing: 1px; + text-transform: lowercase; + font-size:1.2em; + line-height:1%; + font-weight:bold; + padding:0 2px; +} diff --git a/build/pgo/blueprint/forms.html b/build/pgo/blueprint/forms.html new file mode 100644 index 0000000000..68a9512c97 --- /dev/null +++ b/build/pgo/blueprint/forms.html @@ -0,0 +1,144 @@ +<!-- 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/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Blueprint Forms Tests</title> + + <!-- Framework CSS --> + <link + rel="stylesheet" + href="screen.css" + type="text/css" + media="screen, projection" + /> + <link rel="stylesheet" href="print.css" type="text/css" media="print" /> + <!--[if IE + ]><link + rel="stylesheet" + href="ie.css" + type="text/css" + media="screen, projection" + /><![endif]--> + </head> + <body> + <div class="container showgrid"> + <h1>Forms</h1> + <hr /> + + <div class="span-12"> + <form id="dummy" action="" method="post"> + <fieldset> + <legend>Simple sample form</legend> + + <p> + <label for="dummy0">Text input (title)</label><br /> + <input + type="text" + class="title" + name="dummy0" + id="dummy0" + value="Field with class .title" + /> + </p> + + <p> + <label for="dummy1">Another field</label><br /> + <input + type="text" + class="text" + id="dummy1" + name="dummy1" + value="Field with class .text" + /> + </p> + + <p> + <label for="dummy2">Textarea</label><br /> + <textarea name="dummy2" id="dummy2" rows="5" cols="20"></textarea> + </p> + + <p> + <input type="submit" value="Submit" /> + <input type="reset" value="Reset" /> + </p> + </fieldset> + </form> + </div> + <div class="span-12 last"> + <div class="error"> + This is a <div> with the class <strong>.error</strong>. + <a href="#">Link</a>. + </div> + <div class="notice"> + This is a <div> with the class <strong>.notice</strong>. + <a href="#">Link</a>. + </div> + <div class="success"> + This is a <div> with the class <strong>.success</strong>. + <a href="#">Link</a>. + </div> + + <fieldset> + <legend>Select, checkboxes, lists</legend> + + <p> + <label for="dummy3">Select field</label><br /> + <select id="dummy3" name="dummy3"> + <option value="1">Ottawa</option> + <option value="2">Calgary</option> + <option value="3">Moosejaw</option> + </select> + </p> + + <p> + <label for="dummy4">Select with groups</label><br /> + <select id="dummy4" name="dummy4"> + <option>Favorite pet</option> + <optgroup label="mammals"> + <option>dog</option> + <option>cat</option> + <option>rabbit</option> + <option>horse</option> + </optgroup> + <optgroup label="reptiles"> + <option>iguana</option> + <option>snake</option> + </optgroup> + </select> + </p> + + <p> + <label>Radio buttons</label><br /> + <input type="radio" name="example" /> Radio one<br /> + <input type="radio" name="example" /> Radio two<br /> + <input type="radio" name="example" /> Radio three<br /> + </p> + + <p> + <label>Checkboxes</label><br /> + <input type="checkbox" /> Check one<br /> + <input type="checkbox" /> Check two<br /> + <input type="checkbox" /> Check three<br /> + </p> + </fieldset> + </div> + <hr /> + + <p> + <a href="http://validator.w3.org/check?uri=referer"> + <img + src="valid.png" + alt="Valid HTML 4.01 Strict" + height="31" + width="88" + class="top" + /></a> + </p> + </div> + </body> +</html> diff --git a/build/pgo/blueprint/grid.html b/build/pgo/blueprint/grid.html new file mode 100644 index 0000000000..d127f87c88 --- /dev/null +++ b/build/pgo/blueprint/grid.html @@ -0,0 +1,317 @@ +<!-- 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/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Blueprint Grid Tests</title> + + <!-- Framework CSS --> + <link + rel="stylesheet" + href="screen.css" + type="text/css" + media="screen, projection" + /> + <link rel="stylesheet" href="print.css" type="text/css" media="print" /> + <!--[if IE + ]><link + rel="stylesheet" + href="ie.css" + type="text/css" + media="screen, projection" + /><![endif]--> + </head> + <body> + <div class="container showgrid"> + <h1>Blueprint Tests: grid.css</h1> + + <div class="span-8"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <div class="span-8"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <div class="span-8 last"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + + <div class="span-6 append-1"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <div class="span-6 append-2"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <div class="span-6 append-3 last"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + + <div class="span-6 prepend-1"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <div class="span-6 prepend-2"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <div class="span-6 prepend-3 last"> + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> + </div> + <hr /> + + <div class="span-12 border"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + </p> + </div> + <div class="span-12 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + </p> + </div> + <hr /> + + <div class="span-1 prepend-1"><p>1</p></div> + <div class="span-1 prepend-2"><p>2</p></div> + <div class="span-1 prepend-3"><p>3</p></div> + <div class="span-1 prepend-4"><p>4</p></div> + <div class="span-1 prepend-5"><p>5</p></div> + <div class="span-1 prepend-3 last"><p>3</p></div> + + <div class="span-1 append-1"><p>1</p></div> + <div class="span-1 append-2"><p>2</p></div> + <div class="span-1 append-3"><p>3</p></div> + <div class="span-1 append-4"><p>4</p></div> + <div class="span-1 append-5"><p>5</p></div> + <div class="span-1 append-3 last"><p>3</p></div> + + <div class="span-1 border"><p>1</p></div> + <div class="span-1 border"><p>2</p></div> + <div class="span-1 border"><p>3</p></div> + <div class="span-1 border"><p>4</p></div> + <div class="span-1 border"><p>5</p></div> + <div class="span-1 border"><p>6</p></div> + <div class="span-1 border"><p>7</p></div> + <div class="span-1 border"><p>8</p></div> + <div class="span-1 border"><p>9</p></div> + <div class="span-1 border"><p>10</p></div> + <div class="span-1 border"><p>11</p></div> + <div class="span-1 border"><p>12</p></div> + <div class="span-1 border"><p>13</p></div> + <div class="span-1 border"><p>14</p></div> + <div class="span-1 border"><p>15</p></div> + <div class="span-1 border"><p>16</p></div> + <div class="span-1 border"><p>17</p></div> + <div class="span-1 border"><p>18</p></div> + <div class="span-1 border"><p>19</p></div> + <div class="span-1 border"><p>20</p></div> + <div class="span-1 border"><p>21</p></div> + <div class="span-1 border"><p>22</p></div> + <div class="span-1 border"><p>23</p></div> + <div class="span-1 last"><p>24</p></div> + + <div class="span-4"><p>1</p></div> + <div class="span-4"><p>2</p></div> + <div class="span-4"><p>3</p></div> + <div class="span-4"><p>4</p></div> + <div class="span-4"><p>5</p></div> + <div class="span-4 last"><p>6</p></div> + + <div class="prepend-23 span-1 last"><p>24</p></div> + + <div class="prepend-1 span-1"><p>2</p></div> + <div class="prepend-20 span-1 append-1 last"><p>23</p></div> + <hr /> + + <div class="span-24"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + </p> + </div> + + <div class="span-12"> + <div class="span-6"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod. + </p> + </div> + + <div class="span-6 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-12 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + </div> + + <div class="span-12 last"> + <div class="span-6"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod. + </p> + </div> + + <div class="span-6 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-12 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + </div> + + <div class="span-14 prepend-5 append-5 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + <hr /> + + <div class="span-12"> + <h5>TESTING .PUSH-1 TO .PUSH-5</h5> + + <div class="span-2"><img src="test-small.jpg" class="push-1" /></div> + <div class="span-10 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-2"><img src="test-small.jpg" class="push-2" /></div> + <div class="span-10 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-2"><img src="test-small.jpg" class="push-3" /></div> + <div class="span-10 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-2"><img src="test-small.jpg" class="push-4" /></div> + <div class="span-10 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + + <div class="span-2"><img src="test-small.jpg" class="push-5" /></div> + <div class="span-10 last"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + </div> + + <div class="span-12 last"> + <h5>TESTING .PULL-1 TO .PULL-5</h5> + + <div class="span-10"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + <div class="span-2 last"> + <img src="test-small.jpg" class="top pull-1" /> + </div> + + <div class="span-10"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + <div class="span-2 last"> + <img src="test-small.jpg" class="top pull-2" /> + </div> + + <div class="span-10"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + <div class="span-2 last"> + <img src="test-small.jpg" class="top pull-3" /> + </div> + + <div class="span-10"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + <div class="span-2 last"> + <img src="test-small.jpg" class="top pull-4" /> + </div> + + <div class="span-10"> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. + </p> + </div> + <div class="span-2 last"> + <img src="test-small.jpg" class="top pull-5" /> + </div> + </div> + + <div class="span-24"> + <p> + <a href="http://validator.w3.org/check?uri=referer"> + <img + src="valid.png" + alt="Valid HTML 4.01 Strict" + height="31" + width="88" + class="bottom" + /></a> + </p> + </div> + </div> + </body> +</html> diff --git a/build/pgo/blueprint/grid.png b/build/pgo/blueprint/grid.png Binary files differnew file mode 100644 index 0000000000..129d4a29fb --- /dev/null +++ b/build/pgo/blueprint/grid.png diff --git a/build/pgo/blueprint/print.css b/build/pgo/blueprint/print.css new file mode 100644 index 0000000000..661861457a --- /dev/null +++ b/build/pgo/blueprint/print.css @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------- + + Blueprint CSS Framework 0.7.1 + http://blueprintcss.googlecode.com + + * Copyright (c) 2007-2008. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* print.css */ +body {line-height:1.5;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;color:#000;background:none;font-size:10pt;} +.container {background:none;} +hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;} +hr.space {background:#fff;color:#fff;} +h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;} +code {font:.9em "Courier New", Monaco, Courier, monospace;} +img {float:left;margin:1.5em 1.5em 1.5em 0;} +a img {border:none;} +p img.top {margin-top:0;} +blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;} +.small {font-size:.9em;} +.large {font-size:1.1em;} +.quiet {color:#999;} +.hide {display:none;} +a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;} +a:link:after, a:visited:after {content:" (" attr(href) ") ";font-size:90%;}
\ No newline at end of file diff --git a/build/pgo/blueprint/sample.html b/build/pgo/blueprint/sample.html new file mode 100644 index 0000000000..8ae603717b --- /dev/null +++ b/build/pgo/blueprint/sample.html @@ -0,0 +1,227 @@ +<!-- 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/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Blueprint Sample Page</title> + + <!-- Framework CSS --> + <link + rel="stylesheet" + href="screen.css" + type="text/css" + media="screen, projection" + /> + <link rel="stylesheet" href="print.css" type="text/css" media="print" /> + <!--[if IE + ]><link + rel="stylesheet" + href="ie.css" + type="text/css" + media="screen, projection" + /><![endif]--> + + <!-- Import fancy-type plugin for the sample page. --> + <link + rel="stylesheet" + href="fancytype-screen.css" + type="text/css" + media="screen, projection" + /> + </head> + + <body> + <div class="container"> + <h1>A simple sample page</h1> + <hr /> + <h2 class="alt"> + This sample page demonstrates a tiny fraction of what you get with + Blueprint. + </h2> + <hr /> + + <div class="span-7 colborder"> + <h6>Here's a box</h6> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip. + </p> + </div> + + <div class="span-8 colborder"> + <h6>And another box</h6> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat laboris nisi ut aliquip. + </p> + </div> + + <div class="span-7 last"> + <h6>This box is aligned with the sidebar</h6> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip. + </p> + </div> + <hr /> + <hr class="space" /> + + <div class="span-15 prepend-1 colborder"> + <p> + <img src="test.jpg" class="top pull-1" alt="test" />Lorem ipsum dolor + sit amet, <em>consectetuer adipiscing elit</em>. Nunc congue ipsum + vestibulum libero. Aenean vitae justo. Nam eget tellus. Etiam + convallis, est eu lobortis mattis, lectus tellus tempus felis, a + ultricies erat ipsum at metus. + </p> + <p> + Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + <a href="#">Morbi et risus</a>. Aliquam nisl. Nulla facilisi. Cras + accumsan vestibulum ante. Vestibulum sed tortor. Praesent + <span class="caps">SMALL CAPS</span> tempus fringilla elit. Ut elit + diam, sagittis in, nonummy in, gravida non, nunc. Ut orci. Class + aptent taciti sociosqu ad litora torquent per conubia nostra, per + inceptos hymenaeos. Nam egestas, orci eu imperdiet malesuada, nisl + purus fringilla odio, quis commodo est orci vitae justo. Aliquam + placerat odio tincidunt nulla. Cras in libero. Aenean rutrum, magna + non tristique posuere, erat odio eleifend nisl, non convallis est + tortor blandit ligula. Nulla id augue. + </p> + <p> + Nullam mattis, odio ut tempus facilisis, metus nisl facilisis metus, + auctor consectetuer felis ligula nec mauris. Vestibulum odio erat, + fermentum at, commodo vitae, ultrices et, urna. Mauris vulputate, mi + pulvinar sagittis condimentum, sem nulla aliquam velit, sed imperdiet + mi purus eu magna. Nulla varius metus ut eros. Aenean aliquet magna + eget orci. Class aptent taciti sociosqu ad litora. + </p> + <p> + Vivamus euismod. Cum sociis natoque penatibus et magnis dis parturient + montes, nascetur ridiculus mus. Suspendisse vel nibh ut turpis dictum + sagittis. Aliquam vel velit a elit auctor sollicitudin. Nam vel dui + vel neque lacinia pretium. Quisque nunc erat, venenatis id, volutpat + ut, scelerisque sed, diam. Mauris ante. Pellentesque habitant morbi + tristique senectus et netus et malesuada fames ac turpis egestas. + Donec mattis. Morbi dignissim sollicitudin libero. Nulla lorem. + </p> + <blockquote> + <p> + Integer cursus ornare mauris. Praesent nisl arcu, imperdiet eu, + ornare id, scelerisque ut, nunc. Praesent sagittis erat sed velit + tempus imperdiet. Ut tristique, ante in interdum hendrerit, erat + enim faucibus felis, quis rutrum mauris lorem quis sem. Vestibulum + ligula nisi, mattis nec, posuere et, blandit eu, ligula. Nam + suscipit placerat odio. Class aptent taciti sociosqu ad litora + torquent per conubia nostra, per inceptos hymenaeos. Pellentesque + tortor libero, venenatis vitae, rhoncus eu, placerat ut, mi. Nulla + nulla. + </p> + </blockquote> + <p> + Maecenas vel metus quis magna pharetra fermentum. + <em>Integer sit amet tortor</em>. Maecenas porttitor, pede sed gravida + auctor, nulla augue aliquet elit, at pretium urna orci ut metus. + Aliquam in dolor. Vestibulum ante ipsum primis in faucibus orci luctus + et ultrices posuere cubilia Curae; Sed aliquam, tellus id ornare + posuere, quam nunc accumsan turpis, at convallis tellus orci et nisl. + Phasellus congue neque a lorem. + </p> + + <hr /> + <div class="span-7 colborder"> + <h6>This is a nested column</h6> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. + </p> + </div> + <div class="span-7 last"> + <h6>This is another nested column</h6> + <p> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. + </p> + </div> + </div> + <div class="span-7 last"> + <h3>A <span class="alt">Simple</span> Sidebar</h3> + + <p> + Vestibulum ante ipsum primis in faucibus orci luctus et ultrices + posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede + sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem + nisi vel augue. + </p> + <p> + Mauris a lectus. Aliquam erat volutpat. Phasellus ultrices mi a + sapien. Nunc rutrum egestas lorem. Duis ac sem sagittis elit tincidunt + gravida. Mauris a lectus. Aliquam erat volutpat. Phasellus ultrices mi + a sapien. Nunc rutrum egestas lorem. Duis ac sem sagittis elit + tincidunt gravida. + </p> + <p class="quiet"> + Vestibulum ante ipsum primis in faucibus orci luctus et ultrices + posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede + sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem + nisi vel augue. + </p> + + <h5>Incremental leading</h5> + <p class="incr"> + Vestibulum ante ipsum primis in faucibus orci luctus vestibulum ante + ipsum primis in faucibus orci luctus et ultrices posuere cubilia + Curae; Cras ornare mattis nunc. Mauris venenatis, pede sed aliquet + vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue. + sed aliquet vehicula, lectus tellus. + </p> + <p class="incr"> + Vestibulum ante ipsum primis in faucibus orci luctus et ultrices + posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede + sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem + nisi vel augue. sed aliquet vehicula, lectus tellus pulvinar neque, + non cursus sem nisi vel augue. ipsum primis in faucibus orci luctus et + ultrices posuere cubilia Curae; Cras ornare mattis nunc. Mauris + venenatis, pede sed aliquet vehicula, lectus tellus pulvinar neque, + non cursus sem nisi vel augue. sed aliquet vehicula, lectus tellus + pulvinar neque, non cursus sem nisi vel augue. + </p> + </div> + + <hr /> + <h2 class="alt"> + You may pick and choose amongst these and many more features, so be + bold. + </h2> + <hr /> + + <p> + <a href="http://validator.w3.org/check?uri=referer"> + <img + src="valid.png" + alt="Valid HTML 4.01 Strict" + height="31" + width="88" + class="top" + /></a> + </p> + </div> + </body> +</html> diff --git a/build/pgo/blueprint/screen.css b/build/pgo/blueprint/screen.css new file mode 100644 index 0000000000..c631ead6a1 --- /dev/null +++ b/build/pgo/blueprint/screen.css @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------- + + Blueprint CSS Framework 0.7.1 + http://blueprintcss.googlecode.com + + * Copyright (c) 2007-2008. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* reset.css */ +html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} +body {line-height:1.5;} +table {border-collapse:separate;border-spacing:0;} +caption, th, td {text-align:left;font-weight:normal;} +table, td, th {vertical-align:middle;} +blockquote:before, blockquote:after, q:before, q:after {content:"";} +blockquote, q {quotes:"" "";} +a img {border:none;} + +/* typography.css */ +body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;} +h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} +h2 {font-size:2em;margin-bottom:0.75em;} +h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} +h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;height:1.25em;} +h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} +h6 {font-size:1em;font-weight:bold;} +h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} +p {margin:0 0 1.5em;} +p img {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} +p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} +a:focus, a:hover {color:#000;} +a {color:#009;text-decoration:underline;} +blockquote {margin:1.5em;color:#666;font-style:italic;} +strong {font-weight:bold;} +em, dfn {font-style:italic;} +dfn {font-weight:bold;} +sup, sub {line-height:0;} +abbr, acronym {border-bottom:1px dotted #666;} +address {margin:0 0 1.5em;font-style:italic;} +del {color:#666;} +pre, code {margin:1.5em 0;white-space:pre;} +pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} +li ul, li ol {margin:0 1.5em;} +ul, ol {margin:0 1.5em 1.5em 1.5em;} +ul {list-style-type:disc;} +ol {list-style-type:decimal;} +dl {margin:0 0 1.5em 0;} +dl dt {font-weight:bold;} +dd {margin-left:1.5em;} +table {margin-bottom:1.4em;width:100%;} +th {font-weight:bold;background:#C3D9FF;} +th, td {padding:4px 10px 4px 5px;} +tr.even td {background:#E5ECF9;} +tfoot {font-style:italic;} +caption {background:#eee;} +.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} +.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} +.hide {display:none;} +.quiet {color:#666;} +.loud {color:#000;} +.highlight {background:#ff0;} +.added {background:#060;color:#fff;} +.removed {background:#900;color:#fff;} +.first {margin-left:0;padding-left:0;} +.last {margin-right:0;padding-right:0;} +.top {margin-top:0;padding-top:0;} +.bottom {margin-bottom:0;padding-bottom:0;} + +/* grid.css */ +.container {width:950px;margin:0 auto;} +.showgrid {background:url(grid.png);} +body {margin:1.5em 0;} +div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;} +div.last {margin-right:0;} +.span-1 {width:30px;} +.span-2 {width:70px;} +.span-3 {width:110px;} +.span-4 {width:150px;} +.span-5 {width:190px;} +.span-6 {width:230px;} +.span-7 {width:270px;} +.span-8 {width:310px;} +.span-9 {width:350px;} +.span-10 {width:390px;} +.span-11 {width:430px;} +.span-12 {width:470px;} +.span-13 {width:510px;} +.span-14 {width:550px;} +.span-15 {width:590px;} +.span-16 {width:630px;} +.span-17 {width:670px;} +.span-18 {width:710px;} +.span-19 {width:750px;} +.span-20 {width:790px;} +.span-21 {width:830px;} +.span-22 {width:870px;} +.span-23 {width:910px;} +.span-24, div.span-24 {width:950px;margin:0;} +.append-1 {padding-right:40px;} +.append-2 {padding-right:80px;} +.append-3 {padding-right:120px;} +.append-4 {padding-right:160px;} +.append-5 {padding-right:200px;} +.append-6 {padding-right:240px;} +.append-7 {padding-right:280px;} +.append-8 {padding-right:320px;} +.append-9 {padding-right:360px;} +.append-10 {padding-right:400px;} +.append-11 {padding-right:440px;} +.append-12 {padding-right:480px;} +.append-13 {padding-right:520px;} +.append-14 {padding-right:560px;} +.append-15 {padding-right:600px;} +.append-16 {padding-right:640px;} +.append-17 {padding-right:680px;} +.append-18 {padding-right:720px;} +.append-19 {padding-right:760px;} +.append-20 {padding-right:800px;} +.append-21 {padding-right:840px;} +.append-22 {padding-right:880px;} +.append-23 {padding-right:920px;} +.prepend-1 {padding-left:40px;} +.prepend-2 {padding-left:80px;} +.prepend-3 {padding-left:120px;} +.prepend-4 {padding-left:160px;} +.prepend-5 {padding-left:200px;} +.prepend-6 {padding-left:240px;} +.prepend-7 {padding-left:280px;} +.prepend-8 {padding-left:320px;} +.prepend-9 {padding-left:360px;} +.prepend-10 {padding-left:400px;} +.prepend-11 {padding-left:440px;} +.prepend-12 {padding-left:480px;} +.prepend-13 {padding-left:520px;} +.prepend-14 {padding-left:560px;} +.prepend-15 {padding-left:600px;} +.prepend-16 {padding-left:640px;} +.prepend-17 {padding-left:680px;} +.prepend-18 {padding-left:720px;} +.prepend-19 {padding-left:760px;} +.prepend-20 {padding-left:800px;} +.prepend-21 {padding-left:840px;} +.prepend-22 {padding-left:880px;} +.prepend-23 {padding-left:920px;} +div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;} +div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;} +.pull-1 {margin-left:-40px;} +.pull-2 {margin-left:-80px;} +.pull-3 {margin-left:-120px;} +.pull-4 {margin-left:-160px;} +.pull-5 {margin-left:-200px;} +.pull-6 {margin-left:-240px;} +.pull-7 {margin-left:-280px;} +.pull-8 {margin-left:-320px;} +.pull-9 {margin-left:-360px;} +.pull-10 {margin-left:-400px;} +.pull-11 {margin-left:-440px;} +.pull-12 {margin-left:-480px;} +.pull-13 {margin-left:-520px;} +.pull-14 {margin-left:-560px;} +.pull-15 {margin-left:-600px;} +.pull-16 {margin-left:-640px;} +.pull-17 {margin-left:-680px;} +.pull-18 {margin-left:-720px;} +.pull-19 {margin-left:-760px;} +.pull-20 {margin-left:-800px;} +.pull-21 {margin-left:-840px;} +.pull-22 {margin-left:-880px;} +.pull-23 {margin-left:-920px;} +.pull-24 {margin-left:-960px;} +.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;} +.push-1 {margin:0 -40px 1.5em 40px;} +.push-2 {margin:0 -80px 1.5em 80px;} +.push-3 {margin:0 -120px 1.5em 120px;} +.push-4 {margin:0 -160px 1.5em 160px;} +.push-5 {margin:0 -200px 1.5em 200px;} +.push-6 {margin:0 -240px 1.5em 240px;} +.push-7 {margin:0 -280px 1.5em 280px;} +.push-8 {margin:0 -320px 1.5em 320px;} +.push-9 {margin:0 -360px 1.5em 360px;} +.push-10 {margin:0 -400px 1.5em 400px;} +.push-11 {margin:0 -440px 1.5em 440px;} +.push-12 {margin:0 -480px 1.5em 480px;} +.push-13 {margin:0 -520px 1.5em 520px;} +.push-14 {margin:0 -560px 1.5em 560px;} +.push-15 {margin:0 -600px 1.5em 600px;} +.push-16 {margin:0 -640px 1.5em 640px;} +.push-17 {margin:0 -680px 1.5em 680px;} +.push-18 {margin:0 -720px 1.5em 720px;} +.push-19 {margin:0 -760px 1.5em 760px;} +.push-20 {margin:0 -800px 1.5em 800px;} +.push-21 {margin:0 -840px 1.5em 840px;} +.push-22 {margin:0 -880px 1.5em 880px;} +.push-23 {margin:0 -920px 1.5em 920px;} +.push-24 {margin:0 -960px 1.5em 960px;} +.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;} +.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} +hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} +hr.space {background:#fff;color:#fff;} +.clearfix:after, .container:after {content:".";display:block;height:0;clear:both;visibility:hidden;} +.clearfix, .container {display:inline-block;} +* html .clearfix, * html .container {height:1%;} +.clearfix, .container {display:block;} +.clear {clear:both;} + +/* forms.css */ +label {font-weight:bold;} +fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} +legend {font-weight:bold;font-size:1.2em;} +input.text, input.title, textarea, select {margin:0.5em 0;border:1px solid #bbb;} +input.text:focus, input.title:focus, textarea:focus, select:focus {border:1px solid #666;} +input.text, input.title {width:300px;padding:5px;} +input.title {font-size:1.5em;} +textarea {width:390px;height:250px;padding:5px;} +.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} +.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} +.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} +.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} +.error a {color:#8a1f11;} +.notice a {color:#514721;} +.success a {color:#264409;}
\ No newline at end of file diff --git a/build/pgo/blueprint/test-small.jpg b/build/pgo/blueprint/test-small.jpg Binary files differnew file mode 100644 index 0000000000..aa599d99a9 --- /dev/null +++ b/build/pgo/blueprint/test-small.jpg diff --git a/build/pgo/blueprint/test.jpg b/build/pgo/blueprint/test.jpg Binary files differnew file mode 100644 index 0000000000..0107be2734 --- /dev/null +++ b/build/pgo/blueprint/test.jpg diff --git a/build/pgo/certs/README b/build/pgo/certs/README new file mode 100644 index 0000000000..7036e4a87e --- /dev/null +++ b/build/pgo/certs/README @@ -0,0 +1,5 @@ +This directory contains CA and server certificates for testing. + +You can find instructions on how to add or modify certificates at: + +https://firefox-source-docs.mozilla.org/build/buildsystem/test_certificates.html diff --git a/build/pgo/certs/alternateroot.ca b/build/pgo/certs/alternateroot.ca new file mode 100644 index 0000000000..9fa2078b4c --- /dev/null +++ b/build/pgo/certs/alternateroot.ca @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+zCCAeOgAwIBAgIUb/+pohOlRCuQgMy2GJLCUQq+HeMwDQYJKoZIhvcNAQEL +BQAwJjEkMCIGA1UEAwwbQWx0ZXJuYXRlIFRydXN0ZWQgQXV0aG9yaXR5MCIYDzIw +MTAwMTAxMDAwMDAwWhgPMjA1MDAxMDEwMDAwMDBaMCYxJDAiBgNVBAMMG0FsdGVy +bmF0ZSBUcnVzdGVkIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMF1xlJmCZ93CCpnkfG4dsN/XOU4sGxKzSKxy9RvplraKt1ByMJJisSj +s8H2FIf0G2mJQb2ApRw8EgJExYSkxEgzBeUTjAEGzwi+moYnYLrmoujzbyPF2YMT +ud+vN4NF2s5R1Nbc0qbLPMcG680wcOyYzOQKpZHXKVp/ccW+ZmkdKy3+yElEWQvF +o+pJ/ZOx11NAXxdzdpmVhmYlR5ftQmkIiAgRQiBpmIpD/uSM5oeB3SK2ppzSg3UT +H5MrEozihvp9JRwGKtJ+8Bbxh83VToMrNbiTD3S6kKqLx2FnJCqx/W1iFA0YxMC4 +xo/DdIRXMkrX3obmVS8dHhkdcSFo07sCAwEAAaMdMBswCwYDVR0PBAQDAgEGMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAS+qy/sIFV+oia7zsyFhe3X +j3ZHSvmqJ4mxIg5KOPVP2NvDaxD/+pysxGLf69QDRjIsePBdRJz0zZoVl9pSXIn1 +Kpk0sjzKX2bJtAomog+ZnAZUxtLzoXy/aqaheWm8cRJ8qFOJtSMDRrLISqBXCQLO +ECqXIxf3Nt3S+Riu2Pam3YymFdtmqUJvLhhekWtEEnXyh/xfAsoUgS3SQ27c4dCY +R7XGnFsaXrKXv93QeJmtfvrAZMXEuKaBGPSNHV6QH0S0Loh9Jed2Zp7GxnFtIPYe +J2Q5qtxa8KD/tgGFpAD74eMBdgQ4SxbA/YqqXIt1lLNcr7wm0cPRpP0vIY3hk8k= +-----END CERTIFICATE----- diff --git a/build/pgo/certs/alternateroot.ca.keyspec b/build/pgo/certs/alternateroot.ca.keyspec new file mode 100644 index 0000000000..cbd5f309c0 --- /dev/null +++ b/build/pgo/certs/alternateroot.ca.keyspec @@ -0,0 +1 @@ +alternate diff --git a/build/pgo/certs/alternateroot.certspec b/build/pgo/certs/alternateroot.certspec new file mode 100644 index 0000000000..d831222020 --- /dev/null +++ b/build/pgo/certs/alternateroot.certspec @@ -0,0 +1,7 @@ +issuer:Alternate Trusted Authority
+subject:Alternate Trusted Authority
+validity:20100101-20500101
+extension:keyUsage:keyCertSign,cRLSign
+extension:basicConstraints:cA,
+issuerKey:alternate
+subjectKey:alternate
diff --git a/build/pgo/certs/badCertDomain.certspec b/build/pgo/certs/badCertDomain.certspec new file mode 100644 index 0000000000..5d13ffae3b --- /dev/null +++ b/build/pgo/certs/badCertDomain.certspec @@ -0,0 +1,3 @@ +subject:www.badcertdomain.example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:www.badcertdomain.example.com diff --git a/build/pgo/certs/bug1665057cert.certspec b/build/pgo/certs/bug1665057cert.certspec new file mode 100644 index 0000000000..ee338b8d1a --- /dev/null +++ b/build/pgo/certs/bug1665057cert.certspec @@ -0,0 +1,3 @@ +subject:www.suggestion-example.com +extension:subjectAlternativeName:www.suggestion-example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization diff --git a/build/pgo/certs/bug1706126cert.certspec b/build/pgo/certs/bug1706126cert.certspec new file mode 100644 index 0000000000..5fd2d894ff --- /dev/null +++ b/build/pgo/certs/bug1706126cert.certspec @@ -0,0 +1,3 @@ +subject:www.redirect-example.com +extension:subjectAlternativeName:www.redirect-example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization diff --git a/build/pgo/certs/bug413909cert.certspec b/build/pgo/certs/bug413909cert.certspec new file mode 100644 index 0000000000..ed4100219a --- /dev/null +++ b/build/pgo/certs/bug413909cert.certspec @@ -0,0 +1,3 @@ +subject:bug413909.xn--hxajbheg2az3al.xn--jxalpdlp +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:bug413909.xn--hxajbheg2az3al.xn--jxalpdlp diff --git a/build/pgo/certs/cert9.db b/build/pgo/certs/cert9.db Binary files differnew file mode 100644 index 0000000000..92235bfa31 --- /dev/null +++ b/build/pgo/certs/cert9.db diff --git a/build/pgo/certs/dynamicPinningBad.certspec b/build/pgo/certs/dynamicPinningBad.certspec new file mode 100644 index 0000000000..1d377103d2 --- /dev/null +++ b/build/pgo/certs/dynamicPinningBad.certspec @@ -0,0 +1,5 @@ +subject:bad.include-subdomains.pinning-dynamic.example.com +issuer:Alternate Trusted Authority +extension:subjectAlternativeName:bad.include-subdomains.pinning-dynamic.example.com +subjectKey:alternate +issuerKey:alternate diff --git a/build/pgo/certs/dynamicPinningBad.server.keyspec b/build/pgo/certs/dynamicPinningBad.server.keyspec new file mode 100644 index 0000000000..cbd5f309c0 --- /dev/null +++ b/build/pgo/certs/dynamicPinningBad.server.keyspec @@ -0,0 +1 @@ +alternate diff --git a/build/pgo/certs/dynamicPinningGood.certspec b/build/pgo/certs/dynamicPinningGood.certspec new file mode 100644 index 0000000000..2db3836919 --- /dev/null +++ b/build/pgo/certs/dynamicPinningGood.certspec @@ -0,0 +1,3 @@ +subject:dynamic-pinning.example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:*.include-subdomains.pinning-dynamic.example.com,*.pinning-dynamic.example.com diff --git a/build/pgo/certs/escapeattack1.certspec b/build/pgo/certs/escapeattack1.certspec new file mode 100644 index 0000000000..df34d5920c --- /dev/null +++ b/build/pgo/certs/escapeattack1.certspec @@ -0,0 +1,3 @@ +subject:www.bank1.com\00www.bad-guy.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:www.bank1.com\00www.bad-guy.com diff --git a/build/pgo/certs/evintermediate.ca b/build/pgo/certs/evintermediate.ca new file mode 100644 index 0000000000..84a6d8e802 --- /dev/null +++ b/build/pgo/certs/evintermediate.ca @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEfDCCA2SgAwIBAgIUETbLA86peOWkUFhyKYIuZVGUEygwDQYJKoZIhvcNAQEL +BQAwgdwxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRh +aW4gVmlldzEjMCEGA1UEChMaTW96aWxsYSAtIEVWIGRlYnVnIHRlc3QgQ0ExHTAb +BgNVBAsTFFNlY3VyaXR5IEVuZ2luZWVyaW5nMTYwNAYDVQQDEy1FViBUZXN0aW5n +ICh1bnRydXN0d29ydGh5KSBDQS9uYW1lPWV2LXRlc3QtY2ExLDAqBgkqhkiG9w0B +CQEWHWNoYXJsYXRhbkB0ZXN0aW5nLmV4YW1wbGUuY29tMCIYDzIwMTAwMTAxMDAw +MDAwWhgPMjA1MDAxMDEwMDAwMDBaMIHcMQswCQYDVQQGEwJVUzELMAkGA1UECBMC +Q0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxIzAhBgNVBAoTGk1vemlsbGEgLSBF +ViBkZWJ1ZyB0ZXN0IENBMR0wGwYDVQQLExRTZWN1cml0eSBFbmdpbmVlcmluZzE2 +MDQGA1UEAxMtRVYgVGVzdGluZyAodW50cnVzdHdvcnRoeSkgQ0EvbmFtZT1ldi10 +ZXN0LWNhMSwwKgYJKoZIhvcNAQkBFh1jaGFybGF0YW5AdGVzdGluZy5leGFtcGxl +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALVJiVydABCNEaH5 +n4ep49Gl21367PGI2le/ZBNojyzkciz/EJA4wXQCyToqRz29KGrtP9zTY89aKRR3 +Ab3YGNdhW/k1a9XTyDNqqowJcTaKBsPNRGG5PlFCThdEuy6q1GqrOM4ZaCGWH4dx +ShZjaT8JdhzfTWuhJerOx74nDTiPeJ9s33iuMUTtKMReeSk4Y6eiKkiYCjakDnLV +ecm5Jd/4x5M2L/1ol6fBdUxel8lnw+rdGq6KoszONIoBabgOKKLXDBqWDG8zXy2g +m5tkP1q/uknoqqmB6WDifYdIC91V3ZQX+hhQn7tVTM+BpDl+i6gSijS98nhlwYnl +c0+yKQUCAwEAAaMwMC4wCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wEQYDVR0g +BAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBCwUAA4IBAQArG5slgBRJuytlKFa4qcHW +pAOfjN9fwi57fDds1yNv6tXhESdkbVPhIgw+GanVbrVcorGdCkfB51+dPJM+cBgH +HSwEB7TQnNYvm/csA1zH4n+CnX9nBL7dwK63n6dyR9f1uvu6KSB+YJm3amKil85a +d7HeDWdh+gNhC58lEC2QzuOMivP593aS5vLJHfp8pjc21XJkO8M7SRw44OJKYq9/ +v0k6v4SznbfZzSLg3gM4aSNuCLExUtUY2myxPFwJs9QQ4xx5zJTjJTRlpxUm630Z +n4IYlseao949U+UbBNU4PZKH7dzSQzfhdFJpvK3dsPOPNnHYiXO0xAhsEvvjq8zQ +-----END CERTIFICATE----- diff --git a/build/pgo/certs/evintermediate.ca.keyspec b/build/pgo/certs/evintermediate.ca.keyspec new file mode 100644 index 0000000000..1a3d76a550 --- /dev/null +++ b/build/pgo/certs/evintermediate.ca.keyspec @@ -0,0 +1 @@ +ev diff --git a/build/pgo/certs/evintermediate.certspec b/build/pgo/certs/evintermediate.certspec new file mode 100644 index 0000000000..a04850d53f --- /dev/null +++ b/build/pgo/certs/evintermediate.certspec @@ -0,0 +1,7 @@ +issuer:printableString/C=US/ST=CA/L=Mountain View/O=Mozilla - EV debug test CA/OU=Security Engineering/CN=EV Testing (untrustworthy) CA/name=ev-test-ca/emailAddress=charlatan@testing.example.com
+subject:printableString/C=US/ST=CA/L=Mountain View/O=Mozilla - EV debug test CA/OU=Security Engineering/CN=EV Testing (untrustworthy) CA/name=ev-test-ca/emailAddress=charlatan@testing.example.com
+subjectKey:ev
+validity:20100101-20500101
+extension:keyUsage:keyCertSign,cRLSign
+extension:basicConstraints:cA,
+extension:certificatePolicies:any
diff --git a/build/pgo/certs/expired.certspec b/build/pgo/certs/expired.certspec new file mode 100644 index 0000000000..3193168130 --- /dev/null +++ b/build/pgo/certs/expired.certspec @@ -0,0 +1,4 @@ +subject:expired.example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:expired.example.com +validity:20100105-20100106 diff --git a/build/pgo/certs/http2-cert.ca b/build/pgo/certs/http2-cert.ca new file mode 100644 index 0000000000..a6bd5d72e9 --- /dev/null +++ b/build/pgo/certs/http2-cert.ca @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKDCCAhCgAwIBAgIUZwyOUcu/hcoxGM+/mv6i/ZNoK8cwDQYJKoZIhvcNAQEL +BQAwGTEXMBUGA1UEAwwOIEhUVFAyIFRlc3QgQ0EwIhgPMjAxNzAxMDEwMDAwMDBa +GA8yMDI3MDEwMTAwMDAwMFowGzEZMBcGA1UEAwwQIEhUVFAyIFRlc3QgQ2VydDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9 +PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3 +HNUknAJ+zUP8HmnQOCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3Dg +Dw2N/WYLK7AkkqR9uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7 +EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SK +lWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0C +AwEAAaNiMGAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwSQYDVR0RBEIwQIIJbG9jYWxo +b3N0gg9mb28uZXhhbXBsZS5jb22CEGFsdDEuZXhhbXBsZS5jb22CEGFsdDIuZXhh +bXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAEPAH1dHcA0wyt6et0AjiRIBKla0 +EaW/9hFQW8xphNsgZTw2tX6vUqjd2qz4kzKTSbW8AmB26VEfSDkwUxbFrbCP8Pri +FqVYwnWVLsBrr9PF0xg9SuRJnyHAwBv0xNXB3KRY2HtFcUaLn1C8alh2LAhX6eX+ ++ozHvspMjMq7P1lsONGbtfmJaf6pNh7zzok4fOas+eoqhf64TUb4g4JNxfLyXh3P +DcLsP67kr6fZSlGjzhto9ILVhg9rflNmSkmrhVjCxNqDuLFyn5ljvhemw7X3/V8A +iCwqEP2/vOjnE1wCxF2Xdb6+3f/KJKqNwOmjraXZGupOUR6OA/+Z3V3RbGc= +-----END CERTIFICATE----- diff --git a/build/pgo/certs/http2-cert.ca.keyspec b/build/pgo/certs/http2-cert.ca.keyspec new file mode 100644 index 0000000000..4ad96d5159 --- /dev/null +++ b/build/pgo/certs/http2-cert.ca.keyspec @@ -0,0 +1 @@ +default diff --git a/build/pgo/certs/http2-cert.certspec b/build/pgo/certs/http2-cert.certspec new file mode 100644 index 0000000000..1277e6d444 --- /dev/null +++ b/build/pgo/certs/http2-cert.certspec @@ -0,0 +1,5 @@ +issuer: HTTP2 Test CA +subject: HTTP2 Test Cert +validity:20170101-20270101 +extension:extKeyUsage:serverAuth +extension:subjectAlternativeName:localhost,foo.example.com,alt1.example.com,alt2.example.com diff --git a/build/pgo/certs/imminently_distrusted.certspec b/build/pgo/certs/imminently_distrusted.certspec new file mode 100644 index 0000000000..e44e4e8e07 --- /dev/null +++ b/build/pgo/certs/imminently_distrusted.certspec @@ -0,0 +1,4 @@ +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +subject:printableString/CN=Imminently Distrusted End Entity +validity:20100101-20500101 +extension:subjectAlternativeName:imminently-distrusted.example.com diff --git a/build/pgo/certs/key4.db b/build/pgo/certs/key4.db Binary files differnew file mode 100644 index 0000000000..8700456238 --- /dev/null +++ b/build/pgo/certs/key4.db diff --git a/build/pgo/certs/mochitest-cert.ca b/build/pgo/certs/mochitest-cert.ca new file mode 100644 index 0000000000..fd968257a1 --- /dev/null +++ b/build/pgo/certs/mochitest-cert.ca @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID1TCCAr2gAwIBAgIUMxWonuaoi1gBujMOrB4Ap5YkGu0wDQYJKoZIhvcNAQEL +BQAwHTEbMBkGA1UEAwwSIE1vY2hpdGVzdCBUZXN0IENBMCIYDzIwMjIwMTAxMDAw +MDAwWhgPMjAzMjAxMDEwMDAwMDBaMB8xHTAbBgNVBAMMFCBNb2NoaXRlc3QgVGVz +dCBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohRqESOFtZB +/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+KvWnVramRx +CHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+rWkasdMC +OosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPvJxbYVbdm +Wqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5Fw6naOGz +ey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6clHEMdUD +rNoYCjXtjQIDAQABo4IBBTCCAQEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwgekGA1Ud +EQSB4TCB3oIKbW9jaGkudGVzdIILZXhhbXBsZS5jb22CDSouZXhhbXBsZS5jb22C +C2V4YW1wbGUubmV0gg0qLmV4YW1wbGUubmV0ggtleGFtcGxlLm9yZ4INKi5leGFt +cGxlLm9yZ4IPKi5pdGlzYXRyYXAub3Jngg4qLnhuLS1qeGFscGRscIIQaXRpc2F0 +cmFja2VyLm9yZ4IMdzNjLXRlc3Qub3Jngg4qLnczYy10ZXN0Lm9yZ4IVbW9jaGl0 +ZXN0LnlvdXR1YmUuY29tgglsb2NhbGhvc3SCCTEyNy4wLjAuMjANBgkqhkiG9w0B +AQsFAAOCAQEAlqXzcG/TvKitOZh3SrY+AQH3sbop8gQ5NnzEVTXt4N8LI7Kbb8h1 +2aZjwvnCp0yCdk0dRekZq8f6xq5bd6/k0C4Wkr9ivCdhxc4nvuZa62S2X53JObm2 +egUReeNSqjYyxfO6k1L36+iSLU2iYpYxgPCae0h5c2Fg9UtIbsmjLVqkdGYBnH1B +HAuVGJkWoKDt9QlG2uROdhFqcz6pSXlTifev6hQ2Ffl7HirIqyqwtB+JygMSat52 +ROfvcFTHXGx0K1OmfjUid9yA2mGUOY/NO2HQhYzm9a4zS10Bw+f19SgVjDOx9pK+ +cl8wZKk5SlwmMi346ctGcPNLVBxDcAps4Q== +-----END CERTIFICATE----- diff --git a/build/pgo/certs/mochitest-cert.ca.keyspec b/build/pgo/certs/mochitest-cert.ca.keyspec new file mode 100644 index 0000000000..4ad96d5159 --- /dev/null +++ b/build/pgo/certs/mochitest-cert.ca.keyspec @@ -0,0 +1 @@ +default diff --git a/build/pgo/certs/mochitest-cert.certspec b/build/pgo/certs/mochitest-cert.certspec new file mode 100644 index 0000000000..89698c9dc1 --- /dev/null +++ b/build/pgo/certs/mochitest-cert.certspec @@ -0,0 +1,5 @@ +issuer: Mochitest Test CA +subject: Mochitest Test Cert +validity:20220101-20320101 +extension:extKeyUsage:serverAuth +extension:subjectAlternativeName:mochi.test,example.com,*.example.com,example.net,*.example.net,example.org,*.example.org,*.itisatrap.org,*.xn--jxalpdlp,itisatracker.org,w3c-test.org,*.w3c-test.org,mochitest.youtube.com,localhost,127.0.0.2 diff --git a/build/pgo/certs/mochitest.certspec b/build/pgo/certs/mochitest.certspec new file mode 100644 index 0000000000..31f926290e --- /dev/null +++ b/build/pgo/certs/mochitest.certspec @@ -0,0 +1,3 @@ +subject:Mochitest client +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +serialNumber:3 diff --git a/build/pgo/certs/mochitest.client b/build/pgo/certs/mochitest.client Binary files differnew file mode 100644 index 0000000000..d19a92306d --- /dev/null +++ b/build/pgo/certs/mochitest.client diff --git a/build/pgo/certs/mochitest.client.keyspec b/build/pgo/certs/mochitest.client.keyspec new file mode 100644 index 0000000000..4ad96d5159 --- /dev/null +++ b/build/pgo/certs/mochitest.client.keyspec @@ -0,0 +1 @@ +default diff --git a/build/pgo/certs/noSubjectAltName.certspec b/build/pgo/certs/noSubjectAltName.certspec new file mode 100644 index 0000000000..dcbda9ee6e --- /dev/null +++ b/build/pgo/certs/noSubjectAltName.certspec @@ -0,0 +1,2 @@ +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +subject:certificate without subjectAlternativeNames diff --git a/build/pgo/certs/pgoca.ca b/build/pgo/certs/pgoca.ca new file mode 100644 index 0000000000..31cf9c33a0 --- /dev/null +++ b/build/pgo/certs/pgoca.ca @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDgzCCAmugAwIBAgIUQx5pxD+JMg1qPztfSg1Ucw8xsz0wDQYJKoZIhvcNAQEL +BQAwajEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTEY +MBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSQwIgYDVQQLExtQcm9maWxlIEd1aWRl +ZCBPcHRpbWl6YXRpb24wIhgPMjAxMDAxMDEwMDAwMDBaGA8yMDUwMDEwMTAwMDAw +MFowajEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTEY +MBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSQwIgYDVQQLExtQcm9maWxlIEd1aWRl +ZCBPcHRpbWl6YXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6 +iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9sZwGm24ahvJr +4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5TMJrbA7tFYIP +8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7xeC4SB+oN9OI +Q+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHdtMr3/K0dJdMJ +77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l8Y+ZFzG4s/5J +I/pyUcQx1QOs2hgKNe2NAgMBAAGjHTAbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAYFnzom5ROuxDR3WFQatxHs5ekni4uUbEx +6pN8fOzcsllEfCwvmMLVCh36ffSguf/UlmR5Hq1s/S7iMiic5mnK4aaVwixzS4Z3 +ug7Dc+fG7j0VOcBTKWU983xUK/1F409ghQ5KlO38KA7hyx1kzjYjzvxLaweDXRqr +J/RZ1ACP2fKNziEOCbXzzzEx39oc17NBV+LotPFzKZ+pcxMDrtiNts4hwCw/UUw7 +Gp0tKte2CevGJbzjPHP3/6FUzHfOatZSpxEmvAcSTDp5sjdVuOStx4v6jVrwvyAz +VQzDPzaRWh3NtY5JNasrhExr5qxQlygfBngCMgZ9gESG9FvLG+sx +-----END CERTIFICATE----- diff --git a/build/pgo/certs/pgoca.ca.keyspec b/build/pgo/certs/pgoca.ca.keyspec new file mode 100644 index 0000000000..4ad96d5159 --- /dev/null +++ b/build/pgo/certs/pgoca.ca.keyspec @@ -0,0 +1 @@ +default diff --git a/build/pgo/certs/pgoca.certspec b/build/pgo/certs/pgoca.certspec new file mode 100644 index 0000000000..058e5b55a5 --- /dev/null +++ b/build/pgo/certs/pgoca.certspec @@ -0,0 +1,5 @@ +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +subject:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +validity:20100101-20500101 +extension:keyUsage:keyCertSign,cRLSign +extension:basicConstraints:cA, diff --git a/build/pgo/certs/pkcs11.txt b/build/pgo/certs/pkcs11.txt new file mode 100644 index 0000000000..65aead2930 --- /dev/null +++ b/build/pgo/certs/pkcs11.txt @@ -0,0 +1,5 @@ +library= +name=NSS Internal PKCS #11 Module +parameters=configdir='/Users/mozilla/mozilla-unified/build/pgo/certs' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) + diff --git a/build/pgo/certs/selfsigned.certspec b/build/pgo/certs/selfsigned.certspec new file mode 100644 index 0000000000..be255b497a --- /dev/null +++ b/build/pgo/certs/selfsigned.certspec @@ -0,0 +1,3 @@ +issuer:self-signed.example.com +subject:self-signed.example.com +extension:subjectAlternativeName:self-signed.example.com diff --git a/build/pgo/certs/sha1_end_entity.certspec b/build/pgo/certs/sha1_end_entity.certspec new file mode 100644 index 0000000000..eced653a9a --- /dev/null +++ b/build/pgo/certs/sha1_end_entity.certspec @@ -0,0 +1,4 @@ +subject:sha1ee.example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:sha1ee.example.com +signature:sha1WithRSAEncryption diff --git a/build/pgo/certs/sha256_end_entity.certspec b/build/pgo/certs/sha256_end_entity.certspec new file mode 100644 index 0000000000..c3cb5fda2a --- /dev/null +++ b/build/pgo/certs/sha256_end_entity.certspec @@ -0,0 +1,4 @@ +subject:sha256ee.example.com +issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization +extension:subjectAlternativeName:sha256ee.example.com +signature:sha256WithRSAEncryption diff --git a/build/pgo/certs/staticPinningBad.certspec b/build/pgo/certs/staticPinningBad.certspec new file mode 100644 index 0000000000..7589ff6fc3 --- /dev/null +++ b/build/pgo/certs/staticPinningBad.certspec @@ -0,0 +1,5 @@ +subject:include-subdomains.pinning.example.com +issuer:Alternate Trusted Authority +extension:subjectAlternativeName:include-subdomains.pinning.example.com +subjectKey:alternate +issuerKey:alternate diff --git a/build/pgo/certs/staticPinningBad.server.keyspec b/build/pgo/certs/staticPinningBad.server.keyspec new file mode 100644 index 0000000000..cbd5f309c0 --- /dev/null +++ b/build/pgo/certs/staticPinningBad.server.keyspec @@ -0,0 +1 @@ +alternate diff --git a/build/pgo/certs/unknown_ca.certspec b/build/pgo/certs/unknown_ca.certspec new file mode 100644 index 0000000000..40e1bedc70 --- /dev/null +++ b/build/pgo/certs/unknown_ca.certspec @@ -0,0 +1,5 @@ +issuer:Unknown CA +subject:Unknown CA +validity:20100101-20500101 +extension:keyUsage:keyCertSign,cRLSign +extension:basicConstraints:cA, diff --git a/build/pgo/certs/untrusted.certspec b/build/pgo/certs/untrusted.certspec new file mode 100644 index 0000000000..445d3451b0 --- /dev/null +++ b/build/pgo/certs/untrusted.certspec @@ -0,0 +1,3 @@ +subject:untrusted.example.com +issuer:Unknown CA +extension:subjectAlternativeName:untrusted.example.com diff --git a/build/pgo/certs/untrustedandexpired.certspec b/build/pgo/certs/untrustedandexpired.certspec new file mode 100644 index 0000000000..bed16c7694 --- /dev/null +++ b/build/pgo/certs/untrustedandexpired.certspec @@ -0,0 +1,4 @@ +subject:untrusted-expired.example.com +issuer:Unknown CA +extension:subjectAlternativeName:untrusted-expired.example.com +validity:20121012-20121012 diff --git a/build/pgo/favicon.ico b/build/pgo/favicon.ico Binary files differnew file mode 100644 index 0000000000..d44438903b --- /dev/null +++ b/build/pgo/favicon.ico diff --git a/build/pgo/genpgocert.py b/build/pgo/genpgocert.py new file mode 100644 index 0000000000..8edaa47ba9 --- /dev/null +++ b/build/pgo/genpgocert.py @@ -0,0 +1,251 @@ +#!/usr/bin/env 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/. + +# This script exists to generate the Certificate Authority and server +# certificates used for SSL testing in Mochitest. The already generated +# certs are located at $topsrcdir/build/pgo/certs/ . + +import os +import random +import re +import shutil +import subprocess +import sys + +import mozinfo +from mozbuild.base import BinaryNotFoundException, MozbuildObject +from mozfile import NamedTemporaryFile, TemporaryDirectory +from mozprofile.permissions import ServerLocations + +dbFiles = [ + re.compile("^cert[0-9]+\.db$"), + re.compile("^key[0-9]+\.db$"), + re.compile("^secmod\.db$"), +] + + +def unlinkDbFiles(path): + for root, dirs, files in os.walk(path): + for name in files: + for dbFile in dbFiles: + if dbFile.match(name) and os.path.exists(os.path.join(root, name)): + os.unlink(os.path.join(root, name)) + + +def dbFilesExist(path): + for root, dirs, files in os.walk(path): + for name in files: + for dbFile in dbFiles: + if dbFile.match(name) and os.path.exists(os.path.join(root, name)): + return True + return False + + +def runUtil(util, args, inputdata=None, outputstream=None): + env = os.environ.copy() + if mozinfo.os == "linux": + pathvar = "LD_LIBRARY_PATH" + app_path = os.path.dirname(util) + if pathvar in env: + env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar]) + else: + env[pathvar] = app_path + proc = subprocess.Popen( + [util] + args, + env=env, + stdin=subprocess.PIPE if inputdata else None, + stdout=outputstream, + universal_newlines=True, + ) + proc.communicate(inputdata) + return proc.returncode + + +def createRandomFile(randomFile): + for count in xrange(0, 2048): + randomFile.write(chr(random.randint(0, 255))) + + +def writeCertspecForServerLocations(fd): + locations = ServerLocations( + os.path.join(build.topsrcdir, "build", "pgo", "server-locations.txt") + ) + SAN = [] + for loc in [ + i for i in iter(locations) if i.scheme == "https" and "nocert" not in i.options + ]: + customCertOption = False + customCertRE = re.compile("^cert=(?:\w+)") + for _ in [i for i in loc.options if customCertRE.match(i)]: + customCertOption = True + break + + if "ipV4Address" in loc.options: + loc.host = "ip4:" + loc.host + + if not customCertOption: + SAN.append(loc.host) + + fd.write( + "issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization\n" # NOQA: E501 + ) + fd.write("subject:{}\n".format(SAN[0])) + fd.write("extension:subjectAlternativeName:{}\n".format(",".join(SAN))) + + +def constructCertDatabase(build, srcDir): + try: + certutil = build.get_binary_path(what="certutil") + pk12util = build.get_binary_path(what="pk12util") + except BinaryNotFoundException as e: + print("{}\n\n{}\n".format(e, e.help())) + return 1 + openssl = shutil.which("openssl") + pycert = os.path.join(build.topsrcdir, "security", "manager", "tools", "pycert.py") + pykey = os.path.join(build.topsrcdir, "security", "manager", "tools", "pykey.py") + + with NamedTemporaryFile(mode="wt+") as pwfile, TemporaryDirectory() as pemfolder: + pwfile.write("\n") + pwfile.flush() + + if dbFilesExist(srcDir): + # Make sure all DB files from src are really deleted + unlinkDbFiles(srcDir) + + # Copy all .certspec and .keyspec files to a temporary directory + for root, dirs, files in os.walk(srcDir): + for spec in [ + i for i in files if i.endswith(".certspec") or i.endswith(".keyspec") + ]: + shutil.copyfile(os.path.join(root, spec), os.path.join(pemfolder, spec)) + + # Write a certspec for the "server-locations.txt" file to that temporary directory + pgoserver_certspec = os.path.join(pemfolder, "pgoserver.certspec") + if os.path.exists(pgoserver_certspec): + raise Exception( + "{} already exists, which isn't allowed".format(pgoserver_certspec) + ) + with open(pgoserver_certspec, "w") as fd: + writeCertspecForServerLocations(fd) + + # Generate certs for all certspecs + for root, dirs, files in os.walk(pemfolder): + for certspec in [i for i in files if i.endswith(".certspec")]: + name = certspec.split(".certspec")[0] + pem = os.path.join(pemfolder, "{}.cert.pem".format(name)) + + print("Generating public certificate {} (pem={})".format(name, pem)) + + with open(os.path.join(root, certspec), "r") as certspec_file: + certspec_data = certspec_file.read() + with open(pem, "w") as pem_file: + status = runUtil( + pycert, [], inputdata=certspec_data, outputstream=pem_file + ) + if status: + return status + + status = runUtil( + certutil, + [ + "-A", + "-n", + name, + "-t", + "P,,", + "-i", + pem, + "-d", + srcDir, + "-f", + pwfile.name, + ], + ) + if status: + return status + + for keyspec in [i for i in files if i.endswith(".keyspec")]: + parts = keyspec.split(".") + name = parts[0] + key_type = parts[1] + if key_type not in ["ca", "client", "server"]: + raise Exception( + "{}: keyspec filenames must be of the form XXX.client.keyspec " + "or XXX.ca.keyspec (key_type={})".format(keyspec, key_type) + ) + key_pem = os.path.join(pemfolder, "{}.key.pem".format(name)) + + print("Generating private key {} (pem={})".format(name, key_pem)) + + with open(os.path.join(root, keyspec), "r") as keyspec_file: + keyspec_data = keyspec_file.read() + with open(key_pem, "w") as pem_file: + status = runUtil( + pykey, [], inputdata=keyspec_data, outputstream=pem_file + ) + if status: + return status + + cert_pem = os.path.join(pemfolder, "{}.cert.pem".format(name)) + if not os.path.exists(cert_pem): + raise Exception( + "There has to be a corresponding certificate named {} for " + "the keyspec {}".format(cert_pem, keyspec) + ) + + p12 = os.path.join(pemfolder, "{}.key.p12".format(name)) + print( + "Converting private key {} to PKCS12 (p12={})".format(key_pem, p12) + ) + status = runUtil( + openssl, + [ + "pkcs12", + "-export", + "-inkey", + key_pem, + "-in", + cert_pem, + "-name", + name, + "-out", + p12, + "-passout", + "file:" + pwfile.name, + ], + ) + if status: + return status + + print("Importing private key {} to database".format(key_pem)) + status = runUtil( + pk12util, + ["-i", p12, "-d", srcDir, "-w", pwfile.name, "-k", pwfile.name], + ) + if status: + return status + + if key_type == "ca": + shutil.copyfile( + cert_pem, os.path.join(srcDir, "{}.ca".format(name)) + ) + elif key_type == "client": + shutil.copyfile(p12, os.path.join(srcDir, "{}.client".format(name))) + elif key_type == "server": + pass # Nothing to do for server keys + else: + raise Exception( + "State error: Unknown keyspec key_type: {}".format(key_type) + ) + + return 0 + + +build = MozbuildObject.from_environment() +certdir = os.path.join(build.topsrcdir, "build", "pgo", "certs") +certificateStatus = constructCertDatabase(build, certdir) +if certificateStatus: + print("TEST-UNEXPECTED-FAIL | SSL Server Certificate generation") +sys.exit(certificateStatus) diff --git a/build/pgo/index.html b/build/pgo/index.html new file mode 100644 index 0000000000..866150ccc8 --- /dev/null +++ b/build/pgo/index.html @@ -0,0 +1,111 @@ +<script> + /* 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/. */ + + /* global Quitter */ + + var list = [ + "blueprint/elements.html", + "blueprint/forms.html", + "blueprint/grid.html", + "blueprint/sample.html", + "js-input/3d-thingy.html", + "js-input/crypto-otp.html", + "js-input/sunspider/3d-cube.html", + "js-input/sunspider/3d-morph.html", + "js-input/sunspider/3d-raytrace.html", + "js-input/sunspider/access-binary-trees.html", + "js-input/sunspider/access-fannkuch.html", + "js-input/sunspider/access-nbody.html", + "js-input/sunspider/access-nsieve.html", + "js-input/sunspider/bitops-3bit-bits-in-byte.html", + "js-input/sunspider/bitops-bits-in-byte.html", + "js-input/sunspider/bitops-bitwise-and.html", + "js-input/sunspider/bitops-nsieve-bits.html", + "js-input/sunspider/controlflow-recursive.html", + "js-input/sunspider/crypto-aes.html", + "js-input/sunspider/crypto-md5.html", + "js-input/sunspider/crypto-sha1.html", + "js-input/sunspider/date-format-tofte.html", + "js-input/sunspider/date-format-xparb.html", + "js-input/sunspider/math-cordic.html", + "js-input/sunspider/math-partial-sums.html", + "js-input/sunspider/math-spectral-norm.html", + "js-input/sunspider/regexp-dna.html", + "js-input/sunspider/string-base64.html", + "js-input/sunspider/string-fasta.html", + "js-input/sunspider/string-tagcloud.html", + "js-input/sunspider/string-unpack-code.html", + "js-input/sunspider/string-validate-input.html", + "talos/tests/perf-reftest-singletons/abspos-reflow-1.html", + "talos/tests/perf-reftest-singletons/attr-selector-1.html", + "talos/tests/perf-reftest-singletons/bidi-resolution-1.html", + "talos/tests/perf-reftest-singletons/bloom-basic-2.html", + "talos/tests/perf-reftest-singletons/bloom-basic.html", + "talos/tests/perf-reftest-singletons/coalesce-1.html", + "talos/tests/perf-reftest-singletons/coalesce-2.html", + "talos/tests/perf-reftest-singletons/display-none-1.html", + "talos/tests/perf-reftest-singletons/external-string-pass.html", + "talos/tests/perf-reftest-singletons/getElementById-1.html", + "talos/tests/perf-reftest-singletons/id-getter-1.html", + "talos/tests/perf-reftest-singletons/id-getter-2.html", + "talos/tests/perf-reftest-singletons/id-getter-3.html", + "talos/tests/perf-reftest-singletons/id-getter-4.html", + "talos/tests/perf-reftest-singletons/id-getter-5.html", + "talos/tests/perf-reftest-singletons/id-getter-6.html", + "talos/tests/perf-reftest-singletons/id-getter-7.html", + "talos/tests/perf-reftest-singletons/inline-style-cache-1.html", + "talos/tests/perf-reftest-singletons/line-iterator.html", + "talos/tests/perf-reftest-singletons/link-style-cache-1.html", + "talos/tests/perf-reftest-singletons/nth-index-1.html", + "talos/tests/perf-reftest-singletons/nth-index-2.html", + "talos/tests/perf-reftest-singletons/only-children-1.html", + "talos/tests/perf-reftest-singletons/parent-basic-singleton.html", + "talos/tests/perf-reftest-singletons/scrollbar-styles-1.html", + "talos/tests/perf-reftest-singletons/slow-selector-1.html", + "talos/tests/perf-reftest-singletons/slow-selector-2.html", + "talos/tests/perf-reftest-singletons/style-attr-1.html", + "talos/tests/perf-reftest-singletons/style-sharing-style-attr.html", + "talos/tests/perf-reftest-singletons/style-sharing.html", + "talos/tests/perf-reftest-singletons/svg-text-textLength-1.html", + "talos/tests/perf-reftest-singletons/svg-text-getExtentOfChar-1.html", + "talos/tests/perf-reftest-singletons/tiny-traversal-singleton.html", + "talos/tests/perf-reftest-singletons/window-named-property-get.html", + "webkit/PerformanceTests/Speedometer/index.html", + "http://localhost:8000/index.html?startAutomatically=true", + "webkit/PerformanceTests/webaudio/index.html?raptor&rendering-buffer-length=30", + ]; + var defaultInterval = 2000; + var idx = 0; + var w; + + window.onload = function () { + w = window.open("about:blank"); + window.setTimeout(loadURL, defaultInterval); + }; + function loadURL() { + var interval = defaultInterval; + var testURL = list[idx++]; + if (testURL.includes("webkit") || testURL.includes("localhost")) { + interval = 120000; + } + w.close(); + w = window.open(testURL); + // Prevent the perf-reftest-singletons from calling alert() + w.tpRecordTime = function () {}; + + if (idx < list.length) { + window.setTimeout(loadURL, interval); + } else { + window.setTimeout(Quitter.quit, interval); + } + } + var i; + + for (i = 0; i < list.length; i++) { + // eslint-disable-next-line no-unsanitized/method + document.write(list[i]); + document.write("<br>"); + } +</script> diff --git a/build/pgo/js-input/3d-thingy.html b/build/pgo/js-input/3d-thingy.html new file mode 100644 index 0000000000..9e54299df4 --- /dev/null +++ b/build/pgo/js-input/3d-thingy.html @@ -0,0 +1,390 @@ +<html> +<head> +<title>3d thingy</title> +<style type="text/css"> +div.z2 { position:absolute; z-index:2; } +div.z1 { position:absolute; z-index:1; } +</style> +<script type="text/javascript"> +/************************************************************************** +JavaScript Graphics Library 0.0.1, Updated Source Code at Scriptersoft.com +Copyright (C) 2005 Kurt L. Whicher +November,13,2005 + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +**************************************************************************/ + +//________________________________________ global variables + +var S_piDoubled=Math.PI*2; +var S_deg2Rad=Math.PI/180; + +//_______________________________________________ functions + +function S_matrix() { + return [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1]; +} +function S_vec2D(x,y) { this.x=x; this.y=y; } +function S_vec3D(x,y,z) { this.x=x; this.y=y; this.z=z; } +function S_subVec2D(a,b) { + return new S_vec2D(a.x-b.x, a.y-b.y); +} +function S_subVec3D(a,b) { + return new S_vec3D(a.x-b.x, a.y-b.y, a.z-b.z); +} +function S_dotVec3D(a, b) { return a.x*b.x+a.y*b.y+a.z*b.z; } +function S_cross(a,b) { + return new S_vec3D( a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x); +} +function S_lengthSquaredVec3D(v) { return S_dotVec3D(v,v); } +function S_lengthVec3D(v) { return Math.sqrt(S_lengthSquaredVec3D(v)); } +function S_normalizeVec3D(v) { + var l=S_lengthVec3D(v), nv=new S_vec3D(0,0,0); + if(l!=0) { nv.x=v.x/l; nv.y=v.y/l; nv.z=v.z/l; } + return nv; +} +function S_rotate(m,ax,a) { // transformation matrix, axis, angle + var i,j,ij=new Array(),v=new Array(),c=Math.cos(a),s=Math.sin(a); + if (ax=="x") ij=[1,2,5,6,9,10,13,14]; + else if (ax=="y") ij=[2,0,6,4,10,8,14,12]; + else if (ax=="z") ij=[0,1,4,5,8,9,12,13]; + for (i=0;i<8;i++) v[i]=m[ij[i]]; + for (i=0,j=1;i<8;i+=2,j+=2) { + m[ij[i]]=v[i]*c-v[j]*s; + m[ij[j]]=v[i]*s+v[j]*c + } +} +function S_checkBrowser() { + if (document.getElementById) return true; else return false; +} +function S_zIndex(e,z) { document.getElementById(e).style.zIndex=z; } +function S_rgbColor(r,g,b) { + var i, c=[r,g,b]; + for(i=0; i<3; i++) { + c[i]=Math.floor(c[i]); + if(c[i]<0) c[i]=0; else if(c[i]>255) c[i]=255; + } + return c; +} +function S_rgbColorString(c) { + return "rgb("+c[0]+","+c[1]+","+c[2]+")"; +} +function S_vertice(x,y,z) { + this.x=x; this.y=y; this.z=z; this.w=1; + this.t=new S_vec3D(x,y,z); // transformed 3d + this.p=new S_vec2D(0,0); // projected 2d +} +function S_face(v0,v1,v2,c) { // 3 vertice faces + this.v=[v0,v1,v2]; this.c=c; this.b=0; // b:brightness + this.d=true; // display: true or false +} +// x coordinate, number of vertices, distance +function S_verticeRing(x,nv,d) { + var i,a,v=new Array(); + for(i=0;i<nv;i++) { + a=S_piDoubled*i/nv; + v[i]=new S_vertice(x,d*Math.sin(a),d*Math.cos(a)); + } + return v; +} +function S_triangleRing(r1,r2,c,clr) { // rows 1 & 2, cols, color + var i,j,tr=new Array(); + for(i=0,j=1;i<c;i++,j=++j%c) { + tr.push(new S_face(r1+i,r2+i,r2+j,clr)); + tr.push(new S_face(r1+i,r2+j,r1+j,clr)); + } + return tr; +} +function S_model(v,f) { + // vertice & face arrays, transformation matrix, display boolean + this.v=v; this.f=f, this.tm=S_matrix(), this.d=true; +} +S_model.prototype.S_rotateX=function(a) { + S_rotate(this.tm,"x",a*=S_deg2Rad); +} +S_model.prototype.S_rotateY=function(a) { + S_rotate(this.tm,"y",a*=S_deg2Rad); +} +S_model.prototype.S_rotateZ=function(a) { + S_rotate(this.tm,"z",a*=S_deg2Rad); +} +S_model.prototype.S_show=function() { this.d=true; } +S_model.prototype.S_hide=function() { this.d=false; } +function S_cube(d,c) { //distance & color + return new S_cone(d,d,Math.cos(Math.PI/4)*d*2,1,4,c); +} +function S_cylinder(w,h,r,c,clr,e) { + return new S_cone(w,w,h,r,c,clr,e); +} +// width, height, "rows", "columns", color, ends +function S_cone(w1,w2,h,r,c,clr,e) { + var i,r1=0,r2=c,v=new Array(),t=new Array(),rxc=r*c; + for(i=0;i<=r;i++) + v=v.concat(S_verticeRing(h*(0.5-i/r),c,w1*i/r+w2*(r-i)/r)); + for(i=0;i<r;i++,r1+=c,r2+=c) + t=t.concat(S_triangleRing(r1,r2,c,clr)); + if (e!="hideEnds") + for(i=1;i<(c-1);i++) { + t.push(new S_face(0,i,i+1,clr)); + t.push(new S_face(rxc,rxc+i+1,rxc+i,clr)); + } + return new S_model(v,t); +} +function S_sphere(d,r,c,clr) { + // distance, "rows">=2, "columns">=3, color paramaters + var v=new Array(),t=new Array(),r_1xc=(r-1)*c,r_2xc=(r-2)*c; + var i,j,tmp,r1=0,r2=c; + for(i=1;i<r;i++) { + tmp=Math.PI*i/r; + v=v.concat(S_verticeRing(d*Math.cos(tmp),c,Math.sin(tmp)*d)); + } + v.push(new S_vertice( d,0,0)); + v.push(new S_vertice(-d,0,0)); + for(i=0;i<(r-2);i++,r1+=c,r2+=c) + t=t.concat(S_triangleRing(r1,r2,c,clr)); + for(i=0,j=1;i<c;i++,j=++j%c) { + t.push(new S_face(r_1xc,i,j,clr)); + t.push(new S_face(r_1xc+1,r_2xc+j,r_2xc+i,clr)); + } + return new S_model(v,t); +} +S_model.prototype.S_scale=function(x) { + this.tm[0]*=x; this.tm[5]*=x; this.tm[10]*=x; +} +S_model.prototype.S_faceColor=function(i,c) { this.f[i].c=c; } +S_model.prototype.S_scaleX=function(s) { this.tm[0]*=s; } +S_model.prototype.S_scaleY=function(s) { this.tm[5]*=s; } +S_model.prototype.S_scaleZ=function(s) { this.tm[10]*=s; } +function S_scene(dv,l,t,w,h,cmra) { // left, top, width, height + this.dv=dv; + this.ps=1; // pixel size + this.l=l; this.t=t; this.w=w; this.h=h; + this.cx=l+w/2; this.cy=t+h/2; // center x, center y + this.dt="paint"; // output type + this.m=new Array(); // model array + this.lght=new S_light(); + this.lc=S_rgbColor(255,255,255); // light color + this.cmra=-cmra; // camera on z axis + this.bfr=S_buffer(h,w); +} +function S_buffer(h,w) { + var i, j, b=new Array(); + for(i=0;i<h;i++) { + b[i]=new Array(); + for(j=0;j<w;j++) b[i][j]=new S_pixel(); + } + return b; +} +function S_pixel() { // display boolean, color + this.d=true; this.c=0; +} +S_pixel.prototype.S_setColor=function(c) { + this.d=true; this.c=c; +} +S_pixel.prototype.S_hide=function() { this.d=false; } +S_scene.prototype.S_pixelSize=function(ps){ this.ps=ps; } +S_scene.prototype.S_widthAndHeight=function(w,h){ this.w=w; this.h=h; } +S_scene.prototype.S_center=function(cx,cy){ this.cx=cx; this.cy=cy; } +S_scene.prototype.S_paint=function(){ this.dt="paint"; } +S_scene.prototype.S_models=function() { + var i; this.m=new Array(); + for(i=0;i<arguments.length;i++) this.m.push(arguments[i]); +} +S_scene.prototype.S_lightColor=function(c){ this.lc=c; } +S_scene.prototype.S_project=function() { + var i, j, v, tm, d, m; + for(i=0;i<this.m.length;i++) { + m=this.m[i]; tm=this.m[i].tm; + for(j=0;j<m.v.length;j++) { + v=m.v[j]; + v.t.x=v.x*tm[0]+v.y*tm[4]+v.z*tm[8]+v.w*tm[12]; + v.t.y=v.x*tm[1]+v.y*tm[5]+v.z*tm[9]+v.w*tm[13]; + v.t.z=v.x*tm[2]+v.y*tm[6]+v.z*tm[10]+v.w*tm[14]; + d=(this.cmra-v.t.z/2); + if (d<0) { + v.p.x=(this.cmra*v.t.x/d)+this.cx; + v.p.y=-(this.cmra*v.t.y/d)+this.cy; + } + } + } +} +S_scene.prototype.S_display=function(disp){ + var i, j, k, s="", ds, c, cnt=0; // ds:div start + this.tr=new Array(); // triangles ready to draw + this.S_project(); + this.S_adjustLight(); + this.S_clearBuffer(); + for(i=0;i<this.m.length;i++) { + this.m[i].S_setupFaces(this.tr,this.lght.t); + for(j=0;j<this.tr.length;j++) { // loop through triangles + c=S_divColor(this.tr[j].c,this.lc,this.tr[j].b); + S_setupBuffer(this,this.tr[j].p,c); + } + } + for(i=0;i<this.h;i++) { + ds=-1; + for(j=0,k=1;j<this.w;j++,k++) { + if((this.bfr[i][j].d==true)&&(ds==-1)) ds=j; + if( (this.bfr[i][j].d==true)&& + ( (k==this.w)|| + (this.bfr[i][k].d==false)|| + (!S_sameColor(this.bfr[i][j].c, this.bfr[i][k].c)) ) ) { + s+=S_divString(S_rgbColorString(this.bfr[i][j].c),this.t+i*this.ps,this.l+ds*this.ps,this.ps,(k-ds)*this.ps); + ds=-1; + cnt++; + } + } + } + S_writeInnerHTML(this.dv,s); + if(disp=="ShowCount") alert(cnt); +} +S_scene.prototype.S_displayAndShowCount=function(){ + this.S_display("ShowCount"); +} +S_model.prototype.S_setupFaces=function(tr,lght) { + var i, j, fn, v, p=new Array(); // vertice & projection arrays + var z=new Array(); + for(i=0;i<this.f.length;i++) { // loop through faces + v=this.f[i].v; + for(j=0;j<3;j++) { p[j]=this.v[v[j]].p; } + for(j=0;j<3;j++) { z[j]=this.v[v[j]].t.z; } + if (((p[1].x-p[0].x)*(p[2].y-p[0].y))<((p[2].x-p[0].x)*(p[1].y-p[0].y))) { + this.f[i].d=true; + fn=S_faceNormal(this.v[v[0]].t, this.v[v[1]].t, this.v[v[2]].t); + this.f[i].b=S_faceIntensity(fn,lght); + tr.push(new S_triangle(fn,this.f[i].b,p.slice(),this.f[i].c,z)); + } else { this.f[i].d=false; } + } +} +// normal, brightness, array of 2D projection coordinates, and z depth +function S_triangle(fn,b,p,c,z) { + this.fn=fn; this.b=b; this.p=p; this.z=z; this.c=c; +} +function S_faceNormal(a,b,c){ + var cr=S_cross(S_subVec3D(b,a), S_subVec3D(b,c)); + return S_normalizeVec3D(cr); +} +function S_faceIntensity(fn,lght) { + var i=S_dotVec3D(fn,lght); return (i>0)?i:0; +} +function S_divColor(c,lc,b) { // c:array of colors + var i, clr=new Array(); + for(i=0;i<3;i++) clr[i]=Math.floor(c[i]+(lc[i]-c[i]+1)*b); + for(i=0;i<3;i++) if (clr[i]>lc[i]) { clr[i]=lc[i]; } + return S_rgbColor(clr[0],clr[1],clr[2]); +} +function S_sameColor(a,b) { + for(var i=0;i<3;i++) { if(a[i]!=b[i]) return false; } + return true; +} +function S_setupBuffer(scn,p,c) { + // temp, counters, min, max, scanline, vertice & slope arrays + var t,i,j,xmin=new Array(),xmax=new Array(),sl; + var v=new Array(), m=new Array(); + p.sort(function(a,b) { return a.y-b.y; } ); + for(i=0;i<3;i++) p[i].y=Math.floor(p[i].y); + v[0]=S_subVec2D(p[1],p[0]); + v[1]=S_subVec2D(p[2],p[0]); + v[2]=S_subVec2D(p[2],p[1]); + for(i=0;i<3;i++) { m[i]=(v[i].y!=0)?v[i].x/v[i].y:0; } + for(i=0,sl=scn.t;i<scn.h;i++,sl++) { + xmin[i]=1000;xmax[i]=0; + if((sl>=p[0].y)&&(sl<=p[2].y)) { + xmin[i]=xmax[i]=Math.floor(p[0].x+m[1]*(sl-p[0].y)); + } + if((sl>=p[0].y)&&(sl<=p[1].y)) { + t=Math.floor(p[0].x+m[0]*(sl-p[0].y)); + if(t<xmin[i]) xmin[i]=Math.floor(t); + else if(t>xmax[i]) xmax[i]=Math.floor(t); + } + if((sl>=p[1].y)&&(sl<=p[2].y)) { + t=Math.floor(p[1].x+m[2]*(sl-p[1].y)); + if(t<xmin[i]) xmin[i]=Math.floor(t); + else if(t>xmax[i]) xmax[i]=Math.floor(t); + } + for(j=0;j<scn.w;j++) + if((j>=(xmin[i]-scn.l))&&(j<=(xmax[i]-scn.l))) { + scn.bfr[i][j].d=true; scn.bfr[i][j].c=c; + } + } +} +function S_light() { + this.x=0; this.y=1; this.z=0; this.w=1; // original coordinates + this.t=new S_vec3D(0,1,0); // transformed coordinates + this.tm=new S_matrix(); +} +S_scene.prototype.S_adjustLight=function() { + var m=this.lght.tm, l=this.lght; + l.t.x=l.x*m[0]+l.y*m[4]+ l.z*m[8]+l.w*m[12]; + l.t.y=l.x*m[1]+l.y*m[5]+ l.z*m[9]+l.w*m[13]; + l.t.z=l.x*m[2]+l.y*m[6]+ l.z*m[10]+l.w*m[14]; + l.t=S_normalizeVec3D(l.t); +} +S_scene.prototype.S_lightRotateX=function(a) { + S_rotate(this.lght.tm,"x",a*=S_deg2Rad); +} +S_scene.prototype.S_lightRotateY=function(a) { + S_rotate(this.lght.tm,"y",a*=S_deg2Rad); +} +S_scene.prototype.S_lightRotateZ=function(a) { + S_rotate(this.lght.tm,"z",a*=S_deg2Rad); +} +S_scene.prototype.S_clearBuffer=function() { + for(var i=0;i<this.h;i++) + for(var j=0;j<this.w;j++) this.bfr[i][j].d=false; +} +function S_divString(b,t,l,h,w) { + var s='<div style="background-color:'+b+';position:absolute;'; + s+='top:'+t+'px;left:'+l+'px;height:'+h+'px;width:'+w; + return s+'px;font-size:0;visibility:visible"></div>'; +} +function S_writeInnerHTML(id,text) { + document.getElementById(id).innerHTML = text; +} +</script> +</head> +<body> +<div class="z1" id="graphicsDiv">Text to be replaced with graphics.</div> +<script type="text/javascript"> +if(S_checkBrowser()) { +var intrvl; +// Create a new scene with parameters for +// div id, left, top, width, height, and camera distance +var scn=new S_scene("graphicsDiv",75,25,100,100,300); +scn.S_pixelSize(3); // set scene pixel size +var c=S_rgbColor(0,0,127); // color +var c2=S_rgbColor(0,127,127); // color +var m=new S_cube(18,c); // model +m.S_faceColor(4,c2); +m.S_faceColor(5,c2); +m.S_scaleX(2.5); // scale model along x axis +scn.S_models(m); // add model(s) to scene +scn.S_lightRotateX(-25); // adjust light +function r(){ // rotation function +m.S_rotateX(11); // rotate model around y axis +m.S_rotateY(5); // rotate model around y axis +m.S_rotateZ(7); // rotate model around z axis +scn.S_display(); // display scene +} // end rotation function +intrvl=setInterval('r();',75); +} +</script> + +</body> +</html> + diff --git a/build/pgo/js-input/crypto-otp.html b/build/pgo/js-input/crypto-otp.html new file mode 100644 index 0000000000..b811538ba2 --- /dev/null +++ b/build/pgo/js-input/crypto-otp.html @@ -0,0 +1,1344 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<title>One-Time Pad Generator</title> +<meta name="description" content="JavaScript One-Time Pad Generator" /> +<meta name="author" content="John Walker" /> +<meta name="keywords" content="one, time, pad, generator, onetime, cryptography, JavaScript" /> +<style type="text/css"> + a:link, a:visited { + background-color: inherit; + color: rgb(0%, 0%, 80%); + text-decoration: none; + } + + a:hover { + background-color: rgb(30%, 30%, 100%); + color: rgb(100%, 100%, 100%); + } + + a:active { + color: rgb(100%, 0%, 0%); + background-color: rgb(30%, 30%, 100%); + } + + a.i:link, a.i:visited, a.i:hover { + background-color: inherit; + color: inherit; + text-decoration: none; + } + + body { + margin-left: 15%; + margin-right: 10%; + background-color: #FFFFFF; + color: #000000; + } + + body.jsgen { + margin-left: 5%; + margin-right: 5%; + } + + dt { + margin-top: 0.5em; + } + + img.button { + border: 0px; + vertical-align: middle; + } + + img.keyicon { + vertical-align: bottom; + } + + p, dd, li { + text-align: justify; + } + + p.centre { + text-align: center; + } + + table.r { + float: right; + } + + table.c { + background-color: #E0E0E0; + color: #000000; + margin-left: auto; + margin-right: auto; + } + + td.c { + text-align: center; + } + + textarea { + background-color: #FFFFD0; + color: #000000; + } +</style> +<script type="text/javascript"> +//<![CDATA[ + + loadTime = (new Date()).getTime(); + +/* + + L'Ecuyer's two-sequence generator with a Bays-Durham shuffle + on the back-end. Schrage's algorithm is used to perform + 64-bit modular arithmetic within the 32-bit constraints of + JavaScript. + + Bays, C. and S. D. Durham. ACM Trans. Math. Software: 2 (1976) + 59-64. + + L'Ecuyer, P. Communications of the ACM: 31 (1968) 742-774. + + Schrage, L. ACM Trans. Math. Software: 5 (1979) 132-138. + +*/ + +function uGen(old, a, q, r, m) { // Schrage's modular multiplication algorithm + var t; + + t = Math.floor(old / q); + t = a * (old - (t * q)) - (t * r); + return Math.round((t < 0) ? (t + m) : t); +} + +function LEnext() { // Return next raw value + var i; + + this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563); + this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399); + + /* Extract shuffle table index from most significant part + of the previous result. */ + + i = Math.floor(this.state / 67108862); + + // New state is sum of generators modulo one of their moduli + + this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563); + + // Replace value in shuffle table with generator 1 result + + this.shuffle[i] = this.gen1; + + return this.state; +} + +// Return next random integer between 0 and n inclusive + +function LEnint(n) { + return Math.floor(this.next() / (1 + 2147483562 / (n + 1))); +} + +// Constructor. Called with seed value + +function LEcuyer(s) { + var i; + + this.shuffle = new Array(32); + this.gen1 = this.gen2 = (s & 0x7FFFFFFF); + for (i = 0; i < 19; i++) { + this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563); + } + + // Fill the shuffle table with values + + for (i = 0; i < 32; i++) { + this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563); + this.shuffle[31 - i] = this.gen1; + } + this.state = this.shuffle[0]; + this.next = LEnext; + this.nextInt = LEnint; +} + +function sepchar() { + if (rsep) { + var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~"; + return seps.charAt(sepran.nextInt(seps.length - 1)); + } + return "-"; +} + +/* + * md5.jvs 1.0b 27/06/96 + * + * Javascript implementation of the RSA Data Security, Inc. MD5 + * Message-Digest Algorithm. + * + * Copyright (c) 1996 Henri Torgemane. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + + This version contains some trivial reformatting modifications + by John Walker. + + */ + +function array(n) { + for (i = 0; i < n; i++) { + this[i] = 0; + } + this.length = n; +} + +/* Some basic logical functions had to be rewritten because of a bug in + * Javascript.. Just try to compute 0xffffffff >> 4 with it.. + * Of course, these functions are slower than the original would be, but + * at least, they work! + */ + +function integer(n) { + return n % (0xffffffff + 1); +} + +function shr(a, b) { + a = integer(a); + b = integer(b); + if (a - 0x80000000 >= 0) { + a = a % 0x80000000; + a >>= b; + a += 0x40000000 >> (b - 1); + } else { + a >>= b; + } + return a; +} + +function shl1(a) { + a = a % 0x80000000; + if (a & 0x40000000 == 0x40000000) { + a -= 0x40000000; + a *= 2; + a += 0x80000000; + } else { + a *= 2; + } + return a; +} + +function shl(a, b) { + a = integer(a); + b = integer(b); + for (var i = 0; i < b; i++) { + a = shl1(a); + } + return a; +} + +function and(a, b) { + a = integer(a); + b = integer(b); + var t1 = a - 0x80000000; + var t2 = b - 0x80000000; + if (t1 >= 0) { + if (t2 >= 0) { + return ((t1 & t2) + 0x80000000); + } else { + return (t1 & b); + } + } else { + if (t2 >= 0) { + return (a & t2); + } else { + return (a & b); + } + } +} + +function or(a, b) { + a = integer(a); + b = integer(b); + var t1 = a - 0x80000000; + var t2 = b - 0x80000000; + if (t1 >= 0) { + if (t2 >= 0) { + return ((t1 | t2) + 0x80000000); + } else { + return ((t1 | b) + 0x80000000); + } + } else { + if (t2 >= 0) { + return ((a | t2) + 0x80000000); + } else { + return (a | b); + } + } +} + +function xor(a, b) { + a = integer(a); + b = integer(b); + var t1 = a - 0x80000000; + var t2 = b - 0x80000000; + if (t1 >= 0) { + if (t2 >= 0) { + return (t1 ^ t2); + } else { + return ((t1 ^ b) + 0x80000000); + } + } else { + if (t2 >= 0) { + return ((a ^ t2) + 0x80000000); + } else { + return (a ^ b); + } + } +} + +function not(a) { + a = integer(a); + return 0xffffffff - a; +} + +/* Here begin the real algorithm */ + +var state = new array(4); +var count = new array(2); + count[0] = 0; + count[1] = 0; +var buffer = new array(64); +var transformBuffer = new array(16); +var digestBits = new array(16); + +var S11 = 7; +var S12 = 12; +var S13 = 17; +var S14 = 22; +var S21 = 5; +var S22 = 9; +var S23 = 14; +var S24 = 20; +var S31 = 4; +var S32 = 11; +var S33 = 16; +var S34 = 23; +var S41 = 6; +var S42 = 10; +var S43 = 15; +var S44 = 21; + +function F(x, y, z) { + return or(and(x, y), and(not(x), z)); +} + +function G(x, y, z) { + return or(and(x, z), and(y, not(z))); +} + +function H(x, y, z) { + return xor(xor(x, y), z); +} + +function I(x, y, z) { + return xor(y ,or(x , not(z))); +} + +function rotateLeft(a, n) { + return or(shl(a, n), (shr(a, (32 - n)))); +} + +function FF(a, b, c, d, x, s, ac) { + a = a + F(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function GG(a, b, c, d, x, s, ac) { + a = a + G(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function HH(a, b, c, d, x, s, ac) { + a = a + H(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function II(a, b, c, d, x, s, ac) { + a = a + I(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function transform(buf, offset) { + var a = 0, b = 0, c = 0, d = 0; + var x = transformBuffer; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + for (i = 0; i < 16; i++) { + x[i] = and(buf[i * 4 + offset], 0xFF); + for (j = 1; j < 4; j++) { + x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8); + } + } + + /* Round 1 */ + a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + +} + +function init() { + count[0] = count[1] = 0; + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + for (i = 0; i < digestBits.length; i++) { + digestBits[i] = 0; + } +} + +function update(b) { + var index, i; + + index = and(shr(count[0],3) , 0x3F); + if (count[0] < 0xFFFFFFFF - 7) { + count[0] += 8; + } else { + count[1]++; + count[0] -= 0xFFFFFFFF + 1; + count[0] += 8; + } + buffer[index] = and(b, 0xff); + if (index >= 63) { + transform(buffer, 0); + } +} + +function finish() { + var bits = new array(8); + var padding; + var i = 0, index = 0, padLen = 0; + + for (i = 0; i < 4; i++) { + bits[i] = and(shr(count[0], (i * 8)), 0xFF); + } + for (i = 0; i < 4; i++) { + bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF); + } + index = and(shr(count[0], 3), 0x3F); + padLen = (index < 56) ? (56 - index) : (120 - index); + padding = new array(64); + padding[0] = 0x80; + for (i = 0; i < padLen; i++) { + update(padding[i]); + } + for (i = 0; i < 8; i++) { + update(bits[i]); + } + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF); + } + } +} + +/* End of the MD5 algorithm */ + +function gen() { + window.status = "Generating..."; + document.getElementById('onetime').pad.value = ""; + + lower = document.getElementById('onetime').textcase.selectedIndex == 0; + upper = document.getElementById('onetime').textcase.selectedIndex == 1; + mixed = document.getElementById('onetime').textcase.selectedIndex == 2; + rsep = document.getElementById('onetime').rsep.checked; + if (!(numeric = document.getElementById('onetime').keytype[0].checked)) { + english = document.getElementById('onetime').keytype[1].checked; + gibberish = document.getElementById('onetime').keytype[3].checked; + } + clockseed = document.getElementById('onetime').seedy[0].checked + makesig = document.getElementById('onetime').dosig.checked; + npass = document.getElementById('onetime').nkeys.value; + pw_length = Math.round(document.getElementById('onetime').klength.value); + sep = document.getElementById('onetime').sep.value; + linelen = document.getElementById('onetime').linelen.value; +// 01234567890123456789012345678901 + charcodes = " " + + "!\"#$%&'()*+,-./0123456789:;<=>?" + + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + + "`abcdefghijklmnopqrstuvwxyz{|}~"; + + if (clockseed) { + var n, j, ran0; + + /* Obtain seed from the clock. To reduce the likelihood + of the seed being guessed, we create the seed by combining + the time of the request with the time the page was loaded, + then use that composite value to seed an auxiliary generator + which is cycled between one and 32 times based on the time + derived initial seed, with the output of the generator fed + back into the seed we use to generate the pad. */ + + seed = Math.round((new Date()).getTime() % Math.pow(2, 31)); + ran0 = new LEcuyer((seed ^ Math.round(loadTime % Math.pow(2, 31))) & 0x7FFFFFFF); + for (j = 0; j < (5 + ((seed >> 3) & 0xF)); j++) { + n = ran0.nextInt(31); + } + while (n-- >= 0) { + seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next(); + } + seed &= 0x7FFFFFFF; + document.getElementById('onetime').seeder.value = seed; + } else { + var useed, seedNum; + + /* Obtain seed from user specification. If the seed is a + decimal number, use it as-is. If it contains any + non-numeric characters, construct a hash code and + use that as the seed. */ + + useed = document.getElementById('onetime').seeder.value; + seedNum = true; + for (i = 0; i < useed.length; i++) { + if (!"0123456789".includes(useed.charAt(i))) { + seedNum = false; + break; + } + } + if (seedNum) { + seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31)); + document.getElementById('onetime').seeder.value = seed; + } else { + var s, t, iso, hex; + + iso = ""; + hex = "0123456789ABCDEF"; + for (i = 32; i < 256; i++) { + if (i < 127 || i >= 160) { + // Why not "s = i.toString(16);"? Doesn't work in Netscape 3.0 + iso += "%" + hex.charAt(i >> 4) + hex.charAt(i & 0xF); + } + } + iso = unescape(iso); + s = 0; + for (i = 0; i < useed.length; i++) { + t = iso.indexOf(useed.charAt(i)); + if (t < 0) { + t = 17; + } + s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t); + } + seed = s; + } + } + ran1 = new LEcuyer(seed); + ran2 = new LEcuyer(seed); + if (rsep) { + /* Use a separate random generator for separators + so that results are the same for a given seed + for both choices of separators. */ + sepran = new LEcuyer(seed); + } + + ndig = 1; + j = 10; + while (npass >= j) { + ndig++; + j *= 10; + } + pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0); + pw_item += ndig + 5; + j = pw_item * 3; + if (j < 132) { + j = 132; + } + npline = Math.floor(linelen / pw_item); + if (npline < 1) { + npline = 0; + } + v = ""; + md5v = ""; + lineno = 0; + if (!numeric) { + letters = "abcdefghijklmnopqrstuvwxyz"; + if (upper) { + letters = letters.toUpperCase(); + } + if (english) { + + // Frequency of English digraphs (from D. Edwards 1/27/66) + + frequency = new Array( + new Array(4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, + 23, 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1, + 9, 1), /* aa - az */ + + new Array(13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0, + 11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0), /* ba - bz */ + + new Array(32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, + 0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0), /* ca - cz */ + + new Array(40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, + 6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0), /* da - dz */ + + new Array(84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, + 55, 54, 146, 35, 37, 6, 191, 149, 65, 9, 26, + 21, 12, 5, 0), /* ea - ez */ + + new Array(19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, + 0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0), /* fa - fz */ + + new Array(20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, + 4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0), /* ga - gz */ + + new Array(101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, + 2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0), /* ha - hz */ + + new Array(40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, + 25, 202, 56, 12, 1, 46, 79, 117, 1, 22, 0, + 4, 0, 3), /* ia - iz */ + + new Array(3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0), /* ja - jz */ + + new Array(1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0), /* ka - kz */ + + new Array(44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, + 2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0), /* la - lz */ + + new Array(52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, + 1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0), /* ma - mz */ + + new Array(42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, + 6, 9, 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0, + 12, 0), /* na - nz */ + + new Array(7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, + 41, 134, 13, 23, 0, 91, 23, 42, 55, 16, 28, + 0, 4, 1), /* oa - oz */ + + new Array(19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0, + 27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0), /* pa - pz */ + + new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0), /* qa - qz */ + + new Array(83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, + 26, 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0, + 28, 0), /* ra - rz */ + + new Array(65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, + 11, 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0, + 4, 0), /* sa - sz */ + + new Array(57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, + 10, 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0, + 24, 0), /* ta - tz */ + + new Array(11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31, + 1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0), /* ua - uz */ + + new Array(7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0), /* va - vz */ + + new Array(36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, + 8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0), /* wa - wz */ + + new Array(1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1, + 5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0), /* xa - xz */ + + new Array(14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, + 5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0), /* ya - yz */ + + new Array(1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) /* za - zz */ ); + + // This MUST be equal to the sum of the equivalent rows above. + + row_sums = new Array( + 796, 160, 284, 401, 1276, 262, 199, 539, 777, + 16, 39, 351, 243, 751, 662, 181, 17, 683, + 662, 968, 248, 115, 180, 17, 162, 5 + ); + + // Frequencies of starting characters. + + start_freq = new Array( + 1299, 425, 725, 271, 375, 470, 93, 223, 1009, + 24, 20, 355, 379, 319, 823, 618, 21, 317, + 962, 1991, 271, 104, 516, 6, 16, 14 + ); + + // This MUST be equal to the sum of all elements in the above array. + + total_sum = 11646; + } + if (gibberish) { + gibber = "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + "!#$%&()*+,-./:;<=>?@[]^_{|}~"; + if (upper) { + /* Convert to upper case, leaving two copies of the + alphabet for two reasons: first, to favour letters + over gnarl, and second, to change only the letter case + when the mode is selected. */ + gibber = gibber.toUpperCase(); + } else if (lower) { + gibber = gibber.toLowerCase(); + } + } + } + for (line = 1; line <= npass; line++) { + password = ""; + if (numeric) { + for (nchars = 0; nchars < pw_length; nchars++) { + if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) { + password += sepchar(); + } + password += ran1.nextInt(9); + } + } else if (!english) { + for (nchars = 0; nchars < pw_length; nchars++) { + if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) { + password += sepchar(); + } + if (gibberish) { + password += gibber.charAt(ran1.nextInt(gibber.length - 1)); + } else { + password += letters.charAt(ran1.nextInt(25)); + } + } + } else { + position = ran1.nextInt(total_sum - 1); + for (row_position = 0, j = 0; position >= row_position; + row_position += start_freq[j], j++) { + continue; + } + + password = letters.charAt(i = j - 1); + nch = 1; + for (nchars = pw_length - 1; nchars; --nchars) { + + // Now find random position within the row. + + position = ran1.nextInt(row_sums[i] - 1); + for (row_position = 0, j = 0; + position >= row_position; + row_position += frequency[i][j], j++) { + } + + if ((sep > 0) && ((nch % sep) == 0)) { + password += sepchar(); + } + nch++; + password += letters.charAt(i = j - 1); + } + } + + if ((!numeric) && (!gibberish) && mixed) { + var pwm = ''; + var j; + for (j = 0; j < password.length; j++) { + pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase()); + } + password = pwm; + } + + /* If requested, calculate the MD5 signature for this key and + and save for later appending to the results. */ + + if (makesig) { + var n, m, hex = "0123456789ABCDEF"; + + init(); + for (m = 0; m < password.length; m++) { + update(32 + charcodes.indexOf(password.charAt(m))); + } + finish(); + + for (n = 0; n < 16; n++) { + md5v += hex.charAt(digestBits[n] >> 4); + md5v += hex.charAt(digestBits[n] & 0xF); + } + md5v += "\n"; + } + + aline = "" + line; + while (aline.length < ndig) { + aline = " " + aline; + } + v += aline + ") " + password; + + if ((++lineno) >= npline) { + v += "\n"; + lineno = 0; + } else { + v += " "; + } + } + + if (makesig) { + v += "\n---------- MD5 Signatures ----------\n" + md5v; + } + + document.getElementById('onetime').pad.value = v; + window.status = "Done."; +} + +function loadHandler() { + for (var i = 0; i < 25; i++) { + gen(); + } +}; + +//]]> +</script> + +</head> + +<body class="jsgen" onload="loadHandler();"> + +<h1><img src="key.gif" class="keyicon" alt="" + width="40" height="40" /> One-Time Pad Generator</h1> + +<p> +This page, which requires that your browser support JavaScript +(see <a href="#why"><cite>Why JavaScript</cite></a> below), +generates one-time pads or password lists in a variety of +forms. It is based a high-quality pseudorandom sequence +generator, which can be seeded either from the current date +and time, or from a seed you provide. Fill in the form below +to select the format of the pad and press “Generate” to +create the pad in the text box. You can then copy and paste +the generated pad into another window to use as you wish. +Each of the labels on the request form is linked to a description +of that parameter. +</p> + +<form id="onetime" action="#" onsubmit="return false;"> + +<p class="centre"> +<b>Output:</b> +<a href="#NumberOfKeys">Number of keys</a>: <input type="text" name="nkeys" value="20" size="4" maxlength="12" /> +<a href="#LineLength">Line length</a>: <input type="text" name="linelen" value="48" size="3" maxlength="12" /> +<br /> +<b>Format:</b> +<a href="#KeyLength">Key length</a>: <input type="text" name="klength" value="8" size="3" maxlength="12" /> +<a href="#GroupLength">Group length</a>: <input type="text" name="sep" value="4" size="2" maxlength="12" /> + +<br /> +<b>Composition:</b> +<a href="#KeyText">Key text</a>: <input type="radio" name="keytype" /> Numeric +<input type="radio" name="keytype" /> Word-like +<input type="radio" name="keytype" checked="checked" /> Alphabetic +<input type="radio" name="keytype" /> Gibberish +<br /> +<a href="#LetterCase">Letters:</a> +<select size="i" name="textcase"> + + <option value="1" selected="selected">Lower case</option> + <option value="2">Upper case</option> + <option value="3">Mixed case</option> +</select> + +<input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a> +<input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a> + +<br /> +<b><a href="#Seed">Seed:</a></b> +<input type="radio" name="seedy" checked="checked" /> From clock +<input type="radio" name="seedy" /> User-defined: +<input type="text" name="seeder" value="" size="12" maxlength="128" + onchange="document.getElementById('onetime').seedy[1].checked=true;" /> +<br /> +<input type="button" value=" Generate " onclick="gen();" /> + +<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" /> + +<input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br /> +<textarea name="pad" rows="12" cols="72"> + +Uh, oh. It appears your browser either does not support +JavaScript or that JavaScript has been disabled. You'll +have to replace your browser with one supporting JavaScript +(or enable it, if that's the problem) before you can use +this page. +</textarea> +</p> + +</form> + +<script type="text/javascript"> +//<![CDATA[ + // Clear out "sorry, no JavaScript" message from text box. + document.getElementById('onetime').pad.value = ""; +//]]> +</script> + +<h2><a name="details">Details</a></h2> + +<p> +Each of the fields in the one-time pad request form is described +below. +</p> + +<h3><a name="output">Output</a></h3> + +<h4><a name="NumberOfKeys">Number of keys</a></h4> + +<p> +Enter the number of keys you'd like to generate. If you generate +more than fit in the results text box, you can use the scroll +bar to view the additional lines. +</p> + +<h4><a name="LineLength">Line length</a></h4> + +<p> +Lines in the output will be limited to the given length (or contain +only one key if the line length is less than required for a single +key). If the line length is greater than the width of the results +box, you can use the horizontal scroll bar to view the rest of the +line. Enter <tt>0</tt> to force one key per line; this is handy +when you're preparing a list of keys to be read by a computer program. +</p> + +<h3><a name="format">Format</a></h3> + +<h4><a name="KeyLength">Key length</a></h4> + +<p> +Each key will contain this number of characters, not counting +separators between groups. +</p> + +<h4><a name="GroupLength">Group length</a></h4> + +<p> +If a nonzero value is entered in this field, the key will be broken +into groups of the given number of characters by separators. Humans +find it easier to read and remember sequences of characters when +divided into groups of five or fewer characters. +</p> + +<h3><a name="composition">Composition</a></h3> + +<h4><a name="KeyText">Key text</a></h4> + +<p> +This set of radio buttons lets you select the character set used in +the keys. The alternatives are listed in order of +increasing security. +</p> + +<blockquote> +<dl> +<dt><b>Numeric</b></dt> +<dd>Keys contain only the decimal digits “0” through “9”. + <em>Least secure.</em></dd> + +<dt><b>Word-like</b></dt> +<dd>Keys are composed of alphabetic characters which obey the + digraph statistics of English text. Such keys contain + sequences of vowels and consonants familiar to speakers + of Western languages, and are therefore usually easier to + memorise but, for a given key length, are less secure than + purely random letters.</dd> + +<dt><b>Alphabetic</b></dt> +<dd>Keys consist of letters of the alphabet chosen at random. + Each character has an equal probability of being one of + the 26 letters.</dd> + +<dt><b>Gibberish</b></dt> +<dd>Keys use most of the printable ASCII character set, excluding + only characters frequently used for quoting purposes. This + option provides the greatest security for a given key length, + but most people find keys like this difficult to memorise or + even transcribe from a printed pad. If a human is in the loop, + it's often better to use a longer alphabetic or word-like key. + <em>Most secure.</em></dd> +</dl> + +</blockquote> + +<h4><a name="LetterCase">Letters</a></h4> + +<p> +The case of letters in keys generated with Word-like, Alphabetic, and +Gibberish key text will be as chosen. Most people find it easier to +read lower case letters than all capitals, but for some applications +(for example, where keys must be scanned optically by hardware that +only recognises capital letters), capitals are required. Selecting +“Mixed case” creates keys with a mix of upper- and +lower-case letters; such keys are more secure than those with uniform +letter case, but do not pass the “telephone test”: you +can't read them across a (hopefully secure) voice link without having +to indicate whether each letter is or is not a capital. +</p> + +<h4><a name="RandomSep">Random separators</a></h4> + +<p> +When the <a href="#KeyLength">Key length</a> is longer than +a nonzero <a href="#GroupLength">Group length</a> specification, +the key is divided into sequences of the given group length +by separator characters. By default, a hyphen, “<tt>-</tt>”, is used +to separate groups. If you check this box, separators will be +chosen at random among punctuation marks generally acceptable +for applications such as passwords. If you're generating passwords +for a computer system, random separators dramatically increase +the difficulty of guessing passwords by exhaustive search. +</p> + +<h4><a name="Signatures">Include signatures</a></h4> + +<p> + +When this box is checked, at the end of the list of keys, preceded by +a line beginning with ten dashes “<tt>-</tt>”, the 128 bit MD5 signature of +each key is given, one per line, with signatures expressed as 32 +hexadecimal digits. Key signatures can be used to increase security +when keys are used to control access to computer systems or databases. +Instead of storing a copy of the keys, the computer stores their +signatures. When the user enters a key, its signature is computed +with the same MD5 algorithm used to generate it initially, and the key +is accepted only if the signature matches. Since discovering +a key which will generate a given signature is believed to be +computationally prohibitive, even if the list of signatures stored on +the computer is compromised, that information will not permit an +intruder to deduce a valid key. +</p> + +<p> +Signature calculation is a computationally intense process for which +JavaScript is not ideally suited; be patient while signatures are +generated, especially if your computer has modest +processing speed. +</p> + +<p> +For signature-based validation to be secure, it is essential +the original keys be long enough to prohibit discovery of matching +signatures by exhaustive search. Suppose, for example, one used +four digit numeric keys, as used for Personal Identification +Numbers (PINs) by many credit card systems. Since only 10,000 +different keys exist, one could simply compute the signatures of +every possible key from 0000 through 9999, permitting an attacker who +came into possession of the table of signatures to recover the +keys by a simple lookup process. For maximum security, keys must +contain at least as much information as the 128 bit signatures +computed from them. This implies a minimum key length (not counting +non-random separator characters) for the various key formats as +follows: +</p> + +<table class="c" border="border" cellpadding="4"> +<tr><th>Key Composition</th> <th>Minimum Characters</th></tr> + +<tr><td>Numeric</td> <td class="c">39</td></tr> +<tr><td>Word-like</td> <td class="c">30</td></tr> +<tr><td>Alphabetic</td> <td class="c">28</td></tr> +<tr><td>Gibberish</td> <td class="c">20</td></tr> +</table> + +<p> +It should be noted that for many practical applications there is no +need for anything approaching 128-bit security. The guidelines above +apply only in the case where maximum protection in the event of +undetected compromise of key signatures occurs. In many +cases, much shorter keys are acceptable, especially when it is assumed +that a compromise of the system's password or signature database would +be only part of a much more serious subversion of all resources +on the system. +</p> + +<h3><a name="Seed">Seed</a></h3> + +<p> +The <em>seed</em> is the starting value which determines all +subsequent values in the pseudorandom sequence used to generate +the one-time pad. Given the seed, the pad can be reproduced. The +seed is a 31-bit number which can be derived from the date and +time at which the one-time pad was requested, or from a +user-defined seed value. If the user-defined seed consists +entirely of decimal digits, it is used directly as the seed, +modulo 2<sup>31</sup>; if a string containing non-digit characters +is entered, it is used to compute a <em>hash code</em> which is +used to seed the generator. + +</p> + +<p> +When the clock is used to create the seed, the seed value is entered +in the User-defined box to allow you, by checking “User-defined”, +to produce additional pads with the same seed. +</p> + +<h2><a name="why">Why JavaScript?</a></h2> + +<p> +At first glance, JavaScript may seem an odd choice for programming +a page such as this. The one-time pad generator program is rather +large and complicated, and downloading it to your browser takes longer +than would be required for a Java applet or to transfer a +one-time pad generated by a CGI program on the Web server. I chose +JavaScript for two reasons: <em>security</em> and <em>transparency</em>. + +</p> + +<p> +<b>Security.</b> +The sole reason for the existence of one-time pads is to +provide a source of information known only to people to whom +they have been distributed in a secure manner. This means +the generation process cannot involve any link whose security +is suspect. If the pad were generated on a Web server and +transmitted to you, it would have to pass over the +Internet, where any intermediate site might make a copy +of your pad before you even received it. Even if some +mechanism such as encryption could absolutely prevent the +pad's being intercepted, you'd still have no way to be sure +the site generating the pad didn't keep a copy +in a file, conveniently tagged with your Internet address. +</p> + +<p> +In order to have any degree of security, it is essential +that the pad be generated on <em>your</em> computer, without +involving any transmission or interaction with other +sites on the Internet. A Web browser with JavaScript makes +this possible, since the generation program embedded in this +page runs entirely on your own computer and does not +transmit anything over the Internet. Its output appears +only in the text box, allowing you to cut and paste it +to another application. From there on, its security is +up to you. +</p> + +<p> +Security is never absolute. A one-time pad generated with +this page might be compromised in a variety of ways, including +the following: + +</p> + +<ul> +<li> Your Web browser and/or JavaScript interpreter may + contain bugs or deliberate security violations + which report activity on your computer back to some + other Internet site.</li> + +<li> Some other applet running on another page of your + browser, perhaps without your being aware of its + existence, is spying on other windows.</li> + +<li> Some other application running on your computer + may have compromised your system's security and + be snooping on your activity.</li> + +<li> Your Web browser may be keeping a “history log” + + or “cache” of data you generate. Somebody may + come along later and recover a copy of the pad + from that log.</li> + +<li> The implementation of this page may contain a bug + or deliberate error which makes its output + predictable. This is why <a href="#trans"><cite>transparency</cite></a>, + discussed below, is essential.</li> + +<li> Your computer's security may have been compromised + physically; when's the last time you checked that a + bug that transmits your keystrokes and/or screen + contents to that white van parked down the street + wasn't lurking inside your computer cabinet?</li> +</ul> + +<p> +One can whip oneself into a fine fever of paranoia worrying about +things like this. One way to rule out the most probable risks +is to download a copy of the generator page and run it +from a “<tt>file:</tt>” URL on a computer which has no network +connection whatsoever and is located in a secure location +under your control. And look very carefully at any files +created by your Web browser. You may find the most interesting +things squirreled away there…. +</p> + +<p> +<b><a name="trans">Transparency</a>.</b> +Any security-related tool is only as good as its design +and implementation. <em>Transparency</em> means that, in +essence, all the moving parts are visible so you can judge +for yourself whether the tool merits your confidence. In +the case of a program, this means that source code must +be available, and that you can verify that the program +you're running corresponds to the source code provided. + +</p> + +<p> +The very nature of JavaScript achieves this transparency. +The program is embedded into this actual Web page; to +examine it you need only use your browser's “View Source” +facility, or save the page into a file on your computer +and read it with a text editor. JavaScript's being +an interpreted language eliminates the risk of your running +a program different from the purported source code: with +an interpreted language what you read is what you run. +</p> + +<p> +Transparency is important even if you don't know enough about +programming or security to determine whether the program +contains any flaws. The very fact that it can be examined +by anybody allows those with the required expertise to pass +judgment, and you can form your own conclusions based on +their analysis. +</p> + +<h2>Credits</h2> + +<p> + +The pseudorandom sequence generator is based on L'Ecuyer's +two-sequence generator as described in +<cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742. +A Bays-Durham shuffle is used to guard against regularities +lurking in L'Ecuyer's algorithm; see +<cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976) +pages 59–64 for details. +</p> + +<p> +The JavaScript implementation of the +<a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a> +was developed by Henri Torgemane; please view the source code of this +page to examine the code, including the copyright notice and +conditions of use. The MD5 algorithm was developed by Ron Rivest. +</p> + +<p /> + +<hr /> + +<p /> + +<table class="r"> +<tr><td align="center"> + <a class="i" href="http://validator.w3.org/check?uri=referer"><img + class="button" + src="valid-xhtml10.png" + alt="Valid XHTML 1.0" height="31" width="88" /></a> +</td></tr> +</table> + +<address> +by <a href="/">John Walker</a><br /> +May 26, 1997<br /> + +Updated: November 2006 +</address> + +<p class="centre"> +<em>This document is in the public domain.</em> +</p> +</body> +</html> + diff --git a/build/pgo/js-input/key.gif b/build/pgo/js-input/key.gif Binary files differnew file mode 100644 index 0000000000..050311fc6b --- /dev/null +++ b/build/pgo/js-input/key.gif diff --git a/build/pgo/js-input/sunspider/3d-cube.html b/build/pgo/js-input/sunspider/3d-cube.html new file mode 100644 index 0000000000..453167d44d --- /dev/null +++ b/build/pgo/js-input/sunspider/3d-cube.html @@ -0,0 +1,387 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider 3d-cube</title> + +</head> + +<body> +<h3>3d-cube</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// 3D Cube Rotation +// http://www.speich.net/computer/moztesting/3d.htm +// Created by Simon Speich + +var Q = new Array(); +var MTrans = new Array(); // transformation matrix +var MQube = new Array(); // position information of qube +var I = new Array(); // entity matrix +var Origin = new Object(); +var Testing = new Object(); +var LoopTimer; + +var DisplArea = new Object(); +DisplArea.Width = 300; +DisplArea.Height = 300; + +function DrawLine(From, To) { + var x1 = From.V[0]; + var x2 = To.V[0]; + var y1 = From.V[1]; + var y2 = To.V[1]; + var dx = Math.abs(x2 - x1); + var dy = Math.abs(y2 - y1); + var x = x1; + var y = y1; + var IncX1, IncY1; + var IncX2, IncY2; + var Den; + var Num; + var NumAdd; + var NumPix; + + if (x2 >= x1) { IncX1 = 1; IncX2 = 1; } + else { IncX1 = -1; IncX2 = -1; } + if (y2 >= y1) { IncY1 = 1; IncY2 = 1; } + else { IncY1 = -1; IncY2 = -1; } + if (dx >= dy) { + IncX1 = 0; + IncY2 = 0; + Den = dx; + Num = dx / 2; + NumAdd = dy; + NumPix = dx; + } + else { + IncX2 = 0; + IncY1 = 0; + Den = dy; + Num = dy / 2; + NumAdd = dx; + NumPix = dy; + } + + NumPix = Math.round(Q.LastPx + NumPix); + + var i = Q.LastPx; + for (; i < NumPix; i++) { + Num += NumAdd; + if (Num >= Den) { + Num -= Den; + x += IncX1; + y += IncY1; + } + x += IncX2; + y += IncY2; + } + Q.LastPx = NumPix; +} + +function CalcCross(V0, V1) { + var Cross = new Array(); + Cross[0] = V0[1]*V1[2] - V0[2]*V1[1]; + Cross[1] = V0[2]*V1[0] - V0[0]*V1[2]; + Cross[2] = V0[0]*V1[1] - V0[1]*V1[0]; + return Cross; +} + +function CalcNormal(V0, V1, V2) { + var A = new Array(); var B = new Array(); + for (var i = 0; i < 3; i++) { + A[i] = V0[i] - V1[i]; + B[i] = V2[i] - V1[i]; + } + A = CalcCross(A, B); + var Length = Math.sqrt(A[0]*A[0] + A[1]*A[1] + A[2]*A[2]); + for (var i = 0; i < 3; i++) A[i] = A[i] / Length; + A[3] = 1; + return A; +} + +function CreateP(X,Y,Z) { + this.V = [X,Y,Z,1]; +} + +// multiplies two matrices +function MMulti(M1, M2) { + var M = [[],[],[],[]]; + var i = 0; + var j = 0; + for (; i < 4; i++) { + j = 0; + for (; j < 4; j++) M[i][j] = M1[i][0] * M2[0][j] + M1[i][1] * M2[1][j] + M1[i][2] * M2[2][j] + M1[i][3] * M2[3][j]; + } + return M; +} + +//multiplies matrix with vector +function VMulti(M, V) { + var Vect = new Array(); + var i = 0; + for (;i < 4; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2] + M[i][3] * V[3]; + return Vect; +} + +function VMulti2(M, V) { + var Vect = new Array(); + var i = 0; + for (;i < 3; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2]; + return Vect; +} + +// add to matrices +function MAdd(M1, M2) { + var M = [[],[],[],[]]; + var i = 0; + var j = 0; + for (; i < 4; i++) { + j = 0; + for (; j < 4; j++) M[i][j] = M1[i][j] + M2[i][j]; + } + return M; +} + +function Translate(M, Dx, Dy, Dz) { + var T = [ + [1,0,0,Dx], + [0,1,0,Dy], + [0,0,1,Dz], + [0,0,0,1] + ]; + return MMulti(T, M); +} + +function RotateX(M, Phi) { + var a = Phi; + a *= Math.PI / 180; + var Cos = Math.cos(a); + var Sin = Math.sin(a); + var R = [ + [1,0,0,0], + [0,Cos,-Sin,0], + [0,Sin,Cos,0], + [0,0,0,1] + ]; + return MMulti(R, M); +} + +function RotateY(M, Phi) { + var a = Phi; + a *= Math.PI / 180; + var Cos = Math.cos(a); + var Sin = Math.sin(a); + var R = [ + [Cos,0,Sin,0], + [0,1,0,0], + [-Sin,0,Cos,0], + [0,0,0,1] + ]; + return MMulti(R, M); +} + +function RotateZ(M, Phi) { + var a = Phi; + a *= Math.PI / 180; + var Cos = Math.cos(a); + var Sin = Math.sin(a); + var R = [ + [Cos,-Sin,0,0], + [Sin,Cos,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + return MMulti(R, M); +} + +function DrawQube() { + // calc current normals + var CurN = new Array(); + var i = 5; + Q.LastPx = 0; + for (; i > -1; i--) CurN[i] = VMulti2(MQube, Q.Normal[i]); + if (CurN[0][2] < 0) { + if (!Q.Line[0]) { DrawLine(Q[0], Q[1]); Q.Line[0] = true; }; + if (!Q.Line[1]) { DrawLine(Q[1], Q[2]); Q.Line[1] = true; }; + if (!Q.Line[2]) { DrawLine(Q[2], Q[3]); Q.Line[2] = true; }; + if (!Q.Line[3]) { DrawLine(Q[3], Q[0]); Q.Line[3] = true; }; + } + if (CurN[1][2] < 0) { + if (!Q.Line[2]) { DrawLine(Q[3], Q[2]); Q.Line[2] = true; }; + if (!Q.Line[9]) { DrawLine(Q[2], Q[6]); Q.Line[9] = true; }; + if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; }; + if (!Q.Line[10]) { DrawLine(Q[7], Q[3]); Q.Line[10] = true; }; + } + if (CurN[2][2] < 0) { + if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; }; + if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; }; + if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; }; + if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; }; + } + if (CurN[3][2] < 0) { + if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; }; + if (!Q.Line[8]) { DrawLine(Q[5], Q[1]); Q.Line[8] = true; }; + if (!Q.Line[0]) { DrawLine(Q[1], Q[0]); Q.Line[0] = true; }; + if (!Q.Line[11]) { DrawLine(Q[0], Q[4]); Q.Line[11] = true; }; + } + if (CurN[4][2] < 0) { + if (!Q.Line[11]) { DrawLine(Q[4], Q[0]); Q.Line[11] = true; }; + if (!Q.Line[3]) { DrawLine(Q[0], Q[3]); Q.Line[3] = true; }; + if (!Q.Line[10]) { DrawLine(Q[3], Q[7]); Q.Line[10] = true; }; + if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; }; + } + if (CurN[5][2] < 0) { + if (!Q.Line[8]) { DrawLine(Q[1], Q[5]); Q.Line[8] = true; }; + if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; }; + if (!Q.Line[9]) { DrawLine(Q[6], Q[2]); Q.Line[9] = true; }; + if (!Q.Line[1]) { DrawLine(Q[2], Q[1]); Q.Line[1] = true; }; + } + Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false]; + Q.LastPx = 0; +} + +function Loop() { + if (Testing.LoopCount > Testing.LoopMax) return; + var TestingStr = String(Testing.LoopCount); + while (TestingStr.length < 3) TestingStr = "0" + TestingStr; + MTrans = Translate(I, -Q[8].V[0], -Q[8].V[1], -Q[8].V[2]); + MTrans = RotateX(MTrans, 1); + MTrans = RotateY(MTrans, 3); + MTrans = RotateZ(MTrans, 5); + MTrans = Translate(MTrans, Q[8].V[0], Q[8].V[1], Q[8].V[2]); + MQube = MMulti(MTrans, MQube); + var i = 8; + for (; i > -1; i--) { + Q[i].V = VMulti(MTrans, Q[i].V); + } + DrawQube(); + Testing.LoopCount++; + Loop(); +} + +function Init(CubeSize) { + // init/reset vars + Origin.V = [150,150,20,1]; + Testing.LoopCount = 0; + Testing.LoopMax = 50; + Testing.TimeMax = 0; + Testing.TimeAvg = 0; + Testing.TimeMin = 0; + Testing.TimeTemp = 0; + Testing.TimeTotal = 0; + Testing.Init = false; + + // transformation matrix + MTrans = [ + [1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + + // position information of qube + MQube = [ + [1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + + // entity matrix + I = [ + [1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1] + ]; + + // create qube + Q[0] = new CreateP(-CubeSize,-CubeSize, CubeSize); + Q[1] = new CreateP(-CubeSize, CubeSize, CubeSize); + Q[2] = new CreateP( CubeSize, CubeSize, CubeSize); + Q[3] = new CreateP( CubeSize,-CubeSize, CubeSize); + Q[4] = new CreateP(-CubeSize,-CubeSize,-CubeSize); + Q[5] = new CreateP(-CubeSize, CubeSize,-CubeSize); + Q[6] = new CreateP( CubeSize, CubeSize,-CubeSize); + Q[7] = new CreateP( CubeSize,-CubeSize,-CubeSize); + + // center of gravity + Q[8] = new CreateP(0, 0, 0); + + // anti-clockwise edge check + Q.Edge = [[0,1,2],[3,2,6],[7,6,5],[4,5,1],[4,0,3],[1,5,6]]; + + // calculate squad normals + Q.Normal = new Array(); + for (var i = 0; i < Q.Edge.length; i++) Q.Normal[i] = CalcNormal(Q[Q.Edge[i][0]].V, Q[Q.Edge[i][1]].V, Q[Q.Edge[i][2]].V); + + // line drawn ? + Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false]; + + // create line pixels + Q.NumPx = 9 * 2 * CubeSize; + for (var i = 0; i < Q.NumPx; i++) CreateP(0,0,0); + + MTrans = Translate(MTrans, Origin.V[0], Origin.V[1], Origin.V[2]); + MQube = MMulti(MTrans, MQube); + + var i = 0; + for (; i < 9; i++) { + Q[i].V = VMulti(MTrans, Q[i].V); + } + DrawQube(); + Testing.Init = true; + Loop(); +} + +for ( var i = 20; i <= 160; i *= 2 ) { + Init(i); +} + +Q = null; +MTrans = null; +MQube = null; +I = null; +Origin = null; +Testing = null; +LoopTime = null; +DisplArea = null; + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/3d-morph.html b/build/pgo/js-input/sunspider/3d-morph.html new file mode 100644 index 0000000000..aca991d395 --- /dev/null +++ b/build/pgo/js-input/sunspider/3d-morph.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider 3d-morph</title> + +</head> + +<body> +<h3>3d-morph</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +var loops = 15 +var nx = 120 +var nz = 120 + +function morph(a, f) { + var PI2nx = Math.PI * 8/nx + var sin = Math.sin + var f30 = -(50 * sin(f*Math.PI*2)) + + for (var i = 0; i < nz; ++i) { + for (var j = 0; j < nx; ++j) { + a[3*(i*nx+j)+1] = sin((j-1) * PI2nx ) * -f30 + } + } +} + + +var a = Array() +for (var i=0; i < nx*nz*3; ++i) + a[i] = 0 + +for (var i = 0; i < loops; ++i) { + morph(a, i/loops) +} + +testOutput = 0; +for (var i = 0; i < nx; i++) + testOutput += a[3*(i*nx+i)+1]; +a = null; + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/3d-raytrace.html b/build/pgo/js-input/sunspider/3d-raytrace.html new file mode 100644 index 0000000000..2097d4238d --- /dev/null +++ b/build/pgo/js-input/sunspider/3d-raytrace.html @@ -0,0 +1,490 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider 3d-raytrace</title> +</head> + +<body> +<h3>3d-raytrace</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +function createVector(x,y,z) { + return new Array(x,y,z); +} + +function sqrLengthVector(self) { + return self[0] * self[0] + self[1] * self[1] + self[2] * self[2]; +} + +function lengthVector(self) { + return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); +} + +function addVector(self, v) { + self[0] += v[0]; + self[1] += v[1]; + self[2] += v[2]; + return self; +} + +function subVector(self, v) { + self[0] -= v[0]; + self[1] -= v[1]; + self[2] -= v[2]; + return self; +} + +function scaleVector(self, scale) { + self[0] *= scale; + self[1] *= scale; + self[2] *= scale; + return self; +} + +function normaliseVector(self) { + var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); + self[0] /= len; + self[1] /= len; + self[2] /= len; + return self; +} + +function add(v1, v2) { + return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]); +} + +function sub(v1, v2) { + return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]); +} + +function scalev(v1, v2) { + return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]); +} + +function dot(v1, v2) { + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; +} + +function scale(v, scale) { + return [v[0] * scale, v[1] * scale, v[2] * scale]; +} + +function cross(v1, v2) { + return [v1[1] * v2[2] - v1[2] * v2[1], + v1[2] * v2[0] - v1[0] * v2[2], + v1[0] * v2[1] - v1[1] * v2[0]]; + +} + +function normalise(v) { + var len = lengthVector(v); + return [v[0] / len, v[1] / len, v[2] / len]; +} + +function transformMatrix(self, v) { + var vals = self; + var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3]; + var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7]; + var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11]; + return [x, y, z]; +} + +function invertMatrix(self) { + var temp = new Array(16); + var tx = -self[3]; + var ty = -self[7]; + var tz = -self[11]; + for (h = 0; h < 3; h++) + for (v = 0; v < 3; v++) + temp[h + v * 4] = self[v + h * 4]; + for (i = 0; i < 11; i++) + self[i] = temp[i]; + self[3] = tx * self[0] + ty * self[1] + tz * self[2]; + self[7] = tx * self[4] + ty * self[5] + tz * self[6]; + self[11] = tx * self[8] + ty * self[9] + tz * self[10]; + return self; +} + + +// Triangle intersection using barycentric coord method +function Triangle(p1, p2, p3) { + var edge1 = sub(p3, p1); + var edge2 = sub(p2, p1); + var normal = cross(edge1, edge2); + if (Math.abs(normal[0]) > Math.abs(normal[1])) + if (Math.abs(normal[0]) > Math.abs(normal[2])) + this.axis = 0; + else + this.axis = 2; + else + if (Math.abs(normal[1]) > Math.abs(normal[2])) + this.axis = 1; + else + this.axis = 2; + var u = (this.axis + 1) % 3; + var v = (this.axis + 2) % 3; + var u1 = edge1[u]; + var v1 = edge1[v]; + + var u2 = edge2[u]; + var v2 = edge2[v]; + this.normal = normalise(normal); + this.nu = normal[u] / normal[this.axis]; + this.nv = normal[v] / normal[this.axis]; + this.nd = dot(normal, p1) / normal[this.axis]; + var det = u1 * v2 - v1 * u2; + this.eu = p1[u]; + this.ev = p1[v]; + this.nu1 = u1 / det; + this.nv1 = -v1 / det; + this.nu2 = v2 / det; + this.nv2 = -u2 / det; + this.material = [0.7, 0.7, 0.7]; +} + +Triangle.prototype.intersect = function(orig, dir, near, far) { + var u = (this.axis + 1) % 3; + var v = (this.axis + 2) % 3; + var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v]; + var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d; + if (t < near || t > far) + return null; + var Pu = orig[u] + t * dir[u] - this.eu; + var Pv = orig[v] + t * dir[v] - this.ev; + var a2 = Pv * this.nu1 + Pu * this.nv1; + if (a2 < 0) + return null; + var a3 = Pu * this.nu2 + Pv * this.nv2; + if (a3 < 0) + return null; + + if ((a2 + a3) > 1) + return null; + return t; +} + +function Scene(a_triangles) { + this.triangles = a_triangles; + this.lights = []; + this.ambient = [0,0,0]; + this.background = [0.8,0.8,1]; +} +var zero = new Array(0,0,0); + +Scene.prototype.intersect = function(origin, dir, near, far) { + var closest = null; + for (i = 0; i < this.triangles.length; i++) { + var triangle = this.triangles[i]; + var d = triangle.intersect(origin, dir, near, far); + if (d == null || d > far || d < near) + continue; + far = d; + closest = triangle; + } + + if (!closest) + return [this.background[0],this.background[1],this.background[2]]; + + var normal = closest.normal; + var hit = add(origin, scale(dir, far)); + if (dot(dir, normal) > 0) + normal = [-normal[0], -normal[1], -normal[2]]; + + var colour = null; + if (closest.shader) { + colour = closest.shader(closest, hit, dir); + } else { + colour = closest.material; + } + + // do reflection + var reflected = null; + if (colour.reflection > 0.001) { + var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir); + reflected = this.intersect(hit, reflection, 0.0001, 1000000); + if (colour.reflection >= 0.999999) + return reflected; + } + + var l = [this.ambient[0], this.ambient[1], this.ambient[2]]; + for (var i = 0; i < this.lights.length; i++) { + var light = this.lights[i]; + var toLight = sub(light, hit); + var distance = lengthVector(toLight); + scaleVector(toLight, 1.0/distance); + distance -= 0.0001; + if (this.blocked(hit, toLight, distance)) + continue; + var nl = dot(normal, toLight); + if (nl > 0) + addVector(l, scale(light.colour, nl)); + } + l = scalev(l, colour); + if (reflected) { + l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection)); + } + return l; +} + +Scene.prototype.blocked = function(O, D, far) { + var near = 0.0001; + var closest = null; + for (i = 0; i < this.triangles.length; i++) { + var triangle = this.triangles[i]; + var d = triangle.intersect(O, D, near, far); + if (d == null || d > far || d < near) + continue; + return true; + } + + return false; +} + + +// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where +// that somewhere is +function Camera(origin, lookat, up) { + var zaxis = normaliseVector(subVector(lookat, origin)); + var xaxis = normaliseVector(cross(up, zaxis)); + var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis))); + var m = new Array(16); + m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2]; + m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2]; + m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2]; + invertMatrix(m); + m[3] = 0; m[7] = 0; m[11] = 0; + this.origin = origin; + this.directions = new Array(4); + this.directions[0] = normalise([-0.7, 0.7, 1]); + this.directions[1] = normalise([ 0.7, 0.7, 1]); + this.directions[2] = normalise([ 0.7, -0.7, 1]); + this.directions[3] = normalise([-0.7, -0.7, 1]); + this.directions[0] = transformMatrix(m, this.directions[0]); + this.directions[1] = transformMatrix(m, this.directions[1]); + this.directions[2] = transformMatrix(m, this.directions[2]); + this.directions[3] = transformMatrix(m, this.directions[3]); +} + +Camera.prototype.generateRayPair = function(y) { + rays = new Array(new Object(), new Object()); + rays[0].origin = this.origin; + rays[1].origin = this.origin; + rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y)); + rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y)); + return rays; +} + +function renderRows(camera, scene, pixels, width, height, starty, stopy) { + for (var y = starty; y < stopy; y++) { + var rays = camera.generateRayPair(y / height); + for (var x = 0; x < width; x++) { + var xp = x / width; + var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp)); + var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp))); + var l = scene.intersect(origin, dir); + pixels[y][x] = l; + } + } +} + +Camera.prototype.render = function(scene, pixels, width, height) { + var cam = this; + var row = 0; + renderRows(cam, scene, pixels, width, height, 0, height); +} + + + +function raytraceScene() +{ + var startDate = new Date().getTime(); + var numTriangles = 2 * 6; + var triangles = new Array();//numTriangles); + var tfl = createVector(-10, 10, -10); + var tfr = createVector( 10, 10, -10); + var tbl = createVector(-10, 10, 10); + var tbr = createVector( 10, 10, 10); + var bfl = createVector(-10, -10, -10); + var bfr = createVector( 10, -10, -10); + var bbl = createVector(-10, -10, 10); + var bbr = createVector( 10, -10, 10); + + // cube!!! + // front + var i = 0; + + triangles[i++] = new Triangle(tfl, tfr, bfr); + triangles[i++] = new Triangle(tfl, bfr, bfl); + // back + triangles[i++] = new Triangle(tbl, tbr, bbr); + triangles[i++] = new Triangle(tbl, bbr, bbl); + // triangles[i-1].material = [0.7,0.2,0.2]; + // triangles[i-1].material.reflection = 0.8; + // left + triangles[i++] = new Triangle(tbl, tfl, bbl); + // triangles[i-1].reflection = 0.6; + triangles[i++] = new Triangle(tfl, bfl, bbl); + // triangles[i-1].reflection = 0.6; + // right + triangles[i++] = new Triangle(tbr, tfr, bbr); + triangles[i++] = new Triangle(tfr, bfr, bbr); + // top + triangles[i++] = new Triangle(tbl, tbr, tfr); + triangles[i++] = new Triangle(tbl, tfr, tfl); + // bottom + triangles[i++] = new Triangle(bbl, bbr, bfr); + triangles[i++] = new Triangle(bbl, bfr, bfl); + + //Floor!!!! + var green = createVector(0.0, 0.4, 0.0); + var grey = createVector(0.4, 0.4, 0.4); + grey.reflection = 1.0; + var floorShader = function(tri, pos, view) { + var x = ((pos[0]/32) % 2 + 2) % 2; + var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2; + if (x < 1 != z < 1) { + //in the real world we use the fresnel term... + // var angle = 1-dot(view, tri.normal); + // angle *= angle; + // angle *= angle; + // angle *= angle; + //grey.reflection = angle; + return grey; + } else + return green; + } + var ffl = createVector(-1000, -30, -1000); + var ffr = createVector( 1000, -30, -1000); + var fbl = createVector(-1000, -30, 1000); + var fbr = createVector( 1000, -30, 1000); + triangles[i++] = new Triangle(fbl, fbr, ffr); + triangles[i-1].shader = floorShader; + triangles[i++] = new Triangle(fbl, ffr, ffl); + triangles[i-1].shader = floorShader; + + var _scene = new Scene(triangles); + _scene.lights[0] = createVector(20, 38, -22); + _scene.lights[0].colour = createVector(0.7, 0.3, 0.3); + _scene.lights[1] = createVector(-23, 40, 17); + _scene.lights[1].colour = createVector(0.7, 0.3, 0.3); + _scene.lights[2] = createVector(23, 20, 17); + _scene.lights[2].colour = createVector(0.7, 0.7, 0.7); + _scene.ambient = createVector(0.1, 0.1, 0.1); + // _scene.background = createVector(0.7, 0.7, 1.0); + + var size = 30; + var pixels = new Array(); + for (var y = 0; y < size; y++) { + pixels[y] = new Array(); + for (var x = 0; x < size; x++) { + pixels[y][x] = 0; + } + } + + var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0)); + _camera.render(_scene, pixels, size, size); + + return pixels; +} + +function arrayToCanvasCommands(pixels) +{ + var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = ['; + var size = 30; + for (var y = 0; y < size; y++) { + s += "["; + for (var x = 0; x < size; x++) { + s += "[" + pixels[y][x] + "],"; + } + s+= "],"; + } + s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\ +\n\ +\n\ + var size = 30;\n\ + canvas.fillStyle = "red";\n\ + canvas.fillRect(0, 0, size, size);\n\ + canvas.scale(1, -1);\n\ + canvas.translate(0, -size);\n\ +\n\ + if (!canvas.setFillColor)\n\ + canvas.setFillColor = function(r, g, b, a) {\n\ + this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\ + }\n\ +\n\ +for (var y = 0; y < size; y++) {\n\ + for (var x = 0; x < size; x++) {\n\ + var l = pixels[y][x];\n\ + canvas.setFillColor(l[0], l[1], l[2], 1);\n\ + canvas.fillRect(x, y, 1, 1);\n\ + }\n\ +}</scr' + 'ipt>'; + + return s; +} + +testOutput = arrayToCanvasCommands(raytraceScene()); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/access-binary-trees.html b/build/pgo/js-input/sunspider/access-binary-trees.html new file mode 100644 index 0000000000..c2c6cf3d93 --- /dev/null +++ b/build/pgo/js-input/sunspider/access-binary-trees.html @@ -0,0 +1,100 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider access-binary-trees</title> + +</head> + +<body> +<h3>access-binary-trees</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* The Great Computer Language Shootout + http://shootout.alioth.debian.org/ + contributed by Isaac Gouy */ + +function TreeNode(left,right,item){ + this.left = left; + this.right = right; + this.item = item; +} + +TreeNode.prototype.itemCheck = function(){ + if (this.left==null) return this.item; + else return this.item + this.left.itemCheck() - this.right.itemCheck(); +} + +function bottomUpTree(item,depth){ + if (depth>0){ + return new TreeNode( + bottomUpTree(2*item-1, depth-1) + ,bottomUpTree(2*item, depth-1) + ,item + ); + } + else { + return new TreeNode(null,null,item); + } +} + +var ret; + +for ( var n = 4; n <= 7; n += 1 ) { + var minDepth = 4; + var maxDepth = Math.max(minDepth + 2, n); + var stretchDepth = maxDepth + 1; + + var check = bottomUpTree(0,stretchDepth).itemCheck(); + + var longLivedTree = bottomUpTree(0,maxDepth); + for (var depth=minDepth; depth<=maxDepth; depth+=2){ + var iterations = 1 << (maxDepth - depth + minDepth); + + check = 0; + for (var i=1; i<=iterations; i++){ + check += bottomUpTree(i,depth).itemCheck(); + check += bottomUpTree(-i,depth).itemCheck(); + } + } + + ret = longLivedTree.itemCheck(); +} + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/access-fannkuch.html b/build/pgo/js-input/sunspider/access-fannkuch.html new file mode 100644 index 0000000000..02b306ff25 --- /dev/null +++ b/build/pgo/js-input/sunspider/access-fannkuch.html @@ -0,0 +1,116 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider access-fannkuch</title> + +</head> + +<body> +<h3>access-fannkuch</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* The Great Computer Language Shootout + http://shootout.alioth.debian.org/ + contributed by Isaac Gouy */ + +function fannkuch(n) { + var check = 0; + var perm = Array(n); + var perm1 = Array(n); + var count = Array(n); + var maxPerm = Array(n); + var maxFlipsCount = 0; + var m = n - 1; + + for (var i = 0; i < n; i++) perm1[i] = i; + var r = n; + + while (true) { + // write-out the first 30 permutations + if (check < 30){ + var s = ""; + for(var i=0; i<n; i++) s += (perm1[i]+1).toString(); + check++; + } + + while (r != 1) { count[r - 1] = r; r--; } + if (!(perm1[0] == 0 || perm1[m] == m)) { + for (var i = 0; i < n; i++) perm[i] = perm1[i]; + + var flipsCount = 0; + var k; + + while (!((k = perm[0]) == 0)) { + var k2 = (k + 1) >> 1; + for (var i = 0; i < k2; i++) { + var temp = perm[i]; perm[i] = perm[k - i]; perm[k - i] = temp; + } + flipsCount++; + } + + if (flipsCount > maxFlipsCount) { + maxFlipsCount = flipsCount; + for (var i = 0; i < n; i++) maxPerm[i] = perm1[i]; + } + } + + while (true) { + if (r == n) return maxFlipsCount; + var perm0 = perm1[0]; + var i = 0; + while (i < r) { + var j = i + 1; + perm1[i] = perm1[j]; + i = j; + } + perm1[r] = perm0; + + count[r] = count[r] - 1; + if (count[r] > 0) break; + r++; + } + } +} + +var n = 8; +var ret = fannkuch(n); + + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/access-nbody.html b/build/pgo/js-input/sunspider/access-nbody.html new file mode 100644 index 0000000000..4ef73c8552 --- /dev/null +++ b/build/pgo/js-input/sunspider/access-nbody.html @@ -0,0 +1,219 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider access-nbody</title> + +</head> + +<body> +<h3>access-nbody</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* The Great Computer Language Shootout + http://shootout.alioth.debian.org/ + contributed by Isaac Gouy */ + +var PI = 3.141592653589793; +var SOLAR_MASS = 4 * PI * PI; +var DAYS_PER_YEAR = 365.24; + +function Body(x,y,z,vx,vy,vz,mass){ + this.x = x; + this.y = y; + this.z = z; + this.vx = vx; + this.vy = vy; + this.vz = vz; + this.mass = mass; +} + +Body.prototype.offsetMomentum = function(px,py,pz) { + this.vx = -px / SOLAR_MASS; + this.vy = -py / SOLAR_MASS; + this.vz = -pz / SOLAR_MASS; + return this; +} + +function Jupiter(){ + return new Body( + 4.84143144246472090e+00, + -1.16032004402742839e+00, + -1.03622044471123109e-01, + 1.66007664274403694e-03 * DAYS_PER_YEAR, + 7.69901118419740425e-03 * DAYS_PER_YEAR, + -6.90460016972063023e-05 * DAYS_PER_YEAR, + 9.54791938424326609e-04 * SOLAR_MASS + ); +} + +function Saturn(){ + return new Body( + 8.34336671824457987e+00, + 4.12479856412430479e+00, + -4.03523417114321381e-01, + -2.76742510726862411e-03 * DAYS_PER_YEAR, + 4.99852801234917238e-03 * DAYS_PER_YEAR, + 2.30417297573763929e-05 * DAYS_PER_YEAR, + 2.85885980666130812e-04 * SOLAR_MASS + ); +} + +function Uranus(){ + return new Body( + 1.28943695621391310e+01, + -1.51111514016986312e+01, + -2.23307578892655734e-01, + 2.96460137564761618e-03 * DAYS_PER_YEAR, + 2.37847173959480950e-03 * DAYS_PER_YEAR, + -2.96589568540237556e-05 * DAYS_PER_YEAR, + 4.36624404335156298e-05 * SOLAR_MASS + ); +} + +function Neptune(){ + return new Body( + 1.53796971148509165e+01, + -2.59193146099879641e+01, + 1.79258772950371181e-01, + 2.68067772490389322e-03 * DAYS_PER_YEAR, + 1.62824170038242295e-03 * DAYS_PER_YEAR, + -9.51592254519715870e-05 * DAYS_PER_YEAR, + 5.15138902046611451e-05 * SOLAR_MASS + ); +} + +function Sun(){ + return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS); +} + + +function NBodySystem(bodies){ + this.bodies = bodies; + var px = 0.0; + var py = 0.0; + var pz = 0.0; + var size = this.bodies.length; + for (var i=0; i<size; i++){ + var b = this.bodies[i]; + var m = b.mass; + px += b.vx * m; + py += b.vy * m; + pz += b.vz * m; + } + this.bodies[0].offsetMomentum(px,py,pz); +} + +NBodySystem.prototype.advance = function(dt){ + var dx, dy, dz, distance, mag; + var size = this.bodies.length; + + for (var i=0; i<size; i++) { + var bodyi = this.bodies[i]; + for (var j=i+1; j<size; j++) { + var bodyj = this.bodies[j]; + dx = bodyi.x - bodyj.x; + dy = bodyi.y - bodyj.y; + dz = bodyi.z - bodyj.z; + + distance = Math.sqrt(dx*dx + dy*dy + dz*dz); + mag = dt / (distance * distance * distance); + + bodyi.vx -= dx * bodyj.mass * mag; + bodyi.vy -= dy * bodyj.mass * mag; + bodyi.vz -= dz * bodyj.mass * mag; + + bodyj.vx += dx * bodyi.mass * mag; + bodyj.vy += dy * bodyi.mass * mag; + bodyj.vz += dz * bodyi.mass * mag; + } + } + + for (var i=0; i<size; i++) { + var body = this.bodies[i]; + body.x += dt * body.vx; + body.y += dt * body.vy; + body.z += dt * body.vz; + } +} + +NBodySystem.prototype.energy = function(){ + var dx, dy, dz, distance; + var e = 0.0; + var size = this.bodies.length; + + for (var i=0; i<size; i++) { + var bodyi = this.bodies[i]; + + e += 0.5 * bodyi.mass * + ( bodyi.vx * bodyi.vx + + bodyi.vy * bodyi.vy + + bodyi.vz * bodyi.vz ); + + for (var j=i+1; j<size; j++) { + var bodyj = this.bodies[j]; + dx = bodyi.x - bodyj.x; + dy = bodyi.y - bodyj.y; + dz = bodyi.z - bodyj.z; + + distance = Math.sqrt(dx*dx + dy*dy + dz*dz); + e -= (bodyi.mass * bodyj.mass) / distance; + } + } + return e; +} + +var ret; + +for ( var n = 3; n <= 24; n *= 2 ) { + (function(){ + var bodies = new NBodySystem( Array( + Sun(),Jupiter(),Saturn(),Uranus(),Neptune() + )); + var max = n * 100; + + ret = bodies.energy(); + for (var i=0; i<max; i++){ + bodies.advance(0.01); + } + ret = bodies.energy(); + })(); +} + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/access-nsieve.html b/build/pgo/js-input/sunspider/access-nsieve.html new file mode 100644 index 0000000000..c3ed067f11 --- /dev/null +++ b/build/pgo/js-input/sunspider/access-nsieve.html @@ -0,0 +1,88 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider access-nsieve</title> + +</head> + +<body> +<h3>access-nsieve</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// modified by Isaac Gouy + +function pad(number,width){ + var s = number.toString(); + var prefixWidth = width - s.length; + if (prefixWidth>0){ + for (var i=1; i<=prefixWidth; i++) s = " " + s; + } + return s; +} + +function nsieve(m, isPrime){ + var i, k, count; + + for (i=2; i<=m; i++) { isPrime[i] = true; } + count = 0; + + for (i=2; i<=m; i++){ + if (isPrime[i]) { + for (k=i+i; k<=m; k+=i) isPrime[k] = false; + count++; + } + } + return count; +} + +function sieve() { + for (var i = 1; i <= 3; i++ ) { + var m = (1<<i)*10000; + var flags = Array(m+1); + nsieve(m, flags); + } +} + +sieve(); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html b/build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html new file mode 100644 index 0000000000..c40be94ef0 --- /dev/null +++ b/build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider bitops-3bit-bits-in-byte</title> + +</head> + +<body> +<h3>bitops-3bit-bits-in-byte</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com + +// 1 op = 6 ANDs, 3 SHRs, 3 SHLs, 4 assigns, 2 ADDs +// O(1) +function fast3bitlookup(b) { +var c, bi3b = 0xE994; // 0b1110 1001 1001 0100; // 3 2 2 1 2 1 1 0 +c = 3 & (bi3b >> ((b << 1) & 14)); +c += 3 & (bi3b >> ((b >> 2) & 14)); +c += 3 & (bi3b >> ((b >> 5) & 6)); +return c; + +/* +lir4,0xE994; 9 instructions, no memory access, minimal register dependence, 6 shifts, 2 adds, 1 inline assign +rlwinmr5,r3,1,28,30 +rlwinmr6,r3,30,28,30 +rlwinmr7,r3,27,29,30 +rlwnmr8,r4,r5,30,31 +rlwnmr9,r4,r6,30,31 +rlwnmr10,r4,r7,30,31 +addr3,r8,r9 +addr3,r3,r10 +*/ +} + + +function TimeFunc(func) { +var x, y, t; +for(var x=0; x<500; x++) +for(var y=0; y<256; y++) func(y); +} + +TimeFunc(fast3bitlookup); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/bitops-bits-in-byte.html b/build/pgo/js-input/sunspider/bitops-bits-in-byte.html new file mode 100644 index 0000000000..4022c777f4 --- /dev/null +++ b/build/pgo/js-input/sunspider/bitops-bits-in-byte.html @@ -0,0 +1,72 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider bitops-bits-in-byte</title> + +</head> + +<body> +<h3>bitops-bits-in-byte</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com) + + +// 1 op = 2 assigns, 16 compare/branches, 8 ANDs, (0-8) ADDs, 8 SHLs +// O(n) +function bitsinbyte(b) { +var m = 1, c = 0; +while(m<0x100) { +if(b & m) c++; +m <<= 1; +} +return c; +} + +function TimeFunc(func) { +var x, y, t; +for(var x=0; x<350; x++) +for(var y=0; y<256; y++) func(y); +} + +TimeFunc(bitsinbyte); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/bitops-bitwise-and.html b/build/pgo/js-input/sunspider/bitops-bitwise-and.html new file mode 100644 index 0000000000..cca5130400 --- /dev/null +++ b/build/pgo/js-input/sunspider/bitops-bitwise-and.html @@ -0,0 +1,78 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider bitops-bitwise-and</title> + +</head> + +<body> +<h3>bitops-bitwise-and</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +bitwiseAndValue = 4294967296; +for (var i = 0; i < 600000; i++) + bitwiseAndValue = bitwiseAndValue & i; + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/bitops-nsieve-bits.html b/build/pgo/js-input/sunspider/bitops-nsieve-bits.html new file mode 100644 index 0000000000..1849f9da2f --- /dev/null +++ b/build/pgo/js-input/sunspider/bitops-nsieve-bits.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider bitops-nsieve-bits</title> + +</head> + +<body> +<h3>bitops-nsieve-bits</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org +// +// Contributed by Ian Osgood + +function pad(n,width) { + var s = n.toString(); + while (s.length < width) s = ' ' + s; + return s; +} + +function primes(isPrime, n) { + var i, count = 0, m = 10000<<n, size = m+31>>5; + + for (i=0; i<size; i++) isPrime[i] = 0xffffffff; + + for (i=2; i<m; i++) + if (isPrime[i>>5] & 1<<(i&31)) { + for (var j=i+i; j<m; j+=i) + isPrime[j>>5] &= ~(1<<(j&31)); + count++; + } +} + +function sieve() { + for (var i = 4; i <= 4; i++) { + var isPrime = new Array((10000<<i)+31>>5); + primes(isPrime, i); + } +} + +sieve(); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/controlflow-recursive.html b/build/pgo/js-input/sunspider/controlflow-recursive.html new file mode 100644 index 0000000000..9a9651d4b6 --- /dev/null +++ b/build/pgo/js-input/sunspider/controlflow-recursive.html @@ -0,0 +1,75 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider controlflow-recursive</title> + +</head> + +<body> +<h3>controlflow-recursive</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Computer Language Shootout +// http://shootout.alioth.debian.org/ +// contributed by Isaac Gouy + +function ack(m,n){ + if (m==0) { return n+1; } + if (n==0) { return ack(m-1,1); } + return ack(m-1, ack(m,n-1) ); +} + +function fib(n) { + if (n < 2){ return 1; } + return fib(n-2) + fib(n-1); +} + +function tak(x,y,z) { + if (y >= x) return z; + return tak(tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y)); +} + +for ( var i = 3; i <= 5; i++ ) { + ack(3,i); + fib(17.0+i); + tak(3*i+3,2*i+2,i+1); +} + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/crypto-aes.html b/build/pgo/js-input/sunspider/crypto-aes.html new file mode 100644 index 0000000000..12f26b2fb7 --- /dev/null +++ b/build/pgo/js-input/sunspider/crypto-aes.html @@ -0,0 +1,472 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider crypto-aes</title> + +</head> + +<body> +<h3>crypto-aes</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* + * AES Cipher function: encrypt 'input' with Rijndael algorithm + * + * takes byte-array 'input' (16 bytes) + * 2D byte-array key schedule 'w' (Nr+1 x Nb bytes) + * + * applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage + * + * returns byte-array encrypted value (16 bytes) + */ +function Cipher(input, w) { // main Cipher function [§5.1] + var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) + var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys + + var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4] + for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i]; + + state = AddRoundKey(state, w, 0, Nb); + + for (var round=1; round<Nr; round++) { + state = SubBytes(state, Nb); + state = ShiftRows(state, Nb); + state = MixColumns(state, Nb); + state = AddRoundKey(state, w, round, Nb); + } + + state = SubBytes(state, Nb); + state = ShiftRows(state, Nb); + state = AddRoundKey(state, w, Nr, Nb); + + var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4] + for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)]; + return output; +} + + +function SubBytes(s, Nb) { // apply SBox to state S [§5.1.1] + for (var r=0; r<4; r++) { + for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]]; + } + return s; +} + + +function ShiftRows(s, Nb) { // shift row r of state S left by r bytes [§5.1.2] + var t = new Array(4); + for (var r=1; r<4; r++) { + for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy + for (var c=0; c<4; c++) s[r][c] = t[c]; // and copy back + } // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES): + return s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf +} + + +function MixColumns(s, Nb) { // combine bytes of each col of state S [§5.1.3] + for (var c=0; c<4; c++) { + var a = new Array(4); // 'a' is a copy of the current column from 's' + var b = new Array(4); // 'b' is a•{02} in GF(2^8) + for (var i=0; i<4; i++) { + a[i] = s[i][c]; + b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1; + } + // a[n] ^ b[n] is a•{03} in GF(2^8) + s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3 + s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3 + s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3 + s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3 + } + return s; +} + + +function AddRoundKey(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4] + for (var r=0; r<4; r++) { + for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r]; + } + return state; +} + + +function KeyExpansion(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2] + var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) + var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys + var Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys + + var w = new Array(Nb*(Nr+1)); + var temp = new Array(4); + + for (var i=0; i<Nk; i++) { + var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]]; + w[i] = r; + } + + for (var i=Nk; i<(Nb*(Nr+1)); i++) { + w[i] = new Array(4); + for (var t=0; t<4; t++) temp[t] = w[i-1][t]; + if (i % Nk == 0) { + temp = SubWord(RotWord(temp)); + for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t]; + } else if (Nk > 6 && i%Nk == 4) { + temp = SubWord(temp); + } + for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t]; + } + + return w; +} + +function SubWord(w) { // apply SBox to 4-byte word w + for (var i=0; i<4; i++) w[i] = Sbox[w[i]]; + return w; +} + +function RotWord(w) { // rotate 4-byte word w left by one byte + w[4] = w[0]; + for (var i=0; i<4; i++) w[i] = w[i+1]; + return w; +} + + +// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1] +var Sbox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]; + +// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] +var Rcon = [ [0x00, 0x00, 0x00, 0x00], + [0x01, 0x00, 0x00, 0x00], + [0x02, 0x00, 0x00, 0x00], + [0x04, 0x00, 0x00, 0x00], + [0x08, 0x00, 0x00, 0x00], + [0x10, 0x00, 0x00, 0x00], + [0x20, 0x00, 0x00, 0x00], + [0x40, 0x00, 0x00, 0x00], + [0x80, 0x00, 0x00, 0x00], + [0x1b, 0x00, 0x00, 0x00], + [0x36, 0x00, 0x00, 0x00] ]; + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* + * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation + * - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + * for each block + * - outputblock = cipher(counter, key) + * - cipherblock = plaintext xor outputblock + */ +function AESEncryptCtr(plaintext, password, nBits) { + if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys + + // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; + // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1 + var nBytes = nBits/8; // no bytes in key + var pwBytes = new Array(nBytes); + for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff; + var key = Cipher(pwBytes, KeyExpansion(pwBytes)); + key = key.concat(key.slice(0, nBytes-16)); // key is now 16/24/32 bytes long + + // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes, + // block counter in 2nd 8 bytes + var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES + var counterBlock = new Array(blockSize); // block size fixed at 16 bytes / 128 bits (Nb=4) for AES + var nonce = (new Date()).getTime(); // milliseconds since 1-Jan-1970 + + // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops + for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff; + for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; + + // generate key schedule - an expansion of the key into distinct Key Rounds for each round + var keySchedule = KeyExpansion(key); + + var blockCount = Math.ceil(plaintext.length/blockSize); + var ciphertext = new Array(blockCount); // ciphertext as array of strings + + for (var b=0; b<blockCount; b++) { + // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) + // again done in two stages for 32-bit ops + for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff; + for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8) + + var cipherCntr = Cipher(counterBlock, keySchedule); // -- encrypt counter block -- + + // calculate length of final block: + var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1; + + var ct = ''; + for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter byte-by-byte -- + var plaintextByte = plaintext.charCodeAt(b*blockSize+i); + var cipherByte = plaintextByte ^ cipherCntr[i]; + ct += String.fromCharCode(cipherByte); + } + // ct is now ciphertext for this block + + ciphertext[b] = escCtrlChars(ct); // escape troublesome characters in ciphertext + } + + // convert the nonce to a string to go on the front of the ciphertext + var ctrTxt = ''; + for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]); + ctrTxt = escCtrlChars(ctrTxt); + + // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency + return ctrTxt + '-' + ciphertext.join('-'); +} + + +/* + * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation + * + * for each block + * - outputblock = cipher(counter, key) + * - cipherblock = plaintext xor outputblock + */ +function AESDecryptCtr(ciphertext, password, nBits) { + if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys + + var nBytes = nBits/8; // no bytes in key + var pwBytes = new Array(nBytes); + for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff; + var pwKeySchedule = KeyExpansion(pwBytes); + var key = Cipher(pwBytes, pwKeySchedule); + key = key.concat(key.slice(0, nBytes-16)); // key is now 16/24/32 bytes long + + var keySchedule = KeyExpansion(key); + + ciphertext = ciphertext.split('-'); // split ciphertext into array of block-length strings + + // recover nonce from 1st element of ciphertext + var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES + var counterBlock = new Array(blockSize); + var ctrTxt = unescCtrlChars(ciphertext[0]); + for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i); + + var plaintext = new Array(ciphertext.length-1); + + for (var b=1; b<ciphertext.length; b++) { + // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) + for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff; + for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff; + + var cipherCntr = Cipher(counterBlock, keySchedule); // encrypt counter block + + ciphertext[b] = unescCtrlChars(ciphertext[b]); + + var pt = ''; + for (var i=0; i<ciphertext[b].length; i++) { + // -- xor plaintext with ciphered counter byte-by-byte -- + var ciphertextByte = ciphertext[b].charCodeAt(i); + var plaintextByte = ciphertextByte ^ cipherCntr[i]; + pt += String.fromCharCode(plaintextByte); + } + // pt is now plaintext for this block + + plaintext[b-1] = pt; // b-1 'cos no initial nonce block in plaintext + } + + return plaintext.join(''); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +function escCtrlChars(str) { // escape control chars which might cause problems handling ciphertext + return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; }); +} // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker + +function unescCtrlChars(str) { // unescape potentially problematic control characters + return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); }); +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* + * if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead + */ +var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +function encodeBase64(str) { // http://tools.ietf.org/html/rfc4648 + var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc=''; + + str = encodeUTF8(str); // encode multi-byte chars into UTF-8 for byte-array + + do { // pack three octets into four hexets + o1 = str.charCodeAt(i++); + o2 = str.charCodeAt(i++); + o3 = str.charCodeAt(i++); + + bits = o1<<16 | o2<<8 | o3; + + h1 = bits>>18 & 0x3f; + h2 = bits>>12 & 0x3f; + h3 = bits>>6 & 0x3f; + h4 = bits & 0x3f; + + // end of string? index to '=' in b64 + if (isNaN(o3)) h4 = 64; + if (isNaN(o2)) h3 = 64; + + // use hexets to index into b64, and append result to encoded string + enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < str.length); + + return enc; +} + +function decodeBase64(str) { + var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc=''; + + do { // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(str.charAt(i++)); + h2 = b64.indexOf(str.charAt(i++)); + h3 = b64.indexOf(str.charAt(i++)); + h4 = b64.indexOf(str.charAt(i++)); + + bits = h1<<18 | h2<<12 | h3<<6 | h4; + + o1 = bits>>16 & 0xff; + o2 = bits>>8 & 0xff; + o3 = bits & 0xff; + + if (h3 == 64) enc += String.fromCharCode(o1); + else if (h4 == 64) enc += String.fromCharCode(o1, o2); + else enc += String.fromCharCode(o1, o2, o3); + } while (i < str.length); + + return decodeUTF8(enc); // decode UTF-8 byte-array back to Unicode +} + +function encodeUTF8(str) { // encode multi-byte string into utf-8 multiple single-byte characters + str = str.replace( + /[\u0080-\u07ff]/g, // U+0080 - U+07FF = 2-byte chars + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } + ); + str = str.replace( + /[\u0800-\uffff]/g, // U+0800 - U+FFFF = 3-byte chars + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } + ); + return str; +} + +function decodeUTF8(str) { // decode utf-8 encoded string back into multi-byte characters + str = str.replace( + /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars + function(c) { + var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; + return String.fromCharCode(cc); } + ); + str = str.replace( + /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars + function(c) { + var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f; + return String.fromCharCode(cc); } + ); + return str; +} + + +function byteArrayToHexStr(b) { // convert byte array to hex string for displaying test vectors + var s = ''; + for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' '; + return s; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + +var plainText = "ROMEO: But, soft! what light through yonder window breaks?\n\ +It is the east, and Juliet is the sun.\n\ +Arise, fair sun, and kill the envious moon,\n\ +Who is already sick and pale with grief,\n\ +That thou her maid art far more fair than she:\n\ +Be not her maid, since she is envious;\n\ +Her vestal livery is but sick and green\n\ +And none but fools do wear it; cast it off.\n\ +It is my lady, O, it is my love!\n\ +O, that she knew she were!\n\ +She speaks yet she says nothing: what of that?\n\ +Her eye discourses; I will answer it.\n\ +I am too bold, 'tis not to me she speaks:\n\ +Two of the fairest stars in all the heaven,\n\ +Having some business, do entreat her eyes\n\ +To twinkle in their spheres till they return.\n\ +What if her eyes were there, they in her head?\n\ +The brightness of her cheek would shame those stars,\n\ +As daylight doth a lamp; her eyes in heaven\n\ +Would through the airy region stream so bright\n\ +That birds would sing and think it were not night.\n\ +See, how she leans her cheek upon her hand!\n\ +O, that I were a glove upon that hand,\n\ +That I might touch that cheek!\n\ +JULIET: Ay me!\n\ +ROMEO: She speaks:\n\ +O, speak again, bright angel! for thou art\n\ +As glorious to this night, being o'er my head\n\ +As is a winged messenger of heaven\n\ +Unto the white-upturned wondering eyes\n\ +Of mortals that fall back to gaze on him\n\ +When he bestrides the lazy-pacing clouds\n\ +And sails upon the bosom of the air."; + +var password = "O Romeo, Romeo! wherefore art thou Romeo?"; + +var cipherText = AESEncryptCtr(plainText, password, 256); +var decryptedText = AESDecryptCtr(cipherText, password, 256); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/crypto-md5.html b/build/pgo/js-input/sunspider/crypto-md5.html new file mode 100644 index 0000000000..8395107ce6 --- /dev/null +++ b/build/pgo/js-input/sunspider/crypto-md5.html @@ -0,0 +1,336 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider crypto-md5</title> + +</head> + +<body> +<h3>crypto-md5</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ +var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} +function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} +function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} +function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } +function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } +function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function md5_vm_test() +{ + return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length + */ +function core_md5(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) +{ + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); +} +function md5_ff(a, b, c, d, x, s, t) +{ + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) +{ + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) +{ + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) +{ + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Calculate the HMAC-MD5, of a key and some data + */ +function core_hmac_md5(key, data) +{ + var bkey = str2binl(key); + if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); + return core_md5(opad.concat(hash), 512 + 128); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert a string to an array of little-endian words + * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. + */ +function str2binl(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); + return bin; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); + return str; +} + +/* + * Convert an array of little-endian words to a hex string. + */ +function binl2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of little-endian words to a base-64 string + */ +function binl2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} + +var plainText = "Rebellious subjects, enemies to peace,\n\ +Profaners of this neighbour-stained steel,--\n\ +Will they not hear? What, ho! you men, you beasts,\n\ +That quench the fire of your pernicious rage\n\ +With purple fountains issuing from your veins,\n\ +On pain of torture, from those bloody hands\n\ +Throw your mistemper'd weapons to the ground,\n\ +And hear the sentence of your moved prince.\n\ +Three civil brawls, bred of an airy word,\n\ +By thee, old Capulet, and Montague,\n\ +Have thrice disturb'd the quiet of our streets,\n\ +And made Verona's ancient citizens\n\ +Cast by their grave beseeming ornaments,\n\ +To wield old partisans, in hands as old,\n\ +Canker'd with peace, to part your canker'd hate:\n\ +If ever you disturb our streets again,\n\ +Your lives shall pay the forfeit of the peace.\n\ +For this time, all the rest depart away:\n\ +You Capulet; shall go along with me:\n\ +And, Montague, come you this afternoon,\n\ +To know our further pleasure in this case,\n\ +To old Free-town, our common judgment-place.\n\ +Once more, on pain of death, all men depart." + +for (var i = 0; i <4; i++) { + plainText += plainText; +} + +var md5Output = hex_md5(plainText); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/crypto-sha1.html b/build/pgo/js-input/sunspider/crypto-sha1.html new file mode 100644 index 0000000000..01d0b56f37 --- /dev/null +++ b/build/pgo/js-input/sunspider/crypto-sha1.html @@ -0,0 +1,274 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider crypto-sha1</title> + +</head> + +<body> +<h3>crypto-sha1</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ +var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} +function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} +function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} +function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} +function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} +function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha1_vm_test() +{ + return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; +} + +/* + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ +function core_sha1(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for(var j = 0; j < 80; j++) + { + if(j < 16) w[j] = x[i + j]; + else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); + var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + +} + +/* + * Perform the appropriate triplet combination function for the current + * iteration + */ +function sha1_ft(t, b, c, d) +{ + if(t < 20) return (b & c) | ((~b) & d); + if(t < 40) return b ^ c ^ d; + if(t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; +} + +/* + * Determine the appropriate additive constant for the current iteration + */ +function sha1_kt(t) +{ + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; +} + +/* + * Calculate the HMAC-SHA1 of a key and some data + */ +function core_hmac_sha1(key, data) +{ + var bkey = str2binb(key); + if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); + return core_sha1(opad.concat(hash), 512 + 160); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert an 8-bit or 16-bit string to an array of big-endian words + * In 8-bit function, characters >255 have their hi-byte silently ignored. + */ +function str2binb(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); + return bin; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); + return str; +} + +/* + * Convert an array of big-endian words to a hex string. + */ +function binb2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of big-endian words to a base-64 string + */ +function binb2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} + + +var plainText = "Two households, both alike in dignity,\n\ +In fair Verona, where we lay our scene,\n\ +From ancient grudge break to new mutiny,\n\ +Where civil blood makes civil hands unclean.\n\ +From forth the fatal loins of these two foes\n\ +A pair of star-cross'd lovers take their life;\n\ +Whole misadventured piteous overthrows\n\ +Do with their death bury their parents' strife.\n\ +The fearful passage of their death-mark'd love,\n\ +And the continuance of their parents' rage,\n\ +Which, but their children's end, nought could remove,\n\ +Is now the two hours' traffic of our stage;\n\ +The which if you with patient ears attend,\n\ +What here shall miss, our toil shall strive to mend."; + +for (var i = 0; i <4; i++) { + plainText += plainText; +} + +var sha1Output = hex_sha1(plainText); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/date-format-tofte.html b/build/pgo/js-input/sunspider/date-format-tofte.html new file mode 100644 index 0000000000..b8e4773423 --- /dev/null +++ b/build/pgo/js-input/sunspider/date-format-tofte.html @@ -0,0 +1,349 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider date-format-tofte</title> + +</head> + +<body> +<h3>date-format-tofte</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +function arrayExists(array, x) { + for (var i = 0; i < array.length; i++) { + if (array[i] == x) return true; + } + return false; +} + +Date.prototype.formatDate = function (input,time) { + // formatDate : + // a PHP date like function, for formatting date strings + // See: http://www.php.net/date + // + // input : format string + // time : epoch time (seconds, and optional) + // + // if time is not passed, formatting is based on + // the current "this" date object's set time. + // + // supported: + // a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L, + // m, M, n, O, r, s, S, t, U, w, W, y, Y, z + // + // unsupported: + // I (capital i), T, Z + + var switches = ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H", + "i", "j", "l", "L", "m", "M", "n", "O", "r", "s", + "S", "t", "U", "w", "W", "y", "Y", "z"]; + var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"]; + var daysShort = ["Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"]; + var monthsShort = ["Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec"]; + var monthsLong = ["January", "February", "March", "April", + "May", "June", "July", "August", "September", + "October", "November", "December"]; + var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th + "th", "th", "th", "th", "th", "th", "th", // 8th - 14th + "th", "th", "th", "th", "th", "th", "st", // 15th - 21st + "nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th + "th", "th", "st"]; // 29th - 31st + + function a() { + // Lowercase Ante meridiem and Post meridiem + return self.getHours() > 11? "pm" : "am"; + } + function A() { + // Uppercase Ante meridiem and Post meridiem + return self.getHours() > 11? "PM" : "AM"; + } + + function B(){ + // Swatch internet time. code simply grabbed from ppk, + // since I was feeling lazy: + // http://www.xs4all.nl/~ppk/js/beat.html + var off = (self.getTimezoneOffset() + 60)*60; + var theSeconds = (self.getHours() * 3600) + + (self.getMinutes() * 60) + + self.getSeconds() + off; + var beat = Math.floor(theSeconds/86.4); + if (beat > 1000) beat -= 1000; + if (beat < 0) beat += 1000; + if ((""+beat).length == 1) beat = "00"+beat; + if ((""+beat).length == 2) beat = "0"+beat; + return beat; + } + + function d() { + // Day of the month, 2 digits with leading zeros + return new String(self.getDate()).length == 1? + "0"+self.getDate() : self.getDate(); + } + function D() { + // A textual representation of a day, three letters + return daysShort[self.getDay()]; + } + function F() { + // A full textual representation of a month + return monthsLong[self.getMonth()]; + } + function g() { + // 12-hour format of an hour without leading zeros + return self.getHours() > 12? self.getHours()-12 : self.getHours(); + } + function G() { + // 24-hour format of an hour without leading zeros + return self.getHours(); + } + function h() { + // 12-hour format of an hour with leading zeros + if (self.getHours() > 12) { + var s = new String(self.getHours()-12); + return s.length == 1? + "0"+ (self.getHours()-12) : self.getHours()-12; + } else { + var s = new String(self.getHours()); + return s.length == 1? + "0"+self.getHours() : self.getHours(); + } + } + function H() { + // 24-hour format of an hour with leading zeros + return new String(self.getHours()).length == 1? + "0"+self.getHours() : self.getHours(); + } + function i() { + // Minutes with leading zeros + return new String(self.getMinutes()).length == 1? + "0"+self.getMinutes() : self.getMinutes(); + } + function j() { + // Day of the month without leading zeros + return self.getDate(); + } + function l() { + // A full textual representation of the day of the week + return daysLong[self.getDay()]; + } + function L() { + // leap year or not. 1 if leap year, 0 if not. + // the logic should match iso's 8601 standard. + var y_ = Y(); + if ( + (y_ % 4 == 0 && y_ % 100 != 0) || + (y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0) + ) { + return 1; + } else { + return 0; + } + } + function m() { + // Numeric representation of a month, with leading zeros + return self.getMonth() < 9? + "0"+(self.getMonth()+1) : + self.getMonth()+1; + } + function M() { + // A short textual representation of a month, three letters + return monthsShort[self.getMonth()]; + } + function n() { + // Numeric representation of a month, without leading zeros + return self.getMonth()+1; + } + function O() { + // Difference to Greenwich time (GMT) in hours + var os = Math.abs(self.getTimezoneOffset()); + var h = ""+Math.floor(os/60); + var m = ""+(os%60); + h.length == 1? h = "0"+h:1; + m.length == 1? m = "0"+m:1; + return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m; + } + function r() { + // RFC 822 formatted date + var r; // result + // Thu , 21 Dec 2000 + r = D() + ", " + j() + " " + M() + " " + Y() + + // 16 : 01 : 07 +0200 + " " + H() + ":" + i() + ":" + s() + " " + O(); + return r; + } + function S() { + // English ordinal suffix for the day of the month, 2 characters + return daysSuffix[self.getDate()-1]; + } + function s() { + // Seconds, with leading zeros + return new String(self.getSeconds()).length == 1? + "0"+self.getSeconds() : self.getSeconds(); + } + function t() { + + // thanks to Matt Bannon for some much needed code-fixes here! + var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31]; + if (L()==1 && n()==2) return 29; // leap day + return daysinmonths[n()]; + } + function U() { + // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) + return Math.round(self.getTime()/1000); + } + function W() { + // Weeknumber, as per ISO specification: + // http://www.cl.cam.ac.uk/~mgk25/iso-time.html + + // if the day is three days before newyears eve, + // there's a chance it's "week 1" of next year. + // here we check for that. + var beforeNY = 364+L() - z(); + var afterNY = z(); + var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6. + if (beforeNY <= 2 && weekday <= 2-beforeNY) { + return 1; + } + // similarly, if the day is within threedays of newyears + // there's a chance it belongs in the old year. + var ny = new Date("January 1 " + Y() + " 00:00:00"); + var nyDay = ny.getDay()!=0?ny.getDay()-1:6; + if ( + (afterNY <= 2) && + (nyDay >=4) && + (afterNY >= (6-nyDay)) + ) { + // Since I'm not sure we can just always return 53, + // i call the function here again, using the last day + // of the previous year, as the date, and then just + // return that week. + var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00"); + return prevNY.formatDate("W"); + } + + // week 1, is the week that has the first thursday in it. + // note that this value is not zero index. + if (nyDay <= 3) { + // first day of the year fell on a thursday, or earlier. + return 1 + Math.floor( ( z() + nyDay ) / 7 ); + } else { + // first day of the year fell on a friday, or later. + return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 ); + } + } + function w() { + // Numeric representation of the day of the week + return self.getDay(); + } + + function Y() { + // A full numeric representation of a year, 4 digits + + // we first check, if getFullYear is supported. if it + // is, we just use that. ppks code is nice, but wont + // work with dates outside 1900-2038, or something like that + if (self.getFullYear) { + var newDate = new Date("January 1 2001 00:00:00 +0000"); + var x = newDate .getFullYear(); + if (x == 2001) { + // i trust the method now + return self.getFullYear(); + } + } + // else, do this: + // codes thanks to ppk: + // http://www.xs4all.nl/~ppk/js/introdate.html + var x = self.getYear(); + var y = x % 100; + y += (y < 38) ? 2000 : 1900; + return y; + } + function y() { + // A two-digit representation of a year + var y = Y()+""; + return y.substring(y.length-2,y.length); + } + function z() { + // The day of the year, zero indexed! 0 through 366 + var t = new Date("January 1 " + Y() + " 00:00:00"); + var diff = self.getTime() - t.getTime(); + return Math.floor(diff/1000/60/60/24); + } + + var self = this; + if (time) { + // save time + var prevTime = self.getTime(); + self.setTime(time); + } + + var ia = input.split(""); + var ij = 0; + while (ia[ij]) { + if (ia[ij] == "\\") { + // this is our way of allowing users to escape stuff + ia.splice(ij,1); + } else { + if (arrayExists(switches,ia[ij])) { + ia[ij] = eval(ia[ij] + "()"); + } + } + ij++; + } + // reset time, back to what it was + if (prevTime) { + self.setTime(prevTime); + } + return ia.join(""); +} + +var date = new Date("1/1/2007 1:11:11"); + +for (i = 0; i < 500; ++i) { + var shortFormat = date.formatDate("Y-m-d"); + var longFormat = date.formatDate("l, F d, Y g:i:s A"); + date.setTime(date.getTime() + 84266956); +} + + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/date-format-xparb.html b/build/pgo/js-input/sunspider/date-format-xparb.html new file mode 100644 index 0000000000..dd35713d1d --- /dev/null +++ b/build/pgo/js-input/sunspider/date-format-xparb.html @@ -0,0 +1,467 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider date-format-xparb</title> + +</head> + +<body> +<h3>date-format-xparb</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, version 2.1. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + */ + +Date.parseFunctions = {count:0}; +Date.parseRegexes = []; +Date.formatFunctions = {count:0}; + +Date.prototype.dateFormat = function(format) { + if (Date.formatFunctions[format] == null) { + Date.createNewFormat(format); + } + var func = Date.formatFunctions[format]; + return this[func](); +} + +Date.createNewFormat = function(format) { + var funcName = "format" + Date.formatFunctions.count++; + Date.formatFunctions[format] = funcName; + var code = "Date.prototype." + funcName + " = function(){return "; + var special = false; + var ch = ''; + for (var i = 0; i < format.length; ++i) { + ch = format.charAt(i); + if (!special && ch == "\\") { + special = true; + } + else if (special) { + special = false; + code += "'" + String.escape(ch) + "' + "; + } + else { + code += Date.getFormatCode(ch); + } + } + eval(code.substring(0, code.length - 3) + ";}"); +} + +Date.getFormatCode = function(character) { + switch (character) { + case "d": + return "String.leftPad(this.getDate(), 2, '0') + "; + case "D": + return "Date.dayNames[this.getDay()].substring(0, 3) + "; + case "j": + return "this.getDate() + "; + case "l": + return "Date.dayNames[this.getDay()] + "; + case "S": + return "this.getSuffix() + "; + case "w": + return "this.getDay() + "; + case "z": + return "this.getDayOfYear() + "; + case "W": + return "this.getWeekOfYear() + "; + case "F": + return "Date.monthNames[this.getMonth()] + "; + case "m": + return "String.leftPad(this.getMonth() + 1, 2, '0') + "; + case "M": + return "Date.monthNames[this.getMonth()].substring(0, 3) + "; + case "n": + return "(this.getMonth() + 1) + "; + case "t": + return "this.getDaysInMonth() + "; + case "L": + return "(this.isLeapYear() ? 1 : 0) + "; + case "Y": + return "this.getFullYear() + "; + case "y": + return "('' + this.getFullYear()).substring(2, 4) + "; + case "a": + return "(this.getHours() < 12 ? 'am' : 'pm') + "; + case "A": + return "(this.getHours() < 12 ? 'AM' : 'PM') + "; + case "g": + return "((this.getHours() %12) ? this.getHours() % 12 : 12) + "; + case "G": + return "this.getHours() + "; + case "h": + return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + "; + case "H": + return "String.leftPad(this.getHours(), 2, '0') + "; + case "i": + return "String.leftPad(this.getMinutes(), 2, '0') + "; + case "s": + return "String.leftPad(this.getSeconds(), 2, '0') + "; + case "O": + return "this.getGMTOffset() + "; + case "T": + return "this.getTimezone() + "; + case "Z": + return "(this.getTimezoneOffset() * -60) + "; + default: + return "'" + String.escape(character) + "' + "; + } +} + +Date.parseDate = function(input, format) { + if (Date.parseFunctions[format] == null) { + Date.createParser(format); + } + var func = Date.parseFunctions[format]; + return Date[func](input); +} + +Date.createParser = function(format) { + var funcName = "parse" + Date.parseFunctions.count++; + var regexNum = Date.parseRegexes.length; + var currentGroup = 1; + Date.parseFunctions[format] = funcName; + + var code = "Date." + funcName + " = function(input){\n" + + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n" + + "var d = new Date();\n" + + "y = d.getFullYear();\n" + + "m = d.getMonth();\n" + + "d = d.getDate();\n" + + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" + + "if (results && results.length > 0) {" + var regex = ""; + + var special = false; + var ch = ''; + for (var i = 0; i < format.length; ++i) { + ch = format.charAt(i); + if (!special && ch == "\\") { + special = true; + } + else if (special) { + special = false; + regex += String.escape(ch); + } + else { + obj = Date.formatCodeToRegex(ch, currentGroup); + currentGroup += obj.g; + regex += obj.s; + if (obj.g && obj.c) { + code += obj.c; + } + } + } + + code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n" + + "{return new Date(y, m, d, h, i, s);}\n" + + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n" + + "{return new Date(y, m, d, h, i);}\n" + + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n" + + "{return new Date(y, m, d, h);}\n" + + "else if (y > 0 && m >= 0 && d > 0)\n" + + "{return new Date(y, m, d);}\n" + + "else if (y > 0 && m >= 0)\n" + + "{return new Date(y, m);}\n" + + "else if (y > 0)\n" + + "{return new Date(y);}\n" + + "}return null;}"; + + Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$"); + eval(code); +} + +Date.formatCodeToRegex = function(character, currentGroup) { + switch (character) { + case "D": + return {g:0, + c:null, + s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"}; + case "j": + case "d": + return {g:1, + c:"d = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{1,2})"}; + case "l": + return {g:0, + c:null, + s:"(?:" + Date.dayNames.join("|") + ")"}; + case "S": + return {g:0, + c:null, + s:"(?:st|nd|rd|th)"}; + case "w": + return {g:0, + c:null, + s:"\\d"}; + case "z": + return {g:0, + c:null, + s:"(?:\\d{1,3})"}; + case "W": + return {g:0, + c:null, + s:"(?:\\d{2})"}; + case "F": + return {g:1, + c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n", + s:"(" + Date.monthNames.join("|") + ")"}; + case "M": + return {g:1, + c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n", + s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"}; + case "n": + case "m": + return {g:1, + c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n", + s:"(\\d{1,2})"}; + case "t": + return {g:0, + c:null, + s:"\\d{1,2}"}; + case "L": + return {g:0, + c:null, + s:"(?:1|0)"}; + case "Y": + return {g:1, + c:"y = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{4})"}; + case "y": + return {g:1, + c:"var ty = parseInt(results[" + currentGroup + "], 10);\n" + + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", + s:"(\\d{1,2})"}; + case "a": + return {g:1, + c:"if (results[" + currentGroup + "] == 'am') {\n" + + "if (h == 12) { h = 0; }\n" + + "} else { if (h < 12) { h += 12; }}", + s:"(am|pm)"}; + case "A": + return {g:1, + c:"if (results[" + currentGroup + "] == 'AM') {\n" + + "if (h == 12) { h = 0; }\n" + + "} else { if (h < 12) { h += 12; }}", + s:"(AM|PM)"}; + case "g": + case "G": + case "h": + case "H": + return {g:1, + c:"h = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{1,2})"}; + case "i": + return {g:1, + c:"i = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{2})"}; + case "s": + return {g:1, + c:"s = parseInt(results[" + currentGroup + "], 10);\n", + s:"(\\d{2})"}; + case "O": + return {g:0, + c:null, + s:"[+-]\\d{4}"}; + case "T": + return {g:0, + c:null, + s:"[A-Z]{3}"}; + case "Z": + return {g:0, + c:null, + s:"[+-]\\d{1,5}"}; + default: + return {g:0, + c:null, + s:String.escape(character)}; + } +} + +Date.prototype.getTimezone = function() { + return this.toString().replace( + /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace( + /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3"); +} + +Date.prototype.getGMTOffset = function() { + return (this.getTimezoneOffset() > 0 ? "-" : "+") + + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0") + + String.leftPad(this.getTimezoneOffset() % 60, 2, "0"); +} + +Date.prototype.getDayOfYear = function() { + var num = 0; + Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; + for (var i = 0; i < this.getMonth(); ++i) { + num += Date.daysInMonth[i]; + } + return num + this.getDate() - 1; +} + +Date.prototype.getWeekOfYear = function() { + // Skip to Thursday of this week + var now = this.getDayOfYear() + (4 - this.getDay()); + // Find the first Thursday of the year + var jan1 = new Date(this.getFullYear(), 0, 1); + var then = (7 - jan1.getDay() + 4); + document.write(then); + return String.leftPad(((now - then) / 7) + 1, 2, "0"); +} + +Date.prototype.isLeapYear = function() { + var year = this.getFullYear(); + return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year))); +} + +Date.prototype.getFirstDayOfMonth = function() { + var day = (this.getDay() - (this.getDate() - 1)) % 7; + return (day < 0) ? (day + 7) : day; +} + +Date.prototype.getLastDayOfMonth = function() { + var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7; + return (day < 0) ? (day + 7) : day; +} + +Date.prototype.getDaysInMonth = function() { + Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; + return Date.daysInMonth[this.getMonth()]; +} + +Date.prototype.getSuffix = function() { + switch (this.getDate()) { + case 1: + case 21: + case 31: + return "st"; + case 2: + case 22: + return "nd"; + case 3: + case 23: + return "rd"; + default: + return "th"; + } +} + +String.escape = function(string) { + return string.replace(/('|\\)/g, "\\$1"); +} + +String.leftPad = function (val, size, ch) { + var result = new String(val); + if (ch == null) { + ch = " "; + } + while (result.length < size) { + result = ch + result; + } + return result; +} + +Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; +Date.monthNames = + ["January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December"]; +Date.dayNames = + ["Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday"]; +Date.y2kYear = 50; +Date.monthNumbers = { + Jan:0, + Feb:1, + Mar:2, + Apr:3, + May:4, + Jun:5, + Jul:6, + Aug:7, + Sep:8, + Oct:9, + Nov:10, + Dec:11}; +Date.patterns = { + ISO8601LongPattern:"Y-m-d H:i:s", + ISO8601ShortPattern:"Y-m-d", + ShortDatePattern: "n/j/Y", + LongDatePattern: "l, F d, Y", + FullDateTimePattern: "l, F d, Y g:i:s A", + MonthDayPattern: "F d", + ShortTimePattern: "g:i A", + LongTimePattern: "g:i:s A", + SortableDateTimePattern: "Y-m-d\\TH:i:s", + UniversalSortableDateTimePattern: "Y-m-d H:i:sO", + YearMonthPattern: "F, Y"}; + +var date = new Date("1/1/2007 1:11:11"); + +for (i = 0; i < 4000; ++i) { + var shortFormat = date.dateFormat("Y-m-d"); + var longFormat = date.dateFormat("l, F d, Y g:i:s A"); + date.setTime(date.getTime() + 84266956); +} + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/math-cordic.html b/build/pgo/js-input/sunspider/math-cordic.html new file mode 100644 index 0000000000..ec28f9ddde --- /dev/null +++ b/build/pgo/js-input/sunspider/math-cordic.html @@ -0,0 +1,145 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider math-cordic</title> + +</head> + +<body> +<h3>math-cordic</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* + * Copyright (C) Rich Moore. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/////. Start CORDIC + +var AG_CONST = 0.6072529350; + +function FIXED(X) +{ + return X * 65536.0; +} + +function FLOAT(X) +{ + return X / 65536.0; +} + +function DEG2RAD(X) +{ + return 0.017453 * (X); +} + +var Angles = [ + FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502), + FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614), + FIXED(0.223811), FIXED(0.111906), FIXED(0.055953), + FIXED(0.027977) + ]; + + +function cordicsincos() { + var X; + var Y; + var TargetAngle; + var CurrAngle; + var Step; + + X = FIXED(AG_CONST); /* AG_CONST * cos(0) */ + Y = 0; /* AG_CONST * sin(0) */ + + TargetAngle = FIXED(28.027); + CurrAngle = 0; + for (Step = 0; Step < 12; Step++) { + var NewX; + if (TargetAngle > CurrAngle) { + NewX = X - (Y >> Step); + Y = (X >> Step) + Y; + X = NewX; + CurrAngle += Angles[Step]; + } else { + NewX = X + (Y >> Step); + Y = -(X >> Step) + Y; + X = NewX; + CurrAngle -= Angles[Step]; + } + } +} + +///// End CORDIC + +function cordic( runs ) { + var start = new Date(); + + for ( var i = 0 ; i < runs ; i++ ) { + cordicsincos(); + } + + var end = new Date(); + + return end.getTime() - start.getTime(); +} + +cordic(25000); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/math-partial-sums.html b/build/pgo/js-input/sunspider/math-partial-sums.html new file mode 100644 index 0000000000..b78b962489 --- /dev/null +++ b/build/pgo/js-input/sunspider/math-partial-sums.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider math-partial-sums</title> + +</head> + +<body> +<h3>math-partial-sums</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Computer Language Shootout +// http://shootout.alioth.debian.org/ +// contributed by Isaac Gouy + +function partial(n){ + var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0; + var twothirds = 2.0/3.0; + var alt = -1.0; + var k2 = k3 = sk = ck = 0.0; + + for (var k = 1; k <= n; k++){ + k2 = k*k; + k3 = k2*k; + sk = Math.sin(k); + ck = Math.cos(k); + alt = -alt; + + a1 += Math.pow(twothirds,k-1); + a2 += Math.pow(k,-0.5); + a3 += 1.0/(k*(k+1.0)); + a4 += 1.0/(k3 * sk*sk); + a5 += 1.0/(k3 * ck*ck); + a6 += 1.0/k; + a7 += 1.0/k2; + a8 += alt/k; + a9 += alt/(2*k -1); + } +} + +for (var i = 1024; i <= 16384; i *= 2) { + partial(i); +} + + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/math-spectral-norm.html b/build/pgo/js-input/sunspider/math-spectral-norm.html new file mode 100644 index 0000000000..2949f9d780 --- /dev/null +++ b/build/pgo/js-input/sunspider/math-spectral-norm.html @@ -0,0 +1,101 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider math-spectral-norm</title> + +</head> + +<body> +<h3>math-spectral-norm</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by Ian Osgood + +function A(i,j) { + return 1/((i+j)*(i+j+1)/2+i+1); +} + +function Au(u,v) { + for (var i=0; i<u.length; ++i) { + var t = 0; + for (var j=0; j<u.length; ++j) + t += A(i,j) * u[j]; + v[i] = t; + } +} + +function Atu(u,v) { + for (var i=0; i<u.length; ++i) { + var t = 0; + for (var j=0; j<u.length; ++j) + t += A(j,i) * u[j]; + v[i] = t; + } +} + +function AtAu(u,v,w) { + Au(u,w); + Atu(w,v); +} + +function spectralnorm(n) { + var i, u=[], v=[], w=[], vv=0, vBv=0; + for (i=0; i<n; ++i) { + u[i] = 1; v[i] = w[i] = 0; + } + for (i=0; i<10; ++i) { + AtAu(u,v,w); + AtAu(v,u,w); + } + for (i=0; i<n; ++i) { + vBv += u[i]*v[i]; + vv += v[i]*v[i]; + } + return Math.sqrt(vBv/vv); +} + +for (var i = 6; i <= 48; i *= 2) { + spectralnorm(i); +} + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/regexp-dna.html b/build/pgo/js-input/sunspider/regexp-dna.html new file mode 100644 index 0000000000..4a00399b80 --- /dev/null +++ b/build/pgo/js-input/sunspider/regexp-dna.html @@ -0,0 +1,1762 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider regexp-dna</title> + +</head> + +<body> +<h3>regexp-dna</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Computer Language Shootout +// http://shootout.alioth.debian.org/ +// +// contributed by Jesse Millikan +// Base on the Ruby version by jose fco. gonzalez + +var l; +var dnaInput = ">ONE Homo sapiens alu\n\ +GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\n\ +TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\n\ +AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\n\ +GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\n\ +CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\n\ +GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\n\ +GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\n\ +TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\n\ +AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\n\ +GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT\n\ +AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC\n\ +AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG\n\ +GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC\n\ +CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG\n\ +AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT\n\ +TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA\n\ +TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT\n\ +GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG\n\ +TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT\n\ +CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG\n\ +CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG\n\ +TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA\n\ +CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG\n\ +AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG\n\ +GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC\n\ +TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA\n\ +TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA\n\ +GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT\n\ +GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC\n\ +ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT\n\ +TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC\n\ +CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG\n\ +CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG\n\ +GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC\n\ +CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT\n\ +GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC\n\ +GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA\n\ +GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA\n\ +GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA\n\ +GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG\n\ +AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\n\ +CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA\n\ +GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA\n\ +AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC\n\ +GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT\n\ +ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG\n\ +GAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATC\n\ +GCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGC\n\ +GGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGG\n\ +TCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAA\n\ +AAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAG\n\ +GAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACT\n\ +CCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCC\n\ +TGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAG\n\ +ACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGC\n\ +GTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGA\n\ +ACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGA\n\ +CAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCA\n\ +CTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCA\n\ +ACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCG\n\ +CCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG\n\ +AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTC\n\ +CGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCG\n\ +AGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACC\n\ +CCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAG\n\ +CTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAG\n\ +CCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGG\n\ +CCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATC\n\ +ACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAA\n\ +AAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGC\n\ +TGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCC\n\ +ACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGG\n\ +CTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGG\n\ +AGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATT\n\ +AGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAA\n\ +TCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGC\n\ +CTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAA\n\ +TCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAG\n\ +CCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGT\n\ +GGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCG\n\ +GGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAG\n\ +CGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\n\ +GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATG\n\ +GTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGT\n\ +AATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTT\n\ +GCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCT\n\ +CAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCG\n\ +GGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTC\n\ +TCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACT\n\ +CGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAG\n\ +ATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGG\n\ +CGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTG\n\ +AGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATA\n\ +CAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGG\n\ +CAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGC\n\ +ACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCAC\n\ +GCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTC\n\ +GAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCG\n\ +GGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCT\n\ +TGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGG\n\ +CGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCA\n\ +GCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGG\n\ +CCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGC\n\ +GCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGG\n\ +CGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGA\n\ +CTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGG\n\ +CCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAA\n\ +ACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCC\n\ +CAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGT\n\ +GAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAA\n\ +AGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGG\n\ +ATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTAC\n\ +TAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGA\n\ +GGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGC\n\ +GCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGG\n\ +TGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC\n\ +AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAA\n\ +ATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGA\n\ +GAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\n\ +AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTG\n\ +TAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGAC\n\ +CAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGT\n\ +GGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\n\ +CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACA\n\ +GAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACT\n\ +TTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAAC\n\ +ATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCC\n\ +TGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAG\n\ +GTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCG\n\ +TCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAG\n\ +GCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCC\n\ +GTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCT\n\ +ACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCC\n\ +GAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCC\n\ +GGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCAC\n\ +CTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAA\n\ +ATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTG\n\ +AGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCAC\n\ +TGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCT\n\ +CACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAG\n\ +TTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAG\n\ +CCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATC\n\ +GCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCT\n\ +GGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATC\n\ +CCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCC\n\ +TGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGG\n\ +CGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\n\ +AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCG\n\ +AGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGG\n\ +AGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGT\n\ +GAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAA\n\ +TCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGC\n\ +AGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCA\n\ +AAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGG\n\ +CGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTC\n\ +TACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCG\n\ +GGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGAT\n\ +CGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCG\n\ +CGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAG\n\ +GTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACA\n\ +AAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCA\n\ +GGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCAC\n\ +TCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGC\n\ +CTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\n\ +GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGG\n\ +CGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTG\n\ +AACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCG\n\ +ACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGC\n\ +ACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCC\n\ +AACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGC\n\ +GCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCG\n\ +GAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACT\n\ +CCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCC\n\ +GAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAAC\n\ +CCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\n\ +GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGA\n\ +GCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAG\n\ +GCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGAT\n\ +CACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTA\n\ +AAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGG\n\ +CTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGC\n\ +CACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTG\n\ +GCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAG\n\ +GAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAAT\n\ +TAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGA\n\ +ATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAG\n\ +CCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTA\n\ +ATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCA\n\ +GCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGG\n\ +TGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCC\n\ +GGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGA\n\ +GCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTT\n\ +GGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT\n\ +GGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTG\n\ +TAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGT\n\ +TGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTC\n\ +TCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGC\n\ +GGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGT\n\ +CTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTAC\n\ +TCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGA\n\ +GATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGG\n\ +GCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCT\n\ +GAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\n\ +ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAG\n\ +GCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\n\ +CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCA\n\ +CGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTT\n\ +CGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCC\n\ +GGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGC\n\ +TTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGG\n\ +GCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCC\n\ +AGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTG\n\ +GCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCG\n\ +CGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAG\n\ +GCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAG\n\ +ACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAG\n\ +GCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGA\n\ +AACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATC\n\ +CCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAG\n\ +TGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAA\n\ +AAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCG\n\ +GATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTA\n\ +CTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGG\n\ +AGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCG\n\ +CGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCG\n\ +GTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGT\n\ +CAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAA\n\ +AATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGG\n\ +AGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTC\n\ +CAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCT\n\ +GTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\n\ +CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG\n\ +TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAA\n\ +CCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGAC\n\ +AGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCAC\n\ +TTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAA\n\ +CATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGC\n\ +CTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGA\n\ +GGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCC\n\ +GTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGA\n\ +GGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCC\n\ +CGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGC\n\ +TACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGC\n\ +CGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGC\n\ +CGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCA\n\ +CCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\n\ +AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCT\n\ +GAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCA\n\ +CTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGC\n\ +TCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGA\n\ +GTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTA\n\ +GCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAAT\n\ +CGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCC\n\ +TGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAAT\n\ +CCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGC\n\ +CTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTG\n\ +GCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGG\n\ +GAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGC\n\ +GAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\n\ +GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGG\n\ +TGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTA\n\ +ATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTG\n\ +CAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTC\n\ +AAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGG\n\ +GCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCT\n\ +CTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTC\n\ +GGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGA\n\ +TCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGC\n\ +GCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGA\n\ +GGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATAC\n\ +AAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGC\n\ +AGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCA\n\ +CTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACG\n\ +CCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCG\n\ +AGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGG\n\ +GCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTT\n\ +GAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGC\n\ +GACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAG\n\ +CACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGC\n\ +CAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCG\n\ +CGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGC\n\ +GGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGAC\n\ +TCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGC\n\ +CGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAA\n\ +CCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCC\n\ +AGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTG\n\ +AGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA\n\ +GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\n\ +TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\n\ +AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\n\ +GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\n\ +CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\n\ +GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\n\ +GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\n\ +TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\n\ +AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\n\ +GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT\n\ +AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC\n\ +AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG\n\ +GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC\n\ +CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG\n\ +AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT\n\ +TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA\n\ +TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT\n\ +GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG\n\ +TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT\n\ +CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG\n\ +CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG\n\ +TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA\n\ +CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG\n\ +AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG\n\ +GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC\n\ +TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA\n\ +TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA\n\ +GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT\n\ +GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC\n\ +ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT\n\ +TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC\n\ +CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG\n\ +CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG\n\ +GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC\n\ +CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT\n\ +GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC\n\ +GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA\n\ +GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA\n\ +GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA\n\ +GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG\n\ +AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\n\ +CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA\n\ +GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA\n\ +AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC\n\ +GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT\n\ +ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG\n\ +GAGGCTGAGGCAGGAGAATC\n\ +>TWO IUB ambiguity codes\n\ +cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg\n\ +tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa\n\ +NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt\n\ +cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga\n\ +gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa\n\ +HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca\n\ +tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt\n\ +tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt\n\ +acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct\n\ +tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt\n\ +gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa\n\ +accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt\n\ +RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt\n\ +tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag\n\ +cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg\n\ +ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat\n\ +actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg\n\ +YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa\n\ +KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata\n\ +aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa\n\ +aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg\n\ +gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc\n\ +tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK\n\ +tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt\n\ +ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg\n\ +ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa\n\ +BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt\n\ +aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc\n\ +tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc\n\ +cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac\n\ +aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga\n\ +tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga\n\ +aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD\n\ +gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg\n\ +ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV\n\ +taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa\n\ +ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat\n\ +gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg\n\ +gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa\n\ +tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt\n\ +tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt\n\ +taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca\n\ +cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag\n\ +aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt\n\ +cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt\n\ +ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW\n\ +attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag\n\ +ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa\n\ +attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc\n\ +tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta\n\ +aagacYRcaggattHaYgtKtaatgcVcaataMYacccatatcacgWDBtgaatcBaata\n\ +cKcttRaRtgatgaBDacggtaattaaYtataStgVHDtDctgactcaaatKtacaatgc\n\ +gYatBtRaDatHaactgtttatatDttttaaaKVccYcaaccNcBcgHaaVcattHctcg\n\ +attaaatBtatgcaaaaatYMctSactHatacgaWacattacMBgHttcgaatVaaaaca\n\ +BatatVtctgaaaaWtctRacgBMaatSgRgtgtcgactatcRtattaScctaStagKga\n\ +DcWgtYtDDWKRgRtHatRtggtcgaHgggcgtattaMgtcagccaBggWVcWctVaaat\n\ +tcgNaatcKWagcNaHtgaaaSaaagctcYctttRVtaaaatNtataaccKtaRgtttaM\n\ +tgtKaBtRtNaggaSattHatatWactcagtgtactaKctatttgRYYatKatgtccgtR\n\ +tttttatttaatatVgKtttgtatgtNtataRatWYNgtRtHggtaaKaYtKSDcatcKg\n\ +taaYatcSRctaVtSMWtVtRWHatttagataDtVggacagVcgKWagBgatBtaaagNc\n\ +aRtagcataBggactaacacRctKgttaatcctHgDgttKHHagttgttaatgHBtatHc\n\ +DaagtVaBaRccctVgtgDtacRHSctaagagcggWYaBtSaKtHBtaaactYacgNKBa\n\ +VYgtaacttagtVttcttaatgtBtatMtMtttaattaatBWccatRtttcatagVgMMt\n\ +agctStKctaMactacDNYgKYHgaWcgaHgagattacVgtttgtRaSttaWaVgataat\n\ +gtgtYtaStattattMtNgWtgttKaccaatagNYttattcgtatHcWtctaaaNVYKKt\n\ +tWtggcDtcgaagtNcagatacgcattaagaccWctgcagcttggNSgaNcHggatgtVt\n\ +catNtRaaBNcHVagagaaBtaaSggDaatWaatRccaVgggStctDaacataKttKatt\n\ +tggacYtattcSatcttagcaatgaVBMcttDattctYaaRgatgcattttNgVHtKcYR\n\ +aatRKctgtaaacRatVSagctgtWacBtKVatctgttttKcgtctaaDcaagtatcSat\n\ +aWVgcKKataWaYttcccSaatgaaaacccWgcRctWatNcWtBRttYaattataaNgac\n\ +acaatagtttVNtataNaYtaatRaVWKtBatKagtaatataDaNaaaaataMtaagaaS\n\ +tccBcaatNgaataWtHaNactgtcDtRcYaaVaaaaaDgtttRatctatgHtgttKtga\n\ +aNSgatactttcgagWaaatctKaaDaRttgtggKKagcDgataaattgSaacWaVtaNM\n\ +acKtcaDaaatttctRaaVcagNacaScRBatatctRatcctaNatWgRtcDcSaWSgtt\n\ +RtKaRtMtKaatgttBHcYaaBtgatSgaSWaScMgatNtctcctatttctYtatMatMt\n\ +RRtSaattaMtagaaaaStcgVgRttSVaScagtgDtttatcatcatacRcatatDctta\n\ +tcatVRtttataaHtattcYtcaaaatactttgVctagtaaYttagatagtSYacKaaac\n\ +gaaKtaaatagataatSatatgaaatSgKtaatVtttatcctgKHaatHattagaaccgt\n\ +YaaHactRcggSBNgtgctaaBagBttgtRttaaattYtVRaaaattgtaatVatttctc\n\ +ttcatgBcVgtgKgaHaaatattYatagWacNctgaaMcgaattStagWaSgtaaKagtt\n\ +ttaagaDgatKcctgtaHtcatggKttVDatcaaggtYcgccagNgtgcVttttagagat\n\ +gctaccacggggtNttttaSHaNtatNcctcatSaaVgtactgBHtagcaYggYVKNgta\n\ +KBcRttgaWatgaatVtagtcgattYgatgtaatttacDacSctgctaaaStttaWMagD\n\ +aaatcaVYctccgggcgaVtaaWtStaKMgDtttcaaMtVgBaatccagNaaatcYRMBg\n\ +gttWtaaScKttMWtYataRaDBMaDataatHBcacDaaKDactaMgagttDattaHatH\n\ +taYatDtattDcRNStgaatattSDttggtattaaNSYacttcDMgYgBatWtaMagact\n\ +VWttctttgYMaYaacRgHWaattgRtaagcattctMKVStatactacHVtatgatcBtV\n\ +NataaBttYtSttacKgggWgYDtgaVtYgatDaacattYgatggtRDaVDttNactaSa\n\ +MtgNttaacaaSaBStcDctaccacagacgcaHatMataWKYtaYattMcaMtgSttDag\n\ +cHacgatcaHttYaKHggagttccgatYcaatgatRaVRcaagatcagtatggScctata\n\ +ttaNtagcgacgtgKaaWaactSgagtMYtcttccaKtStaacggMtaagNttattatcg\n\ +tctaRcactctctDtaacWYtgaYaSaagaWtNtatttRacatgNaatgttattgWDDcN\n\ +aHcctgaaHacSgaataaRaataMHttatMtgaSDSKatatHHaNtacagtccaYatWtc\n\ +actaactatKDacSaStcggataHgYatagKtaatKagStaNgtatactatggRHacttg\n\ +tattatgtDVagDVaRctacMYattDgtttYgtctatggtKaRSttRccRtaaccttaga\n\ +gRatagSaaMaacgcaNtatgaaatcaRaagataatagatactcHaaYKBctccaagaRa\n\ +BaStNagataggcgaatgaMtagaatgtcaKttaaatgtaWcaBttaatRcggtgNcaca\n\ +aKtttScRtWtgcatagtttWYaagBttDKgcctttatMggNttattBtctagVtacata\n\ +aaYttacacaaRttcYtWttgHcaYYtaMgBaBatctNgcDtNttacgacDcgataaSat\n\ +YaSttWtcctatKaatgcagHaVaacgctgcatDtgttaSataaaaYSNttatagtaNYt\n\ +aDaaaNtggggacttaBggcHgcgtNtaaMcctggtVtaKcgNacNtatVaSWctWtgaW\n\ +cggNaBagctctgaYataMgaagatBSttctatacttgtgtKtaattttRagtDtacata\n\ +tatatgatNHVgBMtKtaKaNttDHaagatactHaccHtcatttaaagttVaMcNgHata\n\ +tKtaNtgYMccttatcaaNagctggacStttcNtggcaVtattactHaSttatgNMVatt\n\ +MMDtMactattattgWMSgtHBttStStgatatRaDaagattttctatMtaaaaaggtac\n\ +taaVttaSacNaatactgMttgacHaHRttgMacaaaatagttaatatWKRgacDgaRta\n\ +tatttattatcYttaWtgtBRtWatgHaaattHataagtVaDtWaVaWtgStcgtMSgaS\n\ +RgMKtaaataVacataatgtaSaatttagtcgaaHtaKaatgcacatcggRaggSKctDc\n\ +agtcSttcccStYtccRtctctYtcaaKcgagtaMttttcRaYDttgttatctaatcata\n\ +NctctgctatcaMatactataggDaHaaSttMtaDtcNatataattctMcStaaBYtaNa\n\ +gatgtaatHagagSttgWHVcttatKaYgDctcttggtgttMcRaVgSgggtagacaata\n\ +aDtaattSaDaNaHaBctattgNtaccaaRgaVtKNtaaYggHtaKKgHcatctWtctDt\n\ +ttctttggSDtNtaStagttataaacaattgcaBaBWggHgcaaaBtYgctaatgaaatW\n\ +cDcttHtcMtWWattBHatcatcaaatctKMagtDNatttWaBtHaaaNgMttaaStagt\n\ +tctctaatDtcRVaYttgttMtRtgtcaSaaYVgSWDRtaatagctcagDgcWWaaaBaa\n\ +RaBctgVgggNgDWStNaNBKcBctaaKtttDcttBaaggBttgaccatgaaaNgttttt\n\ +tttatctatgttataccaaDRaaSagtaVtDtcaWatBtacattaWacttaSgtattggD\n\ +gKaaatScaattacgWcagKHaaccaYcRcaRttaDttRtttHgaHVggcttBaRgtccc\n\ +tDatKaVtKtcRgYtaKttacgtatBtStaagcaattaagaRgBagSaattccSWYttta\n\ +ttVaataNctgHgttaaNBgcVYgtRtcccagWNaaaacaDNaBcaaaaRVtcWMgBagM\n\ +tttattacgDacttBtactatcattggaaatVccggttRttcatagttVYcatYaSHaHc\n\ +ttaaagcNWaHataaaRWtctVtRYtagHtaaaYMataHYtNBctNtKaatattStgaMc\n\ +BtRgctaKtgcScSttDgYatcVtggaaKtaagatWccHccgKYctaNNctacaWctttt\n\ +gcRtgtVcgaKttcMRHgctaHtVaataaDtatgKDcttatBtDttggNtacttttMtga\n\ +acRattaaNagaactcaaaBBVtcDtcgaStaDctgaaaSgttMaDtcgttcaccaaaag\n\ +gWtcKcgSMtcDtatgtttStaaBtatagDcatYatWtaaaBacaKgcaDatgRggaaYc\n\ +taRtccagattDaWtttggacBaVcHtHtaacDacYgtaatataMagaatgHMatcttat\n\ +acgtatttttatattacHactgttataMgStYaattYaccaattgagtcaaattaYtgta\n\ +tcatgMcaDcgggtcttDtKgcatgWRtataatatRacacNRBttcHtBgcRttgtgcgt\n\ +catacMtttBctatctBaatcattMttMYgattaaVYatgDaatVagtattDacaacDMa\n\ +tcMtHcccataagatgBggaccattVWtRtSacatgctcaaggggYtttDtaaNgNtaaB\n\ +atggaatgtctRtaBgBtcNYatatNRtagaacMgagSaSDDSaDcctRagtVWSHtVSR\n\ +ggaacaBVaccgtttaStagaacaMtactccagtttVctaaRaaHttNcttagcaattta\n\ +ttaatRtaaaatctaacDaBttggSagagctacHtaaRWgattcaaBtctRtSHaNtgta\n\ +cattVcaHaNaagtataccacaWtaRtaaVKgMYaWgttaKggKMtKcgWatcaDatYtK\n\ +SttgtacgaccNctSaattcDcatcttcaaaDKttacHtggttHggRRaRcaWacaMtBW\n\ +VHSHgaaMcKattgtaRWttScNattBBatYtaNRgcggaagacHSaattRtttcYgacc\n\ +BRccMacccKgatgaacttcgDgHcaaaaaRtatatDtatYVtttttHgSHaSaatagct\n\ +NYtaHYaVYttattNtttgaaaYtaKttWtctaNtgagaaaNctNDctaaHgttagDcRt\n\ +tatagccBaacgcaRBtRctRtggtaMYYttWtgataatcgaataattattataVaaaaa\n\ +ttacNRVYcaaMacNatRttcKatMctgaagactaattataaYgcKcaSYaatMNctcaa\n\ +cgtgatttttBacNtgatDccaattattKWWcattttatatatgatBcDtaaaagttgaa\n\ +VtaHtaHHtBtataRBgtgDtaataMttRtDgDcttattNtggtctatctaaBcatctaR\n\ +atgNacWtaatgaagtcMNaacNgHttatactaWgcNtaStaRgttaaHacccgaYStac\n\ +aaaatWggaYaWgaattattcMaactcBKaaaRVNcaNRDcYcgaBctKaacaaaaaSgc\n\ +tccYBBHYaVagaatagaaaacagYtctVccaMtcgtttVatcaatttDRtgWctagtac\n\ +RttMctgtDctttcKtWttttataaatgVttgBKtgtKWDaWagMtaaagaaattDVtag\n\ +gttacatcatttatgtcgMHaVcttaBtVRtcgtaYgBRHatttHgaBcKaYWaatcNSc\n\ +tagtaaaaatttacaatcactSWacgtaatgKttWattagttttNaggtctcaagtcact\n\ +attcttctaagKggaataMgtttcataagataaaaatagattatDgcBVHWgaBKttDgc\n\ +atRHaagcaYcRaattattatgtMatatattgHDtcaDtcaaaHctStattaatHaccga\n\ +cNattgatatattttgtgtDtRatagSacaMtcRtcattcccgacacSattgttKaWatt\n\ +NHcaacttccgtttSRtgtctgDcgctcaaMagVtBctBMcMcWtgtaacgactctcttR\n\ +ggRKSttgYtYatDccagttDgaKccacgVatWcataVaaagaataMgtgataaKYaaat\n\ +cHDaacgataYctRtcYatcgcaMgtNttaBttttgatttaRtStgcaacaaaataccVg\n\ +aaDgtVgDcStctatatttattaaaaRKDatagaaagaKaaYYcaYSgKStctccSttac\n\ +agtcNactttDVttagaaagMHttRaNcSaRaMgBttattggtttaRMggatggcKDgWR\n\ +tNaataataWKKacttcKWaaagNaBttaBatMHtccattaacttccccYtcBcYRtaga\n\ +ttaagctaaYBDttaNtgaaaccHcaRMtKtaaHMcNBttaNaNcVcgVttWNtDaBatg\n\ +ataaVtcWKcttRggWatcattgaRagHgaattNtatttctctattaattaatgaDaaMa\n\ +tacgttgggcHaYVaaNaDDttHtcaaHtcVVDgBVagcMacgtgttaaBRNtatRtcag\n\ +taagaggtttaagacaVaaggttaWatctccgtVtaDtcDatttccVatgtacNtttccg\n\ +tHttatKgScBatgtVgHtYcWagcaKtaMYaaHgtaattaSaHcgcagtWNaatNccNN\n\ +YcacgVaagaRacttctcattcccRtgtgtaattagcSttaaStWaMtctNNcSMacatt\n\ +ataaactaDgtatWgtagtttaagaaaattgtagtNagtcaataaatttgatMMYactaa\n\ +tatcggBWDtVcYttcDHtVttatacYaRgaMaacaStaatcRttttVtagaDtcacWat\n\ +ttWtgaaaagaaagNRacDtttStVatBaDNtaactatatcBSMcccaSttccggaMatg\n\ +attaaWatKMaBaBatttgataNctgttKtVaagtcagScgaaaDggaWgtgttttKtWt\n\ +atttHaatgtagttcactaaKMagttSYBtKtaYgaactcagagRtatagtVtatcaaaW\n\ +YagcgNtaDagtacNSaaYDgatBgtcgataacYDtaaactacagWDcYKaagtttatta\n\ +gcatcgagttKcatDaattgattatDtcagRtWSKtcgNtMaaaaacaMttKcaWcaaSV\n\ +MaaaccagMVtaMaDtMaHaBgaacataBBVtaatVYaNSWcSgNtDNaaKacacBttta\n\ +tKtgtttcaaHaMctcagtaacgtcgYtactDcgcctaNgagagcYgatattttaaattt\n\ +ccattttacatttDaaRctattttWctttacgtDatYtttcagacgcaaVttagtaaKaa\n\ +aRtgVtccataBggacttatttgtttaWNtgttVWtaWNVDaattgtatttBaagcBtaa\n\ +BttaaVatcHcaVgacattccNggtcgacKttaaaRtagRtctWagaYggtgMtataatM\n\ +tgaaRttattttgWcttNtDRRgMDKacagaaaaggaaaRStcccagtYccVattaNaaK\n\ +StNWtgacaVtagaagcttSaaDtcacaacgDYacWDYtgtttKatcVtgcMaDaSKStV\n\ +cgtagaaWaKaagtttcHaHgMgMtctataagBtKaaaKKcactggagRRttaagaBaaN\n\ +atVVcgRcKSttDaactagtSttSattgttgaaRYatggttVttaataaHttccaagDtg\n\ +atNWtaagHtgcYtaactRgcaatgMgtgtRaatRaNaacHKtagactactggaatttcg\n\ +ccataacgMctRgatgttaccctaHgtgWaYcactcacYaattcttaBtgacttaaacct\n\ +gYgaWatgBttcttVttcgttWttMcNYgtaaaatctYgMgaaattacNgaHgaacDVVM\n\ +tttggtHtctaaRgtacagacgHtVtaBMNBgattagcttaRcttacaHcRctgttcaaD\n\ +BggttKaacatgKtttYataVaNattccgMcgcgtagtRaVVaattaKaatggttRgaMc\n\ +agtatcWBttNtHagctaatctagaaNaaacaYBctatcgcVctBtgcaaagDgttVtga\n\ +HtactSNYtaaNccatgtgDacgaVtDcgKaRtacDcttgctaagggcagMDagggtBWR\n\ +tttSgccttttttaacgtcHctaVtVDtagatcaNMaVtcVacatHctDWNaataRgcgt\n\ +aVHaggtaaaaSgtttMtattDgBtctgatSgtRagagYtctSaKWaataMgattRKtaa\n\ +catttYcgtaacacattRWtBtcggtaaatMtaaacBatttctKagtcDtttgcBtKYYB\n\ +aKttctVttgttaDtgattttcttccacttgSaaacggaaaNDaattcYNNaWcgaaYat\n\ +tttMgcBtcatRtgtaaagatgaWtgaccaYBHgaatagataVVtHtttVgYBtMctaMt\n\ +cctgaDcYttgtccaaaRNtacagcMctKaaaggatttacatgtttaaWSaYaKttBtag\n\ +DacactagctMtttNaKtctttcNcSattNacttggaacaatDagtattRtgSHaataat\n\ +gccVgacccgatactatccctgtRctttgagaSgatcatatcgDcagWaaHSgctYYWta\n\ +tHttggttctttatVattatcgactaagtgtagcatVgtgHMtttgtttcgttaKattcM\n\ +atttgtttWcaaStNatgtHcaaaDtaagBaKBtRgaBgDtSagtatMtaacYaatYtVc\n\ +KatgtgcaacVaaaatactKcRgtaYtgtNgBBNcKtcttaccttKgaRaYcaNKtactt\n\ +tgagSBtgtRagaNgcaaaNcacagtVtttHWatgttaNatBgtttaatNgVtctgaata\n\ +tcaRtattcttttttttRaaKcRStctcggDgKagattaMaaaKtcaHacttaataataK\n\ +taRgDtKVBttttcgtKaggHHcatgttagHggttNctcgtatKKagVagRaaaggaaBt\n\ +NatttVKcRttaHctaHtcaaatgtaggHccaBataNaNaggttgcWaatctgatYcaaa\n\ +HaatWtaVgaaBttagtaagaKKtaaaKtRHatMaDBtBctagcatWtatttgWttVaaa\n\ +ScMNattRactttgtYtttaaaagtaagtMtaMaSttMBtatgaBtttaKtgaatgagYg\n\ +tNNacMtcNRacMMHcttWtgtRtctttaacaacattattcYaMagBaacYttMatcttK\n\ +cRMtgMNccattaRttNatHaHNaSaaHMacacaVaatacaKaSttHatattMtVatWga\n\ +ttttttaYctttKttHgScWaacgHtttcaVaaMgaacagNatcgttaacaaaaagtaca\n\ +HBNaattgttKtcttVttaaBtctgctacgBgcWtttcaggacacatMgacatcccagcg\n\ +gMgaVKaBattgacttaatgacacacaaaaaatRKaaBctacgtRaDcgtagcVBaacDS\n\ +BHaaaaSacatatacagacRNatcttNaaVtaaaataHattagtaaaaSWccgtatWatg\n\ +gDttaactattgcccatcttHaSgYataBttBaactattBtcHtgatcaataSttaBtat\n\ +KSHYttWggtcYtttBttaataccRgVatStaHaKagaatNtagRMNgtcttYaaSaact\n\ +cagDSgagaaYtMttDtMRVgWKWtgMaKtKaDttttgactatacataatcNtatNaHat\n\ +tVagacgYgatatatttttgtStWaaatctWaMgagaRttRatacgStgattcttaagaD\n\ +taWccaaatRcagcagaaNKagtaaDggcgccBtYtagSBMtactaaataMataBSacRM\n\ +gDgattMMgtcHtcaYDtRaDaacggttDaggcMtttatgttaNctaattaVacgaaMMt\n\ +aatDccSgtattgaRtWWaccaccgagtactMcgVNgctDctaMScatagcgtcaactat\n\ +acRacgHRttgctatttaatgaattataYKttgtaagWgtYttgcHgMtaMattWaWVta\n\ +RgcttgYgttBHtYataSccStBtgtagMgtDtggcVaaSBaatagDttgBgtctttctc\n\ +attttaNagtHKtaMWcYactVcgcgtatMVtttRacVagDaatcttgctBBcRDgcaac\n\ +KttgatSKtYtagBMagaRtcgBattHcBWcaactgatttaatttWDccatttatcgagS\n\ +KaWttataHactaHMttaatHtggaHtHagaatgtKtaaRactgtttMatacgatcaagD\n\ +gatKaDctataMggtHDtggHacctttRtatcttYattttgacttgaaSaataaatYcgB\n\ +aaaaccgNatVBttMacHaKaataagtatKgtcaagactcttaHttcggaattgttDtct\n\ +aaccHttttWaaatgaaatataaaWattccYDtKtaaaacggtgaggWVtctattagtga\n\ +ctattaagtMgtttaagcatttgSgaaatatccHaaggMaaaattttcWtatKctagDtY\n\ +tMcctagagHcactttactatacaaacattaacttaHatcVMYattYgVgtMttaaRtga\n\ +aataaDatcaHgtHHatKcDYaatcttMtNcgatYatgSaMaNtcttKcWataScKggta\n\ +tcttacgcttWaaagNatgMgHtctttNtaacVtgttcMaaRatccggggactcMtttaY\n\ +MtcWRgNctgNccKatcttgYDcMgattNYaRagatHaaHgKctcataRDttacatBatc\n\ +cattgDWttatttaWgtcggagaaaaatacaatacSNtgggtttccttacSMaagBatta\n\ +caMaNcactMttatgaRBacYcYtcaaaWtagctSaacttWgDMHgaggatgBVgcHaDt\n\ +ggaactttggtcNatNgtaKaBcccaNtaagttBaacagtatacDYttcctNgWgcgSMc\n\ +acatStctHatgRcNcgtacacaatRttMggaNKKggataaaSaYcMVcMgtaMaHtgat\n\ +tYMatYcggtcttcctHtcDccgtgRatcattgcgccgatatMaaYaataaYSggatagc\n\ +gcBtNtaaaScaKgttBgagVagttaKagagtatVaactaSacWactSaKatWccaKaaa\n\ +atBKgaaKtDMattttgtaaatcRctMatcaaMagMttDgVatggMaaWgttcgaWatga\n\ +aatttgRtYtattaWHKcRgctacatKttctaccaaHttRatctaYattaaWatVNccat\n\ +NgagtcKttKataStRaatatattcctRWatDctVagttYDgSBaatYgttttgtVaatt\n\ +taatagcagMatRaacttBctattgtMagagattaaactaMatVtHtaaatctRgaaaaa\n\ +aaatttWacaacaYccYDSaattMatgaccKtaBKWBattgtcaagcHKaagttMMtaat\n\ +ttcKcMagNaaKagattggMagaggtaatttYacatcWaaDgatMgKHacMacgcVaaca\n\ +DtaDatatYggttBcgtatgWgaSatttgtagaHYRVacaRtctHaaRtatgaactaata\n\ +tctSSBgggaaHMWtcaagatKgagtDaSatagttgattVRatNtctMtcSaagaSHaat\n\ +aNataataRaaRgattctttaataaagWaRHcYgcatgtWRcttgaaggaMcaataBRaa\n\ +ccagStaaacNtttcaatataYtaatatgHaDgcStcWttaacctaRgtYaRtataKtgM\n\ +ttttatgactaaaatttacYatcccRWtttHRtattaaatgtttatatttgttYaatMca\n\ +RcSVaaDatcgtaYMcatgtagacatgaaattgRtcaaYaaYtRBatKacttataccaNa\n\ +aattVaBtctggacaagKaaYaaatatWtMtatcYaaVNtcgHaactBaagKcHgtctac\n\ +aatWtaDtSgtaHcataHtactgataNctRgttMtDcDttatHtcgtacatcccaggStt\n\ +aBgtcacacWtccNMcNatMVaVgtccDYStatMaccDatggYaRKaaagataRatttHK\n\ +tSaaatDgataaacttaHgttgVBtcttVttHgDacgaKatgtatatNYataactctSat\n\ +atatattgcHRRYttStggaactHgttttYtttaWtatMcttttctatctDtagVHYgMR\n\ +BgtHttcctaatYRttKtaagatggaVRataKDctaMtKBNtMtHNtWtttYcVtattMc\n\ +gRaacMcctNSctcatttaaagDcaHtYccSgatgcaatYaaaaDcttcgtaWtaattct\n\ +cgttttScttggtaatctttYgtctaactKataHacctMctcttacHtKataacacagcN\n\ +RatgKatttttSaaatRYcgDttaMRcgaaattactMtgcgtaagcgttatBtttttaat\n\ +taagtNacatHgttcRgacKcBBtVgatKttcgaBaatactDRgtRtgaNacWtcacYtt\n\ +aaKcgttctHaKttaNaMgWgWaggtctRgaKgWttSttBtDcNtgtttacaaatYcDRt\n\ +gVtgcctattcNtctaaaDMNttttNtggctgagaVctDaacVtWccaagtaacacaNct\n\ +gaScattccDHcVBatcgatgtMtaatBgHaatDctMYgagaatgYWKcctaatNaStHa\n\ +aaKccgHgcgtYaaYtattgtStgtgcaaRtattaKatattagaWVtcaMtBagttatta\n\ +gNaWHcVgcaattttDcMtgtaRHVYtHtctgtaaaaHVtMKacatcgNaatttMatatg\n\ +ttgttactagWYtaRacgataKagYNKcattataNaRtgaacKaYgcaaYYacaNccHat\n\ +MatDcNgtHttRaWttagaaDcaaaaaatagggtKDtStaDaRtaVtHWKNtgtattVct\n\ +SVgRgataDaRaWataBgaagaaKtaataaYgDcaStaNgtaDaaggtattHaRaWMYaY\n\ +aWtggttHYgagVtgtgcttttcaaDKcagVcgttagacNaaWtagtaataDttctggtt\n\ +VcatcataaagtgKaaaNaMtaBBaattaatWaattgctHaVKaSgDaaVKaHtatatat\n\ +HatcatSBagNgHtatcHYMHgttDgtaHtBttWatcgtttaRaattgStKgSKNWKatc\n\ +agDtctcagatttctRtYtBatBgHHtKaWtgYBgacVVWaKtacKcDttKMaKaVcggt\n\ +gttataagaataaHaatattagtataatMHgttYgaRttagtaRtcaaVatacggtcMcg\n\ +agtaaRttacWgactKRYataaaagSattYaWgagatYagKagatgSaagKgttaatMgg\n\ +tataatgttWYttatgagaaacctNVataatHcccKtDctcctaatactggctHggaSag\n\ +gRtKHaWaattcgSatMatttagaggcYtctaMcgctcataSatatgRagacNaaDagga\n\ +VBagaYttKtacNaKgtSYtagttggaWcatcWttaatctatgaVtcgtgtMtatcaYcg\n\ +tRccaaYgDctgcMgtgtWgacWtgataacacgcgctBtgttaKtYDtatDcatcagKaV\n\ +MctaatcttgVcaaRgcRMtDcgattaHttcaNatgaatMtactacVgtRgatggaWttt\n\ +actaaKatgagSaaKggtaNtactVaYtaaKRagaacccacaMtaaMtKtatBcttgtaa\n\ +WBtMctaataaVcDaaYtcRHBtcgttNtaaHatttBNgRStVDattBatVtaagttaYa\n\ +tVattaagaBcacggtSgtVtatttaRattgatgtaHDKgcaatattKtggcctatgaWD\n\ +KRYcggattgRctatNgatacaatMNttctgtcRBYRaaaHctNYattcHtaWcaattct\n\ +BtMKtVgYataatMgYtcagcttMDataVtggRtKtgaatgccNcRttcaMtRgattaac\n\ +attRcagcctHtWMtgtDRagaKaBtgDttYaaaaKatKgatctVaaYaacWcgcatagB\n\ +VtaNtRtYRaggBaaBtgKgttacataagagcatgtRattccacttaccatRaaatgWgD\n\ +aMHaYVgVtaSctatcgKaatatattaDgacccYagtgtaYNaaatKcagtBRgagtcca\n\ +tgKgaaaccBgaagBtgSttWtacgatWHaYatcgatttRaaNRgcaNaKVacaNtDgat\n\ +tgHVaatcDaagcgtatgcNttaDataatcSataaKcaataaHWataBtttatBtcaKtK\n\ +tatagttaDgSaYctacaRatNtaWctSaatatttYaKaKtaccWtatcRagacttaYtt\n\ +VcKgSDcgagaagatccHtaattctSttatggtKYgtMaHagVaBRatttctgtRgtcta\n\ +tgggtaHKgtHacHtSYacgtacacHatacKaaBaVaccaDtatcSaataaHaagagaat\n\ +ScagactataaRttagcaaVcaHataKgDacatWccccaagcaBgagWatctaYttgaaa\n\ +tctVNcYtttWagHcgcgcDcVaaatgttKcHtNtcaatagtgtNRaactttttcaatgg\n\ +WgBcgDtgVgtttctacMtaaataaaRggaaacWaHttaRtNtgctaaRRtVBctYtVta\n\ +tDcattDtgaccYatagatYRKatNYKttNgcctagtaWtgaactaMVaacctgaStttc\n\ +tgaKVtaaVaRKDttVtVctaDNtataaaDtccccaagtWtcgatcactDgYaBcatcct\n\ +MtVtacDaaBtYtMaKNatNtcaNacgDatYcatcgcaRatWBgaacWttKttagYtaat\n\ +tcggttgSWttttDWctttacYtatatWtcatDtMgtBttgRtVDggttaacYtacgtac\n\ +atgaattgaaWcttMStaDgtatattgaDtcRBcattSgaaVBRgagccaaKtttcDgcg\n\ +aSMtatgWattaKttWtgDBMaggBBttBaatWttRtgcNtHcgttttHtKtcWtagHSt\n\ +aacagttgatatBtaWSaWggtaataaMttaKacDaatactcBttcaatatHttcBaaSa\n\ +aatYggtaRtatNtHcaatcaHtagVtgtattataNggaMtcttHtNagctaaaggtaga\n\ +YctMattNaMVNtcKtactBKcaHHcBttaSagaKacataYgctaKaYgttYcgacWVtt\n\ +WtSagcaacatcccHaccKtcttaacgaKttcacKtNtacHtatatRtaaatacactaBt\n\ +ttgaHaRttggttWtatYagcatYDatcggagagcWBataagRtacctataRKgtBgatg\n\ +aDatataSttagBaHtaatNtaDWcWtgtaattacagKttcNtMagtattaNgtctcgtc\n\ +ctcttBaHaKcKccgtRcaaYagSattaagtKataDatatatagtcDtaacaWHcaKttD\n\ +gaaRcgtgYttgtcatatNtatttttatggccHtgDtYHtWgttatYaacaattcaWtat\n\ +NgctcaaaSttRgctaatcaaatNatcgtttaBtNNVtgttataagcaaagattBacgtD\n\ +atttNatttaaaDcBgtaSKgacgtagataatttcHMVNttgttBtDtgtaWKaaRMcKM\n\ +tHtaVtagataWctccNNaSWtVaHatctcMgggDgtNHtDaDttatatVWttgttattt\n\ +aacctttcacaaggaSaDcggttttttatatVtctgVtaacaStDVaKactaMtttaSNa\n\ +gtgaaattaNacttSKctattcctctaSagKcaVttaagNaVcttaVaaRNaHaaHttat\n\ +gtHttgtgatMccaggtaDcgaccgtWgtWMtttaHcRtattgScctatttKtaaccaag\n\ +tYagaHgtWcHaatgccKNRtttagtMYSgaDatctgtgaWDtccMNcgHgcaaacNDaa\n\ +aRaStDWtcaaaaHKtaNBctagBtgtattaactaattttVctagaatggcWSatMaccc\n\ +ttHttaSgSgtgMRcatRVKtatctgaaaccDNatYgaaVHNgatMgHRtacttaaaRta\n\ +tStRtDtatDttYatattHggaBcttHgcgattgaKcKtttcRataMtcgaVttWacatN\n\ +catacctRataDDatVaWNcggttgaHtgtMacVtttaBHtgagVttMaataattatgtt\n\ +cttagtttgtgcDtSatttgBtcaacHattaaBagVWcgcaSYttMgcttacYKtVtatc\n\ +aYaKctgBatgcgggcYcaaaaacgNtctagKBtattatctttKtaVttatagtaYtRag\n\ +NtaYataaVtgaatatcHgcaaRataHtacacatgtaNtgtcgYatWMatttgaactacR\n\ +ctaWtWtatacaatctBatatgYtaagtatgtgtatSttactVatcttYtaBcKgRaSgg\n\ +RaaaaatgcagtaaaWgtaRgcgataatcBaataccgtatttttccatcNHtatWYgatH\n\ +SaaaDHttgctgtccHtggggcctaataatttttctatattYWtcattBtgBRcVttaVM\n\ +RSgctaatMagtYtttaaaaatBRtcBttcaaVtaacagctccSaaSttKNtHtKYcagc\n\ +agaaaccccRtttttaaDcDtaStatccaagcgctHtatcttaDRYgatDHtWcaaaBcW\n\ +gKWHttHataagHacgMNKttMKHccaYcatMVaacgttaKgYcaVaaBtacgcaacttt\n\ +MctaaHaatgtBatgagaSatgtatgSRgHgWaVWgataaatatttccKagVgataattW\n\ +aHNcYggaaatgctHtKtaDtctaaagtMaatVDVactWtSaaWaaMtaHtaSKtcBRaN\n\ +cttStggtBttacNagcatagRgtKtgcgaacaacBcgKaatgataagatgaaaattgta\n\ +ctgcgggtccHHWHaaNacaBttNKtKtcaaBatatgctaHNgtKcDWgtttatNgVDHg\n\ +accaacWctKaaggHttgaRgYaatHcaBacaatgagcaaattactgtaVaaYaDtagat\n\ +tgagNKggtggtgKtWKaatacagDRtatRaMRtgattDggtcaaYRtatttNtagaDtc\n\ +acaaSDctDtataatcgtactaHttatacaatYaacaaHttHatHtgcgatRRttNgcat\n\ +SVtacWWgaaggagtatVMaVaaattScDDKNcaYBYaDatHgtctatBagcaacaagaa\n\ +tgagaaRcataaKNaRtBDatcaaacgcattttttaaBtcSgtacaRggatgtMNaattg\n\ +gatatWtgagtattaaaVctgcaYMtatgatttttYgaHtgtcttaagWBttHttgtctt\n\ +attDtcgtatWtataataSgctaHagcDVcNtaatcaagtaBDaWaDgtttagYctaNcc\n\ +DtaKtaHcttaataacccaRKtacaVaatNgcWRaMgaattatgaBaaagattVYaHMDc\n\ +aDHtcRcgYtcttaaaWaaaVKgatacRtttRRKYgaatacaWVacVcRtatMacaBtac\n\ +tggMataaattttHggNagSctacHgtBagcgtcgtgattNtttgatSaaggMttctttc\n\ +ttNtYNagBtaaacaaatttMgaccttacataattgYtcgacBtVMctgStgMDtagtaR\n\ +ctHtatgttcatatVRNWataDKatWcgaaaaagttaaaagcacgHNacgtaatctttMR\n\ +tgacttttDacctataaacgaaatatgattagaactccSYtaBctttaataacWgaaaYa\n\ +tagatgWttcatKtNgatttttcaagHtaYgaaRaDaagtaggagcttatVtagtctttc\n\ +attaaaatcgKtattaRttacagVaDatgcatVgattgggtctttHVtagKaaRBtaHta\n\ +aggccccaaaaKatggtttaMWgtBtaaacttcactttKHtcgatctccctaYaBacMgt\n\ +cttBaBaNgcgaaacaatctagtHccHtKttcRtRVttccVctttcatacYagMVtMcag\n\ +aMaaacaataBctgYtaatRaaagattaaccatVRatHtaRagcgcaBcgDttStttttc\n\ +VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa\n\ +catYaRRcVRHctKtcgacKttaaVctaDaatgttMggRcWaacttttHaDaKaDaBctg\n\ +taggcgtttaHBccatccattcNHtDaYtaataMttacggctNVaacDattgatatttta\n\ +cVttSaattacaaRtataNDgacVtgaacataVRttttaDtcaaacataYDBtttaatBa\n\ +DtttYDaDaMccMttNBttatatgagaaMgaNtattHccNataattcaHagtgaaggDga\n\ +tgtatatatgYatgaStcataaBStWacgtcccataRMaaDattggttaaattcMKtctM\n\ +acaBSactcggaatDDgatDgcWctaacaccgggaVcacWKVacggtaNatatacctMta\n\ +tgatagtgcaKagggVaDtgtaacttggagtcKatatcgMcttRaMagcattaBRaStct\n\ +YSggaHYtacaactMBaagDcaBDRaaacMYacaHaattagcattaaaHgcgctaaggSc\n\ +cKtgaaKtNaBtatDDcKBSaVtgatVYaagVtctSgMctacgttaacWaaattctSgtD\n\ +actaaStaaattgcagBBRVctaatatacctNttMcRggctttMttagacRaHcaBaacV\n\ +KgaataHttttMgYgattcYaNRgttMgcVaaacaVVcDHaatttgKtMYgtatBtVVct\n\ +WgVtatHtacaaHttcacgatagcagtaaNattBatatatttcVgaDagcggttMaagtc\n\ +ScHagaaatgcYNggcgtttttMtStggtRatctacttaaatVVtBacttHNttttaRca\n\ +aatcacagHgagagtMgatcSWaNRacagDtatactaaDKaSRtgattctccatSaaRtt\n\ +aaYctacacNtaRtaactggatgaccYtacactttaattaattgattYgttcagDtNKtt\n\ +agDttaaaaaaaBtttaaNaYWKMBaaaacVcBMtatWtgBatatgaacVtattMtYatM\n\ +NYDKNcKgDttDaVtaaaatgggatttctgtaaatWtctcWgtVVagtcgRgacttcccc\n\ +taDcacagcRcagagtgtWSatgtacatgttaaSttgtaaHcgatgggMagtgaacttat\n\ +RtttaVcaccaWaMgtactaatSSaHtcMgaaYtatcgaaggYgggcgtgaNDtgttMNg\n\ +aNDMtaattcgVttttaacatgVatgtWVMatatcaKgaaattcaBcctccWcttgaaWH\n\ +tWgHtcgNWgaRgctcBgSgaattgcaaHtgattgtgNagtDttHHgBttaaWcaaWagc\n\ +aSaHHtaaaVctRaaMagtaDaatHtDMtcVaWMtagSagcttHSattaacaaagtRacM\n\ +tRtctgttagcMtcaBatVKtKtKacgagaSNatSactgtatatcBctgagVtYactgta\n\ +aattaaaggcYgDHgtaacatSRDatMMccHatKgttaacgactKtgKagtcttcaaHRV\n\ +tccttKgtSataatttacaactggatDNgaacttcaRtVaagDcaWatcBctctHYatHa\n\ +DaaatttagYatSatccaWtttagaaatVaacBatHcatcgtacaatatcgcNYRcaata\n\ +YaRaYtgattVttgaatgaVaactcRcaNStgtgtattMtgaggtNttBaDRcgaaaagc\n\ +tNgBcWaWgtSaDcVtgVaatMKBtttcgtttctaaHctaaagYactgMtatBDtcStga\n\ +ccgtSDattYaataHctgggaYYttcggttaWaatctggtRagWMaDagtaacBccacta\n\ +cgHWMKaatgatWatcctgHcaBaSctVtcMtgtDttacctaVgatYcWaDRaaaaRtag\n\ +atcgaMagtggaRaWctctgMgcWttaagKBRtaaDaaWtctgtaagYMttactaHtaat\n\ +cttcataacggcacBtSgcgttNHtgtHccatgttttaaagtatcgaKtMttVcataYBB\n\ +aKtaMVaVgtattNDSataHcagtWMtaggtaSaaKgttgBtVtttgttatcatKcgHac\n\ +acRtctHatNVagSBgatgHtgaRaSgttRcctaacaaattDNttgacctaaYtBgaaaa\n\ +tagttattactcttttgatgtNNtVtgtatMgtcttRttcatttgatgacacttcHSaaa\n\ +ccaWWDtWagtaRDDVNacVaRatgttBccttaatHtgtaaacStcVNtcacaSRttcYa\n\ +gacagaMMttttgMcNttBcgWBtactgVtaRttctccaaYHBtaaagaBattaYacgat\n\ +ttacatctgtaaMKaRYtttttactaaVatWgctBtttDVttctggcDaHaggDaagtcg\n\ +aWcaagtagtWttHtgKtVataStccaMcWcaagataagatcactctHatgtcYgaKcat\n\ +cagatactaagNSStHcctRRNtattgtccttagttagMVgtatagactaactctVcaat\n\ +MctgtttgtgttgccttatWgtaBVtttctggMcaaKgDWtcgtaaYStgSactatttHg\n\ +atctgKagtagBtVacRaagRtMctatgggcaaaKaaaatacttcHctaRtgtDcttDat\n\ +taggaaatttcYHaRaaBttaatggcacKtgctHVcaDcaaaVDaaaVcgMttgtNagcg\n\ +taDWgtcgttaatDgKgagcSatatcSHtagtagttggtgtHaWtaHKtatagctgtVga\n\ +ttaBVaatgaataagtaatVatSttaHctttKtttgtagttaccttaatcgtagtcctgB\n\ +cgactatttVcMacHaaaggaatgDatggKtaHtgStatattaaSagctWcctccRtata\n\ +BaDYcgttgcNaagaggatRaaaYtaWgNtSMcaatttactaacatttaaWttHtatBat\n\ +tgtcgacaatNgattgcNgtMaaaKaBDattHacttggtRtttaYaacgVactBtaBaKt\n\ +gBttatgVttgtVttcaatcWcNctDBaaBgaDHacBttattNtgtDtatttVSaaacag\n\ +gatgcRatSgtaSaNtgBatagttcHBgcBBaaattaHgtDattatDaKaatBaaYaaMa\n\ +ataaataKtttYtagtBgMatNcatgtttgaNagtgttgtgKaNaSagtttgaSMaYBca\n\ +aaacDStagttVacaaaaactaaWttBaagtctgtgcgtMgtaattctcctacctcaNtt\n\ +taaccaaaaVtBcacataacaccccBcWMtatVtggaatgaWtcaaWaaaaaaaaWtDta\n\ +atatRcctDWtcctaccMtVVatKttaWaaKaaatataaagScHBagaggBaSMtaWaVt\n\ +atattactSaaaKNaactatNatccttgaYctattcaaaVgatttYHcRagattttaSat\n\ +aggttattcVtaaagaKgtattattKtRttNcggcRgtgtgtWYtaacHgKatKgatYta\n\ +cYagDtWcHBDctctgRaYKaYagcactKcacSaRtBttttBHKcMtNtcBatttatttt\n\ +tgSatVgaaagaWtcDtagDatatgMacaacRgatatatgtttgtKtNRaatatNatgYc\n\ +aHtgHataacKtgagtagtaacYttaNccaaatHcacaacaVDtagtaYtccagcattNt\n\ +acKtBtactaaagaBatVtKaaHBctgStgtBgtatgaSNtgDataaccctgtagcaBgt\n\ +gatcttaDataStgaMaccaSBBgWagtacKcgattgaDgNNaaaacacagtSatBacKD\n\ +gcgtataBKcatacactaSaatYtYcDaactHttcatRtttaatcaattataRtttgtaa\n\ +gMcgNttcatcBtYBagtNWNMtSHcattcRctttttRWgaKacKttgggagBcgttcgc\n\ +MaWHtaatactgtctctatttataVgtttaBScttttaBMaNaatMacactYtBMggtHa\n\ +cMagtaRtctgcatttaHtcaaaatttgagKtgNtactBacaHtcgtatttctMaSRagc\n\ +agttaatgtNtaaattgagagWcKtaNttagVtacgatttgaatttcgRtgtWcVatcgt\n\ +taaDVctgtttBWgaccagaaagtcSgtVtatagaBccttttcctaaattgHtatcggRa\n\ +ttttcaaggcYSKaagWaWtRactaaaacccBatMtttBaatYtaagaactSttcgaaSc\n\ +aatagtattgaccaagtgttttctaacatgtttNVaatcaaagagaaaNattaaRtttta\n\ +VaaaccgcaggNMtatattVctcaagaggaacgBgtttaacaagttcKcYaatatactaa\n\ +ccBaaaSggttcNtattctagttRtBacgScVctcaatttaatYtaaaaaaatgSaatga\n\ +tagaMBRatgRcMcgttgaWHtcaVYgaatYtaatctttYttatRaWtctgBtDcgatNa\n\ +tcKaBaDgatgtaNatWKctccgatattaacattNaaacDatgBgttctgtDtaaaMggt\n\ +gaBaSHataacgccSctaBtttaRBtcNHcDatcDcctagagtcRtaBgWttDRVHagat\n\ +tYatgtatcWtaHtttYcattWtaaagtctNgtStggRNcgcggagSSaaagaaaatYcH\n\ +DtcgctttaatgYcKBVSgtattRaYBaDaaatBgtatgaHtaaRaRgcaSWNtagatHa\n\ +acttNctBtcaccatctMcatattccaSatttgcgaDagDgtatYtaaaVDtaagtttWV\n\ +aagtagYatRttaagDcNgacKBcScagHtattatcDaDactaaaaaYgHttBcgaDttg\n\ +gataaaKSRcBMaBcgaBSttcWtgNBatRaccgattcatttataacggHVtaattcaca\n\ +agagVttaaRaatVVRKcgWtVgacctgDgYaaHaWtctttcacMagggatVgactagMa\n\ +aataKaaNWagKatagNaaWtaaaatttgaattttatttgctaaVgaHatBatcaaBWcB\n\ +gttcMatcgBaaNgttcgSNaggSaRtttgHtRtattaNttcDcatSaVttttcgaaaaa\n\ +ttgHatctaRaggSaNatMDaaatDcacgattttagaHgHaWtYgattaatHNSttatMS\n\ +gggNtcKtYatRggtttgtMWVtttaYtagcagBagHaYagttatatggtBacYcattaR\n\ +SataBatMtttaaatctHcaaaSaaaagttNSaaWcWRccRtKaagtBWtcaaattSttM\n\ +tattggaaaccttaacgttBtWatttatatWcDaatagattcctScacctaagggRaaYt\n\ +aNaatgVtBcttaaBaacaMVaaattatStYgRcctgtactatcMcVKatttcgSgatRH\n\ +MaaaHtagtaaHtVgcaaataatatcgKKtgccaatBNgaaWcVttgagttaKatagttc\n\ +aggKDatDtattgaKaVcaKtaataDataataHSaHcattagttaatRVYcNaHtaRcaa\n\ +ggtNHcgtcaaccaBaaagYtHWaaaRcKgaYaaDttgcWYtataRgaatatgtYtgcKt\n\ +aNttWacatYHctRaDtYtattcBttttatcSataYaYgttWaRagcacHMgtttHtYtt\n\ +YaatcggtatStttcgtRSattaaDaKMaatatactaNBaWgctacacYtgaYVgtgHta\n\ +aaRaaRgHtagtWattataaaSDaaWtgMattatcgaaaagtaYRSaWtSgNtBgagcRY\n\ +aMDtactaacttaWgtatctagacaagNtattHggataatYttYatcataDcgHgttBtt\n\ +ctttVttgccgaaWtaaaacgKgtatctaaaaaNtccDtaDatBMaMggaatNKtatBaa\n\ +atVtccRaHtaSacataHattgtttKVYattcataVaattWtcgtgMttcttKtgtctaa\n\ +cVtatctatatBRataactcgKatStatattcatHHRttKtccaacgtgggtgRgtgaMt\n\ +attattggctatcgtgacMtRcBDtcttgtactaatRHttttaagatcgVMDStattatY\n\ +BtttDttgtBtNttgRcMtYtgBacHaWaBaatDKctaagtgaaactaatgRaaKgatcc\n\ +aagNaaaatattaggWNtaagtatacttttKcgtcggSYtcttgRctataYcttatataa\n\ +agtatattaatttataVaacacaDHatctatttttKYVatHRactttaBHccaWagtact\n\ +BtcacgaVgcgttRtttttttSVgtSagtBaaattctgaHgactcttgMcattttagVta\n\ +agaattHctHtcaDaaNtaacRggWatagttcgtSttgaDatcNgNagctagDgatcNtt\n\ +KgttgtaDtctttRaaYStRatDtgMggactSttaDtagSaVtBDttgtDgccatcacaM\n\ +attaaaMtNacaVcgSWcVaaDatcaHaatgaattaMtatccVtctBtaattgtWattat\n\ +BRcWcaatgNNtactWYtDaKttaaatcactcagtRaaRgatggtKgcgccaaHgaggat\n\ +StattYcaNMtcaBttacttatgagDaNtaMgaaWtgtttcttctaHtMNgttatctaWW\n\ +atMtBtaaatagDVatgtBYtatcggcttaagacMRtaHScgatatYgRDtcattatSDa\n\ +HggaaataNgaWSRRaaaBaatagBattaDctttgHWNttacaataaaaaaatacggttt\n\ +gHgVtaHtWMttNtBtctagtMcgKMgHgYtataHaNagWtcaacYattaataYRgtaWK\n\ +gaBctataaccgatttaHaNBRaRaMtccggtNgacMtctcatttgcaattcWgMactta\n\ +caaDaaNtactWatVtttagccttMaatcagVaagtctVaaDaBtattaattaYtNaYtg\n\ +gattaKtaKctYaMtattYgatattataatKtVgDcttatatNBtcgttgtStttttMag\n\ +aggttaHYSttcKgtcKtDNtataagttataagSgttatDtRttattgttttSNggRtca\n\ +aKMNatgaatattgtBWtaMacctgggYgaSgaagYataagattacgagaatBtggtRcV\n\ +HtgYggaDgaYaKagWagctatagacgaaHgtWaNgacttHRatVaWacKYtgRVNgVcS\n\ +gRWctacatcKSactctgWYtBggtataagcttNRttVtgRcaWaaatDMatYattaact\n\ +ttcgaagRatSctgccttgcRKaccHtttSNVagtagHagBagttagaccaRtataBcca\n\ +taatSHatRtcHagacBWatagcaMtacaRtgtgaaBatctKRtScttccaNaatcNgta\n\ +atatWtcaMgactctBtWtaaNactHaaaaRctcgcatggctMcaaNtcagaaaaacaca\n\ +gtggggWttRttagtaagaVctVMtcgaatcttcMaaaHcaHBttcgattatgtcaDagc\n\ +YRtBtYcgacMgtDcagcgaNgttaataatagcagKYYtcgtaBtYctMaRtaRtDagaa\n\ +aacacatgYaBttgattattcgaaNttBctSataaMataWRgaHtttccgtDgaYtatgg\n\ +tDgHKgMtatttVtMtVagttaRatMattRagataaccctKctMtSttgaHagtcStcta\n\ +tttccSagatgttccacgaggYNttHRacgattcDatatDcataaaatBBttatcgaHtN\n\ +HaaatatDNaggctgaNcaaggagttBttMgRagVatBcRtaWgatgBtSgaKtcgHttt\n\ +gaatcaaDaHttcSBgHcagtVaaSttDcagccgttNBtgttHagYtattctttRWaaVt\n\ +SttcatatKaaRaaaNacaVtVctMtSDtDtRHRcgtaatgctcttaaatSacacaatcg\n\ +HattcaWcttaaaatHaaatcNctWttaNMcMtaKctVtcctaagYgatgatcYaaaRac\n\ +tctaRDaYagtaacgtDgaggaaatctcaaacatcaScttcKttNtaccatNtaNataca\n\ +tttHaaDHgcaDatMWaaBttcRggctMaagctVYcacgatcaDttatYtaatcKatWat\n\ +caatVYtNagatttgattgaYttttYgacttVtcKaRagaaaHVgDtaMatKYagagttN\n\ +atWttaccNtYtcDWgSatgaRgtMatgKtcgacaagWtacttaagtcgKtgatccttNc\n\ +ttatagMatHVggtagcgHctatagccctYttggtaattKNaacgaaYatatVctaataM\n\ +aaaYtgVtcKaYtaataacagaatHcacVagatYWHttagaaSMaatWtYtgtaaagNaa\n\ +acaVgaWtcacNWgataNttcaSagctMDaRttgNactaccgataMaaatgtttattDtc\n\ +aagacgctDHYYatggttcaagccNctccttcMctttagacBtaaWtaWVHggaaaaNat\n\ +ttaDtDtgctaaHHtMtatNtMtagtcatttgcaaaRatacagRHtatDNtgtDgaatVg\n\ +tVNtcaaatYBMaaaagcaKgtgatgatMgWWMaHttttMgMagatDtataaattaacca\n\ +actMtacataaattgRataatacgBtKtaataattRgtatDagDtcRDacctatRcagag\n\ +cSHatNtcaScNtttggacNtaaggaccgtgKNttgttNcttgaaRgYgRtNtcagttBc\n\ +ttttcHtKtgcttYaaNgYagtaaatgaatggWaMattBHtatctatSgtcYtgcHtaat\n\ +tHgaaMtHcagaaSatggtatgccaHBtYtcNattWtgtNgctttaggtttgtWatNtgH\n\ +tgcDttactttttttgcNtactKtWRaVcttcatagtgSNKaNccgaataaBttataata\n\ +YtSagctttaaatSttggctaaKSaatRccgWHgagDttaaatcatgagMtcgagtVtaD\n\ +ggaBtatttgDacataaacgtagYRagBWtgDStKDgatgaagttcattatttaKWcata\n\ +aatWRgatataRgttRacaaNKttNtKagaaYaStaactScattattaacgatttaaatg\n\ +DtaattagatHgaYataaactatggggatVHtgccgtNgatNYcaStRtagaccacWcaM\n\ +tatRagHgVactYtWHtcttcatgatWgagaKggagtatgaWtDtVtNaNtcgYYgtaaa\n\ +ctttaDtBactagtaDctatagtaatatttatatataacgHaaaRagKattSagttYtSt\n\ +>THREE Homo sapiens frequency\n\ +agagagacgatgaaaattaatcgtcaatacgctggcgaacactgagggggacccaatgct\n\ +cttctcggtctaaaaaggaatgtgtcagaaattggtcagttcaaaagtagaccggatctt\n\ +tgcggagaacaattcacggaacgtagcgttgggaaatatcctttctaccacacatcggat\n\ +tttcgccctctcccattatttattgtgttctcacatagaattattgtttagacatccctc\n\ +gttgtatggagagttgcccgagcgtaaaggcataatccatataccgccgggtgagtgacc\n\ +tgaaattgtttttagttgggatttcgctatggattagcttacacgaagagattctaatgg\n\ +tactataggataattataatgctgcgtggcgcagtacaccgttacaaacgtcgttcgcat\n\ +atgtggctaacacggtgaaaatacctacatcgtatttgcaatttcggtcgtttcatagag\n\ +cgcattgaattactcaaaaattatatatgttgattatttgattagactgcgtggaaagaa\n\ +ggggtactcaagccatttgtaaaagctgcatctcgcttaagtttgagagcttacattagt\n\ +ctatttcagtcttctaggaaatgtctgtgtgagtggttgtcgtccataggtcactggcat\n\ +atgcgattcatgacatgctaaactaagaaagtagattactattaccggcatgcctaatgc\n\ +gattgcactgctatgaaggtgcggacgtcgcgcccatgtagccctgataataccaatact\n\ +tacatttggtcagcaattctgacattatacctagcacccataaatttactcagacttgag\n\ +gacaggctcttggagtcgatcttctgtttgtatgcatgtgatcatatagatgaataagcg\n\ +atgcgactagttagggcatagtatagatctgtgtatacagttcagctgaacgtccgcgag\n\ +tggaagtacagctgagatctatcctaaaatgcaaccatatcgttcacacatgatatgaac\n\ +ccagggggaaacattgagttcagttaaattggcagcgaatcccccaagaagaaggcggag\n\ +tgacgttgaacgggcttatggtttttcagtacttcctccgtataagttgagcgaaatgta\n\ +aacagaataatcgttgtgttaacaacattaaaatcgcggaatatgatgagaatacacagt\n\ +gtgagcatttcacttgtaaaatatctttggtagaacttactttgctttaaatatgttaaa\n\ +ccgatctaataatctacaaaacggtagattttgcctagcacattgcgtccttctctattc\n\ +agatagaggcaatactcagaaggttttatccaaagcactgtgttgactaacctaagtttt\n\ +agtctaataatcatgattgattataggtgccgtggactacatgactcgtccacaaataat\n\ +acttagcagatcagcaattggccaagcacccgacttttatttaatggttgtgcaatagtc\n\ +cagattcgtattcgggactctttcaaataatagtttcctggcatctaagtaagaaaagct\n\ +cataaggaagcgatattatgacacgctcttccgccgctgttttgaaacttgagtattgct\n\ +cgtccgaaattgagggtcacttcaaaatttactgagaagacgaagatcgactaaagttaa\n\ +aatgctagtccacagttggtcaagttgaattcatccacgagttatatagctattttaatt\n\ +tatagtcgagtgtacaaaaaacatccacaataagatttatcttagaataacaacccccgt\n\ +atcatcgaaatcctccgttatggcctgactcctcgagcttatagcatttgtgctggcgct\n\ +cttgccaggaacttgctcgcgaggtggtgacgagtgagatgatcagtttcattatgatga\n\ +tacgattttatcgcgactagttaatcatcatagcaagtaaaatttgaattatgtcattat\n\ +catgctccattaacaggttatttaattgatactgacgaaattttttcacaatgggttttc\n\ +tagaatttaatatcagtaattgaagccttcataggggtcctactagtatcctacacgacg\n\ +caggtccgcagtatcctggagggacgtgttactgattaaaagggtcaaaggaatgaaggc\n\ +tcacaatgttacctgcttcaccatagtgagccgatgagttttacattagtactaaatccc\n\ +aaatcatactttacgatgaggcttgctagcgctaaagagaatacatacaccaccacatag\n\ +aattgttagcgatgatatcaaatagactcctggaagtgtcagggggaaactgttcaatat\n\ +ttcgtccacaggactgaccaggcatggaaaagactgacgttggaaactataccatctcac\n\ +gcccgacgcttcactaattgatgatccaaaaaatatagcccggattcctgattagcaaag\n\ +ggttcacagagaaagatattatcgacgtatatcccaaaaaacagacgtaatgtgcatctt\n\ +cgaatcgggatgaatacttgtatcataaaaatgtgacctctagtatacaggttaatgtta\n\ +gtgatacacaatactcgtgggccatgggttctcaaataaaatgtaatattgcgtcgatca\n\ +ctcacccacgtatttggtctaattatgttttatttagtgacaatccaatagataaccggt\n\ +cctattaagggctatatttttagcgaccacgcgtttaaacaaaggattgtatgtagatgg\n\ +taccagtttaattgccagtgggcaatcctaagcaaaatgagattctatcctaaagtttgg\n\ +gcttgatataagatttcggatgtatgggttttataatcgttggagagctcaatcatgagc\n\ +taatacatggatttcgctacctcaccgagagaccttgcatgaagaattctaaccaaaagt\n\ +ttaataggccggattggattgagttaattaagaccttgttcagtcatagtaaaaaccctt\n\ +aaattttaccgattgacaaagtgagcagtcgcaataccctatgcgaaacgcctcgatagt\n\ +gactaggtatacaaggtttttgagttcctttgaaatagttaactaatttaaaattaatta\n\ +acgacatggaaatcacagaacctaatgctttgtaggagttatttatgctgtttactgcct\n\ +ctacaaccctaataaagcagtcctaagaatgaaacgcatcttttagttcagaaagtggta\n\ +tccagggtggtcaatttaataaattcaacatcgggtctcaggatattcggtcatataatt\n\ +tattaagggctcttcgagtcttactctgagtgaaattggaaacagtcatccttttcgttg\n\ +tgaggcatcttacaccgctatcgatatacaatgcattccaccgcggtgtcccgtacacaa\n\ +ggaaacttgttaccttggggatataagaaaactcacacgtctcattattaaactgagtac\n\ +aatttttgcacgagaaagtaatgcaatacaatatgatgaaagccagctaatgaaaaggga\n\ +tggaacgcacctcggatctgttgcactggattaaaatccgattatttttaaaaatattca\n\ +gtgctagagcatatcaggtctacttttttatctggtatgtaaagcccacggagcgatagt\n\ +gagatccttacgactcaacgaaaagttataacataactcccgttagccaaagcccaatcc\n\ +cgattactgccctaccctaacgtctgccatctaaatatcgaacttgttatgatcaatgtg\n\ +actacctcccaccctttccccttcatttgttccactggggataagctagcgttttcagaa\n\ +tcaatgcaataagaatagccaattgtctcacttcatcagagctcttggcaattccaggcg\n\ +ctacgtggttctggaatatattcatttttcaaatagtaatacgtttagtgttgctattgt\n\ +ctacacgtttggatattacgttatgtgagcggacatcaatagttgtctaactctttagta\n\ +agccagagatagcactcttagcgaatggataccatcttccataagtttagttaatagtcc\n\ +gaaacaactgcttcgagcatatttgaacctccttgtaggcaaatagcctcttcaaagcaa\n\ +tcttactaatagatagagtttgttttaagggactactagaaatgggacaatcttaatagt\n\ +atgacctaaactgacatttaaagatatatccaggtggcaagcataaagatcattgcgcca\n\ +cctccaccgtgggattacttatcagtcgatatcctatatgctaagtttgcgacggcagaa\n\ +tacaaactaagctgagttgatgctaaccttacctatgataccccattggaccggttaaca\n\ +gccctacttattccaaataaaagaacttttatgctgtagaagctattatagtgatgcctg\n\ +gtaacttcagtatattaaaatgacacacatacgccatatagagctcctggaactttgaat\n\ +aatgagcgaacttcgaagttgaagagcaagaaaccatatgtcacggttgcctaaagcccg\n\ +gtaaccagacatgtgctatcattgatcattatcgaggttttcataaccttgacccattat\n\ +cggctgtgcgcggacaagtacttaaatcactagtttcttcacctgcttatcggtaagaaa\n\ +taaggttggcaaagaatcgcataagacggacgtagagccgcagcgttgtgcgagtccagg\n\ +tgcatgcgcagcaataggattttaaattttgttccatttttaatttagccgtaaggatgt\n\ +ccgtaaatgattgaaaattggattcaatctttgggcctatgctactggaacctgatcgac\n\ +aaaatttcaaacatacgttaactccgaaagaccgtatttttgcggctagaatagtcagtc\n\ +gcttggagccatataccttaccacttaaacgacgtgctcctgtagttgaaatataaacag\n\ +aacacaaagactaccgatcatatcaactgaagatctttgtaactttgaggcgaagcaccc\n\ +tcttcgagacaactaagagtaaagtaccgggcgccgcaaggagtcgattgggaccctaaa\n\ +tcttgacgaattgctaagaggctcagagctaccactgtaatttctctagagcccataata\n\ +aatgaacgatacatccgtaggtagcacctaagggattataatggaagccaaatgcagtta\n\ +ataatattatatactggcgtacacgattcgacggatctctcacatagtgattcacgaccc\n\ +ccccctttgattgacacagcgtcagcattttgcaagaacgatcttctgcatagggtgcgc\n\ +caccgtaaggatgacgtcgaagctacaactgggtataatttaccatgcttccctgatgct\n\ +gagtgcaatacactaagaatgagtttttaccccatatcaccagtatttgttctgttattg\n\ +cgaagaaatggctatgctgagttggcgactaaagtcacccatcctttttattaggtaacc\n\ +ccctcccttaaactaactgatttgctggagctgccctgcatacatatactttatcattta\n\ +tggacgtccgtgacgcttattatccaccatagtcgatatgctacacggattcattaatgg\n\ +atcgtaggagtttaagttatatttactaagatcggtctcggctactatcccgccttaccc\n\ +ggcgctatttacggccatttttaatatattgacggtaattattcctatggtttcgaccgc\n\ +acgtccttggacaagaaagaatggcaaaaaaaatgtaaaagaaaaaaaatattgagtccc\n\ +taccatcatataaaaaatatgtgatgagtaacttgacgaaatgttagtggttattaaaga\n\ +ctatctattacaccttttgttttctgtcgtagtatattaaagtctagaagccttacagga\n\ +aaatcagggttatacagccgatactccgcagcatgaatcatcgaggaggtgtcctaccat\n\ +cgcgccttgtaatcttgtctgtgtatactgtatttagaccttttatacaaagtaaatatc\n\ +tcggctttatgtgattgggaggggcctactcaaacatgatgacttgacctaataatcact\n\ +gtgcgggcgtcttatgactagctattccttgaaatccaccaccaaatggttaatatgtaa\n\ +aaactttgacgatgaaacaaggtgaatgtgtagttactttgtgtaattagctgcgtcgag\n\ +cattgcttgtaaaaccgtcaatcgcacacgttacttccataaaatttctacgaatacacc\n\ +cttcttaaaaaaaacgtaggaattcacgagtttaacaaacgataactgtataaagtggaa\n\ +gtccgaagaaagcagatgcccgaactactcgaagatgtttcgttttcttaaccatagggg\n\ +cttcttaatggcccactacgcacattttgttcaagcccgagagggacatccccattacgg\n\ +gagtattactaaaactgttccgtaatacgttcagcaagggatgaaaaaggccactgctca\n\ +agttattgacgtgggagtattacatcggaagcctgaatcccacactatgatggtctgtac\n\ +aggcctagggactgcgtctagacggtattaccggcttctaatcatacgatcgtgagtctt\n\ +aacgggaagtaaggctcacacctaccccaaaccatttatctatgtaagtataaaattgtg\n\ +cgtaagtgttcaaagtggacaataaagacgtggcaaaaacccccgcacataagccgcttt\n\ +agatttcacaaataccaatgcggttaaaaacatccttgagtcgtacatacaccatactcg\n\ +cgttaaacggatataacagaagataataaatccggatgtggagtcggtgtaactatagaa\n\ +agccaagtgaaataatgcttaccagtcatttagctatacggctttcatttcatgtcaaga\n\ +gggtggagtttgacctgtacagttgatatatcaccgatacttagaactcacctaaagcta\n\ +aaattgctcgcagcgtgtaatccgcatattacaaacaatagatgggattcattatacata\n\ +agacacgatgatctgctttttcaggttgcgagatgttgcctatcgtcaatcgagtcctgc\n\ +cttacaccacttaaacaaaagtattgacagggaacctattttcgaggtattatatagtcc\n\ +agcttgaatatcaatttgacagttaacctagtgaaaatcagtaagaggaaatacgccaca\n\ +ttctccagtgaaattctacgggttatcgtctagtccaactatcaattataactcacgaga\n\ +tataagtaaattctcgtacttggcctgatttttattatactttggatccttagtaaacag\n\ +gaagggagaaaccttcaacgaaaaacactggattttgttttactctcaaagctcttatat\n\ +gacggaaataccctgtcaagtcttaactttattactagactaatgaaatgggcttggggt\n\ +ggccagaatcatagtacaatttagcggatacactattcggactttcctatcggctgtctg\n\ +gttggataagtatggggactaataggctagacatacctatacttaaactatacaggcgtc\n\ +atctatctctgcaactttggagttccctgatgttctcccgccctttgggttcacatcttc\n\ +tataccgacacccctaataacgattagtttgtgggttagagtaaattaatacggttaata\n\ +ttaatgtatcgttgaaaagctggtgtcgccaataaggtaaccggctaggcagagtatatg\n\ +tcacgaagtataactaccctaatgataagctgtaggaataaaattaatgctgtctctaag\n\ +cgaagagatatttccgactctgttttaatgacgaatctcattacttctgacttgcaaatg\n\ +ttcaatatggcacggtttcacggcacctttgtgacgcatataatgaacttagaagattat\n\ +aacgacggaactttatatgataatccgttacgattaaagaatctgttaaatatcataatg\n\ +gcattcagttctagaccgtgcatcatggtaaacttactttctctgcatggcgacatacat\n\ +ttcgctattcaaattcgcgtgtggttacacccactcgcacctttggaatattaagagaag\n\ +atgatcagaaaatccattcgctcaatttttctgacgtacgtctaatttatcctaggagac\n\ +aaatcgttttatgtctctcacatttttgaagaaaggttcgagagacaatactcaggtcct\n\ +gaactgctagaagatactcggtggagcgtggcaacaatgaaaaactcgtgacataaatga\n\ +atgatacttttccaagttcagttaagtgaatatgtttaacatacccggcttttcgatctt\n\ +aagctgacgctggacgtgcgagtaatgtcagtctcttacatacactagtgactccaagtt\n\ +tcgtcaaaaacgccccctcccttctcgagcccactcacgctatgtattgacgcgaacttg\n\ +ttcgggatcagacttttcaggagttcggtcgcgtgtccctatgtgctaatatataagtta\n\ +gatcgcattagatgctaatctgaatacttatagacgaccttcaacgagaacgggtaccac\n\ +cttgaggctagagttaggtgtgaaacgacaggtagggacatataaaatttgagtgcggct\n\ +ttagttaagggtttaattacctactcaaacatcacgctcgcgcccttcgtacgtaatcga\n\ +ccatctagaggctaaggggactgtactaggtagtgattaatgatatcctagacgcacgtg\n\ +ccttagatcttcagactctgatggtccgcgatcaccgtaattgtagtcctccaactcgat\n\ +cactttgttggcgtcaaagaaattacgatatctaaatacttataatacaataaccaagga\n\ +tgagaatgactcatcgcgttggagttatattgcttgaagttctatggaatgaaagcacgt\n\ +tatctgccgtcccaatatctccagtgagctaattcattggacggtccactttgatcaatc\n\ +cccgaggagatgttcggacactttagtctgtaacacttagcgttgagaccacgaacaatt\n\ +gattactcagtcttgaaggtgttttccaaagttcattttaaataagactacgataggcct\n\ +ttcctattgatataaactacccggctctgttgttcgtgtgagtcgtacttctctgtgttt\n\ +ttctgattatagcaagattcgattcttagtgtaaacagcgatttttatttgacccgtcaa\n\ +tgagaagcgcataggatctaagcaaaattatcaagttgtgccacaaggtaagatctttcc\n\ +agttattgcaggtaggatgtatcccacgttgatagtatgaggtctgacgtcaactgtcta\n\ +ggagagttgaccgcgtgcgggtacaccggatttgcatcgatgttgagaacgcagaactcc\n\ +cactgtcgtggcggcgttcctgatatttagcaagaggcgttgataaagccctcatcatct\n\ +agatctcgacctcatctgccctcttgctccatcattttctacacagactactttcctatc\n\ +tacgttagtataattgctttctatcttagtatcatttagagcttctccgtcaacaggttc\n\ +gtgctattaaagttagtacgaaagggacaacttgtagcaacgcatttaatcggttttcga\n\ +ctacttcgcacaaaatcagataaagaagtttgtcattctattagacattgaattgcgcaa\n\ +ttgacttgtaccacttatgatcgaacactgaatcaagactgtgattaactaaaatagaca\n\ +agccactatatcaactaataaaaacgcccctggtggtcgaacatagttgactacaggata\n\ +attaattggactggagccattacattctctacaatcgtatcacttcccaagtagacaact\n\ +ttgaccttgtagtttcatgtacaaaaaaatgctttcgcaggagcacattggtagttcaat\n\ +agtttcatgggaacctcttgagccgtcttctgtgggtgtgttcggatagtaggtactgat\n\ +aaagtcgtgtcgctttcgatgagagggaattcaccggaaaacaccttggttaacaggata\n\ +gtctatgtaaacttcgagacatgtttaagagttaccagcttaatccacggtgctctacta\n\ +gtatcatcagctgtcttgcctcgcctagaaatatgcattctatcgttatcctatcaacgg\n\ +ttgccgtactgagcagccttattgtggaagagtaatatataaatgtagtcttgtctttac\n\ +gaagcagacgtaagtaataatgacttggaataccaaaactaaacatagtggattatcata\n\ +ctcaagaactctccagataaataacagtttttacgatacgtcaccaatgagcttaaagat\n\ +taggatcctcaaaactgatacaaacgctaattcatttgttattggatccagtatcagtta\n\ +aactgaatggagtgaagattgtagaatgttgttctggcctcgcatggggtctaggtgata\n\ +tacaatttctcatacttacacggtagtggaaatctgattctagcttcgtagctgactata\n\ +ctcaaggaaccactgctcaaggtaggagactagttccgaccctacagtcaaagtggccga\n\ +agcttaaactatagactagttgttaaatgctgatttcaagatatcatctatatacagttt\n\ +ggacaattatgtgtgcgaaactaaaattcatgctattcagatggatttcacttatgcctt\n\ +agaaacagatattgcccgagctcaatcaacagttttagccggaaacaatcgaagcatagg\n\ +gacaatgtatcttttcctaaattgccatgtgcagatttctgagtgtcacgaagcgcataa\n\ +tagaatcttgtgttgcctcaactcgttgaaaagtttaaaacaatcgcagcagtctttttg\n\ +gggtctactgtgtgtttgcaaaataactgaaagaaacgcttgaacaactctgaagtagct\n\ +cgagtactcattaaagtgtaacacattagtgaatatcggccaatgaaccaaacgcttccc\n\ +ggtacgctatctctctcatcgggaggcgatgtgcaggttatctacgaaagcatcccttta\n\ +cgttgagagtgtcgatgcatgaacctcattgtaacaatagcccagcaaattctcatacgt\n\ +gcctcagggtccgggcgtactcctccatggaagggcgcgcatctagtgttataccaactc\n\ +gctttttaactactatgctgtagttctacaggcatagtggccagtattttctaacttctc\n\ +tggatagatgctctcactcctcatccatcacggcttcagtttacgtcttacttgcttgtt\n\ +cagcaacggatggaggcattaagtatcttcactgttccctaaaattgctgttcaatatca\n\ +aagtaaggacgatacagggaaagctcaagcacactcattgaatactgccccagttgcaac\n\ +ctcacttaatctgacaaaaataatgactactctaagtgttgcggaagcagtctcttccac\n\ +gagcttgtctgtatcacttcgtataggcatgtaactcgatagacacgaacaccgagtgag\n\ +aaactatattcttgcttccgtgtgtgtgacaccaggtaattgatgcggatataagctgga\n\ +gatcactcacgcccacacaaggcgctgctacctctttattccaatgtgtaagaatttgct\n\ +aacttcatttctagaccgcagctttgcggtcataatttcacggtacggacccttgggtta\n\ +gagacttgataacacacttcgcagtttccaccgcgcacatgttttagtggcttctaacat\n\ +agaatttttgttgtgacataaagagtgcgtgggagacttgcccgaccgttaagccataat\n\ +caattgaaagccccgtgagtcacatctaattggttgtactgcgcatttagctatccttta\n\ +gctgactcgaagagattcgattcctaatataggttaattagatggctgccgcgcgaagta\n\ +aaacgtgaaaaacgtagtgcgcagatctgcataactcgcgcttaattacttatgagtagt\n\ +tccaagttcgctacgttatgagagagattggaattaagcaaatatgttttatggtgattt\n\ +tgggatgagaaggactgctaagtacggctactaaacaaatttctaaaaccgccatctacc\n\ +ttatcttggagacatttaagttgtatatgtcactagtctagcttttgtctgtgggacgcg\n\ +ttctcggaatgagggaaatgcaagagccgattcatcaaatgcttatctaagaaagtagtg\n\ +gactattacaccaagcacgaatgccagggaactgctttcttgctcaggacctcgcgacaa\n\ +ggtaccccgcataagtcctagaattacatttggtcagcaatgctgacatttgaccgtgaa\n\ +aacataattttaatcagaaggcagctcacccgcttgctctagatcttatctttgtatgaa\n\ +tgtcagaatttactgcaatatccgttccgaatagtgagggcttagtatagttctctgtat\n\ +acaggtcacatcaaactccccctgtcctagtacagctctgagctttaattaattgcatac\n\ +atttccttcaatcatcagatgaaaacaccgcgaatcatgctcttctcgtatagggcaaga\n\ +gaagcaacaaacaactagcccgactcacgttcatccgccgtatccttgttcagttcttac\n\ +tccgtattaggtcagcgaaatctaatcagaataatcggtcgcgtatcaaaattaaaatcc\n\ +cgcttgaggttgacaattaaaacgctgagcagttatcggctattagatagtggggtgaaa\n\ +gtaattggctggaattatgttaaaacgtgatattaagctaaaatacgctacttgttgccg\n\ +acctaattcagtcattcgatattcagttagagccaagaataacaagcttgtataaattga\n\ +acggggtgcactaaacgatgtgttactctaatattcagcttggagtatacctgaaggcga\n\ +attcatgtatcggccaataataagacgttgaagatcacaatttggactagcaaaagaagg\n\ +tgatttatgcgtggggattgagtccactgtacgagtacggtctctggaaaattataggtt\n\ +cagggaatataaggaagtaaagataattaccaagagatttttggtatcgctatgacccag\n\ +aggtgttctaacgtctgttttgatccgcagaatttctgcctcaatgcatatttgacggac\n\ +ttgaactagagcctctaaagttaaatggcgacgcaactgttcctaaacttcaattattac\n\ +tactctttttttcctagggtattgtagaggccagtggacaaaataaatcaaatttaagat\n\ +gtttcggacattaacatcccccgtagcatagaaatcatcagttatccaatctctcatcga\n\ +gcttttacaatttctgctggcgctatggacagcatatgccgcgagacctccgcaagactc\n\ +acttgatcactgtaagtatcttcattagaggttagagcctatagttaagctgctgaccta\n\ +gtaaaattggtattttctaattttattgctcaagttaaaggttagtgaagggataatgac\n\ +gttatttttgaacaatgggttgtattcaattttatatcacgaatggaacccttcattccc\n\ +ggcataatactagacgacacgaacaagctccgatctatcagccaggcacgtgttaaggtt\n\ +taattccggcaaaccaatgaagcatcaaaaggtgacctgatgcaacttagggtcacgatg\n\ +agtttttcaggactacttattacctattaataagttaacatgagccttcataccccgtaa\n\ +gacaatacatactccaccaattagaattctgagccatcttatctttttgtatcatcgaag\n\ +ggtatggccgaataggttaattagttactcctaacgtctctacaggcatgcatttgacgc\n\ +accttcgaaaatagtcaatctctcgccacacgcgtctagtatgcagcatcaaaaatatag\n\ +tccacggtttccggattaccaaacgcggcaaagagaaacattgtatcgacggagataact\n\ +taatacagaaggaaggggcatcttcgaatacggatgaataattctatctgtttattctga\n\ +catcttgttttcaggttaatcttacgcattcaaatgacgcctgccccatgcgtgcgcaat\n\ +tattttctaatattgacgagagcaatctcactccttttgggtctatttatgttttattga\n\ +ggcacaagcctatacagaacaggtactattaaggccgtgagtgtgagactcaaaccgtgg\n\ +aaacaaaggatgggttgttcttggtacaagttttagtgcatgtgggcaatccttaccaaa\n\ +atcagatgctatccttaactttgggctgcatttaagatggcggttggaggcctgtgagaa\n\ +tcctgcgtgtcatctttaatgaccgaattcatccatgtagattcagatcacacactcatt\n\ +ccttgatgttgtctaaacaaaagttgttgtggacgcattggagggagttaagtaacaact\n\ +tgggatcgcatacttataaaaattatatgttaaactttcacaaacgctgaagtccaaagt\n\ +aactagcccaaacgcctcgagagtcactaggtattaatggtgtttgagttcctgtgaaat\n\ +agtgttcgaaggtaaaatttatgtaccaaatcgaaagaacacttaataaggcttgcttgc\n\ +acggaggtatgatgtttactgactctacaaccctaattttccagtacgtacattcattcc\n\ +aataggttagttctcaaagtgctatacaggctcctcaattgatgatatgcttcagccgct\n\ +ctatggatattagctcattttatttaggaagcccgcttagaggcttactatgagggaaat\n\ +gccaaaatgtcatacttttcggtgtgtcccatatgacaccgctttacatagaatttgaat\n\ +taaaacgcgctctcccgttcactaccatacttggtaccgtgcgcatattacatatagata\n\ +taggatcattttttaaagctgtactaggtttgatcgacaatcttatgctatactatatga\n\ +tgtaaccctcataatcaataccgatcgtacgatcctagcataggtggcaagcgattttat\n\ +gccgattattgtgttaaatagtctgtgagtgtgattatcagggctacgttggtagagggg\n\ +ttgtatagacctcgcacacattgtgacatacttaacaatatacgaaaactgatataataa\n\ +atccccttacccaaacaccaatcccgttgaatcaactaccataacgtctcccatataaat\n\ +tgcctacttgtttgcataaatctgaatacataacaccattgcaccttcttgtgttccaat\n\ +cccgttaagattgccttgtcagatgatatgcaagaacaatagcatttgctagcaattatt\n\ +aacagctcttcgaattgcctccacataacgcgggagggtatattttaatttggcaaatac\n\ +taagtactgttggcgtcatatgctattaacggttggatattaagttatgtcagccgtaag\n\ +caagagtgggcgaaatattttgttacccagtgagagcactcttagagtttggatacaata\n\ +ggccatatgttgacttaagaggacgtaactacgccgtacaccattgttcaaccgacttct\n\ +tggcaaatagaatcgtattagcaatcttaagaatagagacacgttcgtgttagggtatac\n\ +tacaaatccgaaaatcttaagaggatcacctaaactgaaatttatacatatttcaacgtg\n\ +gatagatttaacataattcagccacctccaacctgggagtaattttcagtagatttacta\n\ +gatgattagtggcccaacgcacttgactatataagatctggggatcctaacctgacctat\n\ +gagacaaaattggaaacgttaacagcccttatgtgtacaaagaaaagtaagttgttgctg\n\ +ttcaacagatgatagtcatgacgcgtaacttcactatagtaaattgaaacaaatacgcaa\n\ +tttagacagaatggtacggtcatgaatgacagtaattcgaagtgctagaccaacttaaaa\n\ +taggtaaacgtgcccgaaaccccccttaacagaaagctgctatcatggtgcagtatcgac\n\ +gtgttcagaaacttgtaacttttgagcaggtccgagcacatggaagtatatcacgtgttt\n\ +ctgaaccggcttatccctaagatatatccgtcgcaaactttcgatttagtcccacgtaga\n\ +gcccaagcgttgtgcgactccacgtgcatgcccagaaatacgagtttaaatttggttaca\n\ +tggttaattttgaccgaagcatcgcactttatgattgataattggattcaatatgtcgcc\n\ +ctatgcgaatgcaacatgatccacaatttggctataagacgtttaatccgtatcacactt\n\ +tgtttgcggctagtatagtaacgcccgtgcaccaagagtcagtaacaattataagtactc\n\ +cgcaggtacttcaaatataaaaactaatcaaacacgacccatatgatcatctgaagatat\n\ +ttggaactttctcgacaaccaccctcgtactcaatacttacactaatcgacaggcacacg\n\ +caacgtgtacagtcgcaccatattgagtcaagatttgcttagtggcgatgagcgtacacg\n\ +cttatttctctagtcacaattagttatctacgagacatcacgagggagcaaataagcgat\n\ +gttatggctacacataggcacgtatgaatatgatataagccagttaaacagtcgaaccat\n\ +cgagcaaattctcatgcaccaacccacacgttgaggcacaaagagtaagctgtttgaatg\n\ +taacttcttctgctgagcgggccccaacgtaaggatcaactagaagagaaaactcggtat\n\ +tagtttaaatgcgtcacggagcatgagtgcatttcactaagaatgtctgtgtaaccaata\n\ +taacatctatttgttatctgattgcctacttatggctttgcggtcgtggcgactaatgtc\n\ +tccaatccttttgaggtcggtaccaactccctttaaattacgctgtgcaggctcatgcac\n\ +tgcatacatatacggtagcaggtagggacctcacgcacccttattataatcaatagtagt\n\ +tatcagtcaacgaggcaggaatgctgaggtcgaggtgttggtatattttctatgtgccgt\n\ +ctaggcgactatcacgcattaccaggcgagatttaagccaattttgaatatagtcaacgt\n\ +aatttttactatgggttccaccgaaacgccttgcacaactaagaatcccataaaatatcg\n\ +atatcaaataaaagattgtgtcaataccttcatatatattttttcggttgactaacgtga\n\ +actaaggttaggggttttgtatgtctatataggaaacagtttcttttctgtcctacttta\n\ +gtaaagtcttcaagccttactccaaaatcacggtgattaagccgttactcagcagcatga\n\ +ttctgcctgctcgggtcctaaaatccagccttgtaagagtcgctgtgtattagctaggga\n\ +gacctttgttaaaaaggatatatcgcggcgggatgtgagtgcgtggcgcatactcaatct\n\ +tcagctcgtgtcattataatatctctcccccacgcttttcactagatatgccgtgtaagc\n\ +aaacaccttatgcttaatttcgaaaatattggtacttgaaaaaagctgtaggggtactta\n\ +atgtctggtaggagatcaggagagaattgagtgtaaaaccgtaaagccctcacctgactt\n\ +catgtaaatggcttagaagactccatgatttaataaatactacgaaggaaagactggatc\n\ +taaagataactctagtaaggccaactcccttcaatgctgttgccagttataatccaagag\n\ +ctgtccttttctgaaccatagcggcttctgaagcgaactagaagcaaagttggttctagc\n\ +cagacagccacataccctgtacgggtgtattactaaaactggtccggtattagttcacca\n\ +agggaggaattaggcaaaggatctaggtatgcaagtcggagtattacatccctaccctga\n\ +atccatcaataggttcctctgtactggccttcgcaatgagtattcaaggttgtacagccg\n\ +tataataataagatagtgactatgaacgggaagtaacccgctcaccttccccaaaacatt\n\ +gttatatctaagtattaaagtctgccgtagtgttaatactcgaaaataaacaactggcaa\n\ +attacaccgcacttaagccgcttttgatttatatttttccaatgcgcttttaaaaataat\n\ +tcagtcctacatactaattaagacccttaaacggagatatcacaagttaagttttaacca\n\ +tctcgactaggtggaactatagatacccaactcaatttatcattacctgtaatgttccta\n\ +gaaggattgcatttcatgtcaagacggtggagtttcacagcgaaacttcagtgtgaacag\n\ +attctgagaaatcacctaaacctattagtcagagcacccggttagaaccagttgtcaaaa\n\ +aatagagcggttgcatgagacagaagtaacgatgagatccgttgtaacgttgagacatct\n\ +ggcctatcgtcaatacagtcctcccttaaaaatatttttaaatactaggcaaacccaaca\n\ +taggttagtcctatgtgatacgccacatggtatatcattttgtaacgttacctagggata\n\ +atcaggaagtggaattacgcaaaagtagacagtgaaatgcttagggttatagtctagtcc\n\ +aaagataaaggataaagcacgtcagagaactatattagccgaatgggaatcattgttagg\n\ +agactgtggatcatgtctaaaaagcaacgcagaaacagtcatcgaaaaaatctcgttttt\n\ +gtttgaatctaaaagagctttgatgaccgatagtacctgtatactagttactgtattacg\n\ +tgtctaatgatttcggattggggtccccagaatcagacgtcattgtagacgattcaagtt\n\ +taccaatttaatttcccagctctccttggagaactatcgccaataattgcagtcactttc\n\ +cttttctgaaacgataaagccgtcagagttctctgcaacgttggacttacctgaggttct\n\ +aacccactttcggttctaatagtagttaacgacacaacgaataacctttactgtggggct\n\ +ttcacgatattttttcgcttattattaatggttacgtcataagctggtgtccaaattaag\n\ +gttaccggcttcgcagagtagttgtatccaagtataacttccctaatcataagatcgagg\n\ +tagaaaattaatgctgtctctaaccgaacagatatgtcccactatgtggtatggacgttg\n\ +ctaattacttctgaagggaaattggtcattatggatacgtgtctaccatcaggtcggacg\n\ +cagatatggttctgtcttcagttgatccaccgttctttataggataataactgacgatta\n\ +aagattatggtaaatagattaagccaattctcttcttgtcagtgaagcatccttaactga\n\ +cttgctctgcagcccctcatacatttagctattcaaagtaccggctcgtttcaaactctc\n\ +ccacctttggaagaggttgtcaacttgataagtatatcatttacagcattttttcggacg\n\ +tacctctaatgtttcattgcagaaaattagttttttctatcgcacattttgcaagtaacg\n\ +ttagagacacaattatctgcgaatgaactgctagatctgacgaccgggagcctcgcaaat\n\ +atcaaaaaagactgacatatatcaaggagtcgttgacaagtgctggtaagtcaattggtt\n\ +tatctgtcccggcgtttcgatcttaagctgaccatgcacggcagagtaatgtcactctcg\n\ +ttcttacaagtctgtctccaagggtcggcaaaaaagacccctccattctcgagcccactc\n\ +acgatatgtagggacgacaacttgtgcggcttatgaattgtctggactgcgggcgagggt\n\ +ccatatctccgaagttagaagggacatacctttagatgataagatcaattcttattgacg\n\ +aaattcatccacaacggggaacaacttcaccctagacttacgtctgaaaagacacctagc\n\ +gtcttataaaaggtcagtgccccgtttcgtaaggctggaattacctacgcaaacttaaac\n\ +ctcgcgcccttccttacgtatcgacaagatagaggctatcgcgaatgtactacggaggca\n\ +tgaatcatatactagaaccaagtgcctgtgatattaacaagatgatccgacgcgagcacc\n\ +gtaattctaggcataaaactccagcaatttgggggccgaaaacaaatgacgttagctaat\n\ +taattatatgacatgatcaaaggaggtcaatcacgcatcgagttcgacgtatattcattg\n\ +aacttcgtgcgtttgaaagaaacttttatgaaggcaaaattgatcctgtctcctatttca\n\ +tgcgtacctcctagttgataattccccgagcagtggttaggacacttttgtcggtatcaa\n\ +gttccggtctcaaaacgtaaaattctgtaatctgtatggatggtctgtgaattagttaat\n\ +ttttatgaagtcgtcgagacgcagttcctattgatttattctaaacggagatgtgcttcg\n\ +tgggactcggaagtagatctgtgtttatgattattgctactttagatgctgactgttaac\n\ +tccgtgttgtttttcaaccgtatatcacaaccgaattggatagaacctatagtttcaagt\n\ +tctgccacaaggtatcatatttacagttagtgctggttgcttctttcaaacgtggtgagt\n\ +ttgtgctatcacgtcaacggtagagctcagtggaccgagtgcgcgttcaaccctgttcca\n\ +gagagggtgtgatagcacatataccacgctcgtcgaggcgttcatgatagtttgcaagag\n\ +ccggtgttaaacacatattattattgttatccaactaatcggacctatgcataaagcatt\n\ +gtctaaacagaataattgcctatatacggtagttttagtgatttatatcttagtatcagt\n\ +tagagcttcgaactcttcaggttcctcatatttaacgttcttcgaaagcgaaaacttcta\n\ +caaacgaatgtaagcggttttccaagtagtacctataaatcacagaaagatctgtctcag\n\ +tatagttgaaatggtattcagctagtgacgtgtaccaattatcatagttcactcaagcaa\n\ +gacgctcattaacgaatatagacaagacactatatcatataataaaaaagaacatggtgc\n\ +tcgaacatagttgaattcaccatattgaaggggaatgctgacatgtaattcgctactaga\n\ +cgatcaattccctacttgtcaaagttgaactggtacgttcttggaattaaatatgattgc\n\ +gctggaccaaattgcgacttcttgagtttcagggcaaacgattgagccggaggatgtccg\n\ +tctcttacctttcttgcttatgataaacgacggtccctgtacatcactgggaattctcag\n\ +caaaaataattgggtaaatcgagactcgatgtattcggccacaaaggtgttagacgttaa\n\ +agattattcaacggggcgataataggatcataaccggtatgcaagcgcattgaaagagcc\n\ +atgagatccttatccgataaacgctgcacggtatgtgcagccttattgtcgatcacgaat\n\ +ttataaatgtagtctgggctgtaagttgaagacctaagttataatgaagtgcaataccaa\n\ +atcgattcatagtggattatcagactcaagatatctcctgataaattacagttgttaaga\n\ +tacggataaaatgagatttaagattagcagcctctaatctgtttcaatcccgttggaatg\n\ +tggtatgcgatcaaggttaagttaaaatcaagcctgtcttcagtcttgattcttgttctg\n\ +ccatcgcatgcggtctacgtgagttaatatgtagcttacgttctagcttgtgctaatctg\n\ +agtatagattcgtagaggaatattatcaagcttccacgcctcaacgtacgtgtattggtc\n\ +acacaagacactaaaagtggaagtagcgtaaactatagtctagttgttaaatgctcagtt\n\ +cttgttatattcgatatactcttggctaatttatgtctgagtatataaaattaatgatat\n\ +taacttgcatttcacggatcccttagaaaaagattttgaccgagcgcattataaacggtt\n\ +acaccgaatcaatagaagcatacccaatagctttctttgaatttattgcctgcgcaactt\n\ +ggctgactctctagatccgaataattctatatggtcgtgacgaaactagttcattactgt\n\ +ttaaaatgccaacatgtcttttgggccgataatggctctttgcaaaattactcaatgata\n\ +cgattgatcaaagcggtagttgctagtggtagcatgtaagtctatcaaatgtctgattat\n\ +ccgaaaatcttccaaaagagtccacgtaccatatctatctcatagcgacgcgaggggaac\n\ +cttatctaactatcattccatttaccgggtgactctcgatgcaggatccgattgggataa\n\ +attgcccagaaatggctcattcctgactaagggtaaggccgttctcagcaagggaacccc\n\ +gcgaatctaggcttataccatctagattgttaactacttgcctgtagttctacagccata\n\ +ctggacagttgtttctaaatgatcgggattcatgctagcactcctctgaatgcaccgcgt\n\ +aagtttaactattacgtccgtgggcagataaggatggaggctgtatgtatcttaactgtt\n\ +acctaatatggctggtaattatcaaagtaaggaccttaatgccatagcgctagcaatcgc\n\ +tttgtatactgaccatgtgccaacctctcttaatctgtaaaatataatgtcttagctaac\n\ +tgtggacgatcatgtctctgcctagagcttcgctgtatcaattcctatagccagcgtact\n\ +agtgacacaacaacaccgtgtgagaaaagatattagtccttacgtctgtctctctacagc\n\ +ttattgatgaggattgaacatggacatatagctccccctcaaaagcagatgctacctctt\n\ +tattccattctcgaacatttgccgaacttaatttcgacaaacctgaggtcacgtcttaat\n\ +ttatcggtaacgtcacgtccctttgagactggataaatatattaccaggggccaacgagc\n\ +aattgttggaggcgcttctataatacaaggtgtcttgtcaaagaaagacggcgtgcgtct\n\ +cgtgcaactcacttaaccaatattaatgtgaaacccccctctctcacatcttatgcggtg\n\ +tactgccctggtacatttcctgtacaggactccaacagtgtagattcctaagatagctgt\n\ +tggagttgcctcacgccagatcgaaaaactgaataaactagtgagctgagctgcagaaat\n\ +accgcttaattacttatgactagttcaaagggacctacgtgatgtcagacattgcaagga\n\ +agaaattaggtttgtgcgtcattttggctggactagcactccttacttcccctactattc\n\ +aaatgtcgtaaacagcatgagacaggatcgtgctgacatttaaggtctattgggaacgag\n\ +gctacctttggtcgcgcgctcgcgttctccgaatgaccgaaatgcatgagcacagtatgc\n\ +aattgcttatagatctaaggtctggtcgttgaaaccaagcacgtaggcctgggaaatcag\n\ +ttcttcctcagcaactacacaaaagcgtccaagcattagtacttgtagtaaatgtccgaa\n\ +cctatgcgctcatttgaaagtcaaaaaatatttttaagcagtaggcacctaacccgattc\n\ +ctctacttagtagctttctttgattctcagaattgactgcaatatcactgcacaattctg\n\ +tgccattactagacttctctgtattaacgtctcatcttactaacactcgcctaggacaca\n\ +tctgagagtgaagtatttcaatacatttactgaaatcttcagttctaaaatccccgaata\n\ +aggctcttatcggtttggccaacacaagaaaaaaacttcttgcaccactcaccttcatac\n\ +gcaggagcctggggaacttagtaataactatttcggcagacaaagcttataacaagttgc\n\ +cggcgcgtataatatttaaaagaccccttgagctgctcaattaaaacgctcacctggtat\n\ +aggctattagatagtgccgtcttagtaaggggcgggaattatcggataaactgatatttt\n\ +gataaaataaccgacttgttcacgacataagtcactaaggagattttatctttctccaaa\n\ +gtatatcttccttggataatttcaaagcgctgcaatttaagttctgttactagtttatgc\n\ +tgctgggaggtgaccggaaggcgtagtaatctagaggcaaattataagaagttcatcata\n\ +tcattttcgactacaaaaacaaggtgttgtatgccggcgcattgtgtaaactggacgagt\n\ +accctagatggaaaattatacgttaagccaagatttcgatgtaatgataattacctacac\n\ +atttttgctatccataggaacaagagctgttctataggctcgtggcatacgaacatttgc\n\ +tgccgctatgaatattggaagctcttcaactacagactctattcttaattgccgtcgaaa\n\ +atgggccgaatcggctattattaatactcggtttttccgaggggattgttgtcgacagtc\n\ +gtaattattattaatattgatgttggtgaggtcatttaaatacaaccttgcagacaatga\n\ +ataagggatccaatctctcatactccttttacaattgctcatgcccctatgcaaacctta\n\ +tgccgccacacctccgcaactctctcttctgaactgtaagtagcttcattactggtttga\n\ +gactatactgaagctgatgacattctaaaatggctattttcgaatgtgattcataatgtt\n\ +tatcgtttgggatggcagaatcacgttatttttgatatagcccgggtattctattgtata\n\ +gaacgtatgctacaagtcattccccgaagaagactagaagtaaacaacatgcgaccatcg\n\ +ttaagccacgcaaggctgtagctttatttcccgataacctatcttccataaatagcggac\n\ +agcaggatactgacgctcaacatcagtggttatggtctaatttttaacttttaataaggt\n\ +aacttcagcaggcatacacagtaactctttaatttataatcaaattagaagtctgacact\n\ +tcttatatttttctatcatccaacgcgatcgcccattagcttattgtgttactaataacg\n\ +tatctaaaccaatccttttcaagctactgcctatattgtcaatatatacaaacaacagga\n\ +tagtaggctgcttaaaaaatattgtcaaccgtgtacgctttacaatacccggaaatcaca\n\ +aactttgtagacaacgagtgaaatttatacactacgaagggccagcgtacaagacccatg\n\ +aattaggcgatatgtttattctgacatattggtttatccttaatctgtcgctgtaaaatg\n\ +aagccgcccccatccctgcgaattttttttcgaagattcacgactgaaatataaatacgt\n\ +ttggctatatttatgttggagggaggcaatagcctttactgttaaccgaagatttagcca\n\ +gtgagtgtgacactaaaacactggaataaatgcaggcgttcttctgggtaaaaggtttag\n\ +tcaatctcgcctataagttcatatagctctggatataattatctggcccatgcatttatc\n\ +atggcgcttggtgccctgtgtgaagccggcctctcatattgaaggtccgaagtattccat\n\ +gtacattaagatcactctctcattcatgcatcttggcttaacaaatctggttgtccaagc\n\ +tttccaggcacgtatggtacaaattcggatcgaatacttataaaaatgatatgttaaact\n\ +gtctaaaacgctcatctacaaagtaaagtgcactaaccaatagagtctcaagaccgtgta\n\ +atgctggtgcactgaatgtgtaatacggttagaagggattagttatgttacaaatccatt\n\ +gaaaacttaagaagcattgcgtgctcggagggtgcatcttttatcaagagactaacatta\n\ +ttttcaacgacgtacatgctttacaatagggtacttatcaaacgccgagaaacgcgccta\n\ +tagtgatgttatgattatgacccgatatccattggaccgaattttatgtaggttcccagc\n\ +gtactcgcgtaatatctcggtattgccataatgtaatacttgtcggtctctcccagatga\n\ +aaaagcgttacagagtatttcaatgaaaaacagcgcgcaacgtcaatacctttaggggta\n\ +acggccgctgatttcatatagatatacgataagttggtatagctctactaggtggcatcc\n\ +acaatcgttgcatttactatagctggttacaatcataatctataccgttccttacatact\n\ +accatagcgggatagcgtttttttgccgttgattgggtttaagaggatgtcagtctcatt\n\ +atatccgattcggtgggagagccgttgttttcaaatcgcacactttgtgacataatgtac\n\ +aagataacaaaactgatataagatataaactgtcaatatcaccttgacacttgaatcaaa\n\ +gtaaattaactcgcaaatataatttgactaattgggtgcagatttctcaattaataaaaa\n\ +aatggcaccggatgggcttacaagccccttatcattcacttgtatcatgatttccaagaa\n\ +caatagaatttgctagcaagtatgaacagagattcgaattgcatccacagtacgccggag\n\ +cgtttattttaatgtggatatgacgatgtactgttggcggcatttgctagtaaccggtcc\n\ +ttatttacgtagcgcacacgtaagcatgtctgggagaaatatggtggtacaatctcagag\n\ +aaagattacagtttggtttaaataggacttatcgggtcggaagtggaacttaataagcag\n\ +tacacaattgggcaacagacgtcttgcctattacaataggattacaatgcgttagatttc\n\ +agacacgttcgtgtttggctattcgtcaattccctaaatagttagacgatcaactattat\n\ +caaagtgattctttgttcatcctccattcatgtaacagatggcacactacgcataacgcc\n\ +gaggaattttaacgagatttaagagagcagttcgggcacaacccacttgactttataaca\n\ +gctcggcagcataaacggtaatatgtgacaaatttccaaacgttataagaacgtatgtgt\n\ +acttagaaaactaagtggttcatgttcaacagatgtgacgcagcaagcctaacttatcta\n\ +ttggttttgctataaaagaacaaagttacacagaatcctaagggcttgtttcacacttat\n\ +gcctagtgcttcaccatcttaaaatagcgaaaccggcacgaatcaaaccttaaaacaatg\n\ +cgcagatattggtgatggtgactccgggtatgataatggtaactgttgaccagcgcccac\n\ +ctcatcgaagtatagaaagtggttaggataaggatgagaccgaacttatttccggccata\n\ +actttagattttctacctagtacacaacatcagggcggacacgaaaccgccatcacatca\n\ +tataccaggtttaatttgcttaatgggggaagtgtcaacgaaccttcgaactttagcagg\n\ +catatggccattatatatggccccagagcagaatgctacagcagacaaaatttggattta\n\ +tgtagtttaatacctatcaaacttggtgtgaccatacttgtctaacgacagtgcacaaag\n\ +tgtaagttacaattattactactcagcagcttctgcaatgataaaatcttatcatacacg\n\ +tcacatatgataatatctacttagggggaacgggctccacaacctacatagtactcaata\n\ +cttacactattcgacaggcacaccaaacctgtacagtcccaaaagattgagtcaactttg\n\ +cagtactgcagatcacagtaatagcttagttagcgagtcaaaattagttttctacgagac\n\ +tgcacgaccgtgcaaatttccgatgtgttggctacaaatagcaacgtatgaatttgtttg\n\ +aagccacgtaaactgtacaaccttagagataagtctcaggctactaaaaacacgttgtgg\n\ +cactaacaggatcatggttgattcttacttattcggctgaccggcccaataagtaacctt\n\ +caactagaacagaataatcgggagtagtttaattcagtcaaggtgcaggtctcattgtaa\n\ +ctaacaagctctgtgtaaccaagttaaaatcgttttcttagcggattccctacttatgga\n\ +tttgagctcgtccacaatattcgatacaagaagtttgtggtccgtaacaacgaaatttta\n\ +attacgctgtgcagcctcatccaaggaattaatagaaggttgatggtaggctccgaacgc\n\ +tccatgattataatcaagtggactgtgcagtaaacgaggaaggtatcctgacgtcgtggt\n\ +gttcgtttttgttatttgtgccctatacgagtagataaaccatgaacagcacagtgtgaa\n\ +cccatggttgattttaggctaccttatttttaatttccgttacacagaaacgaattccac\n\ +aactaacatgccattaatttttcgatatcttataaaagatggtcgaaattcattcattta\n\ +ttttttttcggttctcgaaagtcaactaagctgtcgcgttttgtttctctttagaggtaa\n\ +aagtggctttgatctcctacgtttggatactagtcaaccattactccatttgatccgtga\n\ +gtatcacctgtctaacatccagcattatgactcctcggcgaagaaaagacacacttctta\n\ +gagtcgatgtgtattagctagggacacagttgtttaatacgatagtgagcccagggaggg\n\ +cagtgcgtcccccagtagatttattcagctagtgtaagtataagatatctcacccacgag\n\ +gttcaagtgatatgcagtcttagaataatacttatcctgaatttcgatattatgggtact\n\ +tcaataatccgctagcgctactttatgtctcgttggacagcaggacacatggcagtctta\n\ +aacactaaagacatcacctgaatgaatgtaatgggattacaagaatcaatgaggtattat\n\ +atacgacgtaggaaactctggatatatacagtaatctagttacgccatcgcacttcattc\n\ +ctctggaaacttagaagacatcagctgtacgtggaggaaccagacccccgtatgtagcca\n\ +aatagaaccaaagttgcttatacaaacacacccaatgacaatggaccgctggagttcgta\n\ +aactcggaacgtagtactgcacaaacccagcatttagcaataggagctacgtatgcaact\n\ +cccacgtggtaataccttcaagctatcaatatataggtgcctagctaatcgcattcgcaa\n\ +gcagtattcaagcttgtaaaccagtataataattacagaggctctatgaaacccaacttt\n\ +ccagctaaaagtcccaattaaatggttatttcgtacttttaaagtcgcccgttctgttat\n\ +tacgcgaattgattctactccaaaattaaacacaaattatcaaccgtttcatttatattt\n\ +gtcaatgcagctgtttaaaataaggctctactaaattataattaagacacttattaccag\n\ +atttctctagttaagtttgaaccagctcgactaccgcgaaagatacattcccttctctat\n\ +ttttcagttcatctatgggtcagagaagcattgaatttattctattcaccctcgtcgttc\n\ +acagcgaatcgtcagtgtgatcagtgtatgagaaatatcctaaaccgtttagtcagacca\n\ +cacgcttagaacaagtggtctaaaaagactgccctggaaggagtaagaagtatacagctg\n\ +atccggtgtatccttcagtcatctgccctatactaattacacgacgcaaggaaaaatagg\n\ +tttattttctaggcaaacccttcataggtgactccgatgtgttacgaatcatgcttgaga\n\ +atgtgctatcgttaccgacggataataacgatctccaatgaaccaaatgtagaatgtcta\n\ +ttgattacccttttactattcgacttagagataggagatagaacctcagtgtactttttt\n\ +agccgaatgggaatctttgggaggtgaatggccataaggtcgtaaatccaaccctcttaa\n\ +agtcttccatattatatcgttgttcgtggaatcgataacagatttgttgacccatagtaa\n\ +atgtatactagtttatgttgtaagtgtagattgttttccgattgccgtccaaactttatg\n\ +tcgtaattgtagaccagtaaagttgaccaaggtaagtgcccagcgatcctgcgagatcga\n\ +tcgccaatttttccagtcactgtaagtgtaggtttagataaagccgtatgagttatatca\n\ +taagggcctcggaaagcagcttcgaaccaaagttcccttataatagtagtttaactataa\n\ +aagtatatactggtctgtcgccctttcacgatttgttttaccggtttatgaagcgttacg\n\ +tcattagagcggctccaatttaaggttaacggcttccatgtgtagttgtatacaaggata\n\ +acttaaagtatctgttcagcgagctagttaagttatcctcgatagaacacaactcagagg\n\ +tcccaagatcgggtttgcaacttgctaatttattctcaaggcaaattgggaattatcgat\n\ +acctgtataccataaggtcgctcgatgtgatgcttatgtcttctggtgatcctaccttag\n\ +ttagtgctgattaacggaacattaatgtttatcgttttgagatttagccaattctctgat\n\ +tctaactcaagatgccttatctgacgtgctatgcagcccctaagtattttacattgtaat\n\ +aggacacgctcctttaaaactcgccaaaaggtcgttgtggttctctactggttaactata\n\ +taatttacagctttgttgagctagttcctctttggtttaagtcctcaatattagttggtt\n\ +cgagcgataagttggctagttaccttagtcactatattagatccgaatgttatgcttcat\n\ +ctgaagaccgccaccctccaaaatttcttttaagactcacttattgcaaggtgtaggtga\n\ +attcggctcgtttctcaagtggtgtatctgtacacgagtttccatattttcatcaacagc\n\ +caccgcacacttatgtcactctaggtattaaaagtcgctctacaaggggacgcaattaag\n\ +aaacagacatgctagtcaaaaataaacatagcgaggcaccactaattcggccgcttatca\n\ +atgggatgctctgcgcgagacgcgccagagctcagtagttagttcggacatacatttact\n\ +tcagatgatcaattagttttctacaaatgcttactctaccccgaaaaaagtcaccagact\n\ +cttacgtctctttagtatccttccgtcttatataaggtcagtcccccgtttcggtaccct\n\ +ggaatttactaagaataatgaaacagcccccaaggacgtacgtttacaaatgatagacca\n\ +gatcgcctagcttattccgacgcatgttgcatagaattgaaccaacggaatgtgagagta\n\ +actagatgagccgaccacagcacccgtttgcgtcgcagaatacgcctgatagttcggcca\n\ +cgaaatcatatgtcctttgagtattaagtatttgtaatgatcaatcgagctcaagcaagc\n\ +ttacacttcctcggatattcagggaacttagtgcctttgaaagatacgttgatcaacgaa\n\ +aaattgataatggctcatatggaatgcctacctcatagtgctgaattaacacagcactgc\n\ +ggacctaacttttcgaggtttcaagttcacgtctcaaaacctaataggctggaatatgta\n\ +gggatcctcggtgaatttgtgattgggtttgttgtagtactgaccaagtgaatattcttt\n\ +ttttctaaaagcagatctgctgccgggcactacgaaggagatctctgtgtatcattattg\n\ +cttcttgacatgatgactcttaaatcactgtgggtgtgcaaaacgatagcacaacccaat\n\ +tcgatagtacatattgttgatacttcgcactaaaccgttcatatttaaaggttgtgctcc\n\ +ttccttcgttaaatactggtgacttggtcctatctactattagctagacctctggggaac\n\ +cacgcccccgtaaaacctgtgcaagagagggggtcatacatcttagacatcgcgcctcca\n\ +ccagggaagcattgggtgattgaccaggtgtgtaacaaatatgattattcttatactaat\n\ +attagcaaagatgcataatgatttgtattaaatgtataattgaattgataagggtctttt\n\ +agtcagtgatagagtagtataaggtagacattagaactcttaaccggacgcagatttttc\n\ +ggtcttagtaagccaattagtcgacaaaacaaggtaagagcggttactagtagtacctat\n\ +aatgcactgaatcttcggtcgaagtatagttctaatgctatgcagattgtgacggcgaca\n\ +aatgttcagacttatatcatgaaacaagctcttgtaagtattgacaaatgaaaagattga\n\ +atatttttaaatacaaaatgcgcctacttattaggggaattaaccagattgaaggccaat\n\ +cctcacatgtaatgagataatagacgataaatgaaattcttgtaatagttgaactgctac\n\ +gtgatgggtattatatatgattgagatcctccaattgccgacgtcttgtcttgatgccca\n\ +aaagattgtcaacgaggagctccctcgcgtacctgtcgtccgtatcataaacgacgcgac\n\ +atgtacagcactccgaagtataagcaataataatgcgggtaatccagactagatcttttc\n\ +ggactcaatgcggtttcacggtaaacatgattaataccggagagtagtcgagcttatcag\n\ +cgatgcaagcgaattcattgtgccaggagatacgttgcagataaaaccggcaacgtatgt\n\ +caacaagttttggcgatctcgttgtttgtattcgacgaggcgcgggaacttcaagaacta\n\ +tcgtatattcaagtccattaccttttagtttcagactggtggagctgactaaagttatat\n\ +catcattttgtacactggtttagttaacgataatttcagatttaacatgaccagacgata\n\ +atcgctgtatatccagttggaatgtggtttgccagaaaggttaacttataatcaagcctc\n\ +tcttcagtcttgattcgtcgtatcccatccattgcgctatacctcagtgtatttggagct\n\ +gtagttataccgtgtgctaagatcagtagacatgacgagagcaatattatctaccttaca\n\ +agcatcaacggacgtctagtcggaacaaaagactctaaaactcgaacttcaggttaatat\n\ +actatagttctgtattcagcagttattcttatattcgatattatcttgcctattggatgt\n\ +ctgactttagtatattaatcatagtatctgccatgtaaaggtgccagtactaaatctgtt\n\ +tcacagtgcgaattataaacggttacaaccattaaagacaacaagaccctatagctttat\n\ +ttgaattttgtcaatgcgcaacttggagctcgcgatacatcccaattagtctatagggtc\n\ +gggacgattctacggcatttctggttataatgacaacatggattgtggcccgagaatcgc\n\ +tctttcattaattaagcaatcattacagtcttataagcgctacttccgagtggtagcagg\n\ +taactcgatataaggtcgcatgagccgaatagcttaaaaaacaggccaccgaacattgat\n\ +agagaataccgaccacagcgcaacctttgattactttcattaaattgtacggctcactcg\n\ +acatcaagcttaagattgcgataatgtgaactcaaatggatcagtactgaagaaccgtaa\n\ +cccacttcgcagaaagcgtacccagagaagatacgctgttacaatatacagggtgaaatt\n\ +attgcctgttcttcgtaaccatttcgccaaacttggttagaaatgatagccattcatgat\n\ +agaaataagctgaatgataccagtatctttaactatgtagtcagggggaagataacgatg\n\ +gtccatgtatgtttctgatatgtgacagtattggccgcgtaatttgctaacgaagctact\n\ +taatgcctttgagcttcatatagatttctttaatcaaaatcggcaaaaagatagtatgag\n\ +ctataatatatgctagtagagaactctggaccatcatctatatgaatactgattcgagcg\n\ +tgcaattactttagcctgcgtactactgactctacaaaacactctgagataagtttgtag\n\ +tcagtaagtcgctctctataaaccttttggatgaccattgtacagccacttatagatccc\n\ +aataaatagcacaggagacagagtttttcaatgctcgatcatttgccgatagtattttcg\n\ +tctaacctcagggcacctattatttgatacctaacctaacggccctttcacaatggagaa\n\ +atatatgacatcgggacaaacacaaatggtgggtggccaggagatatgacatggtggcgt\n\ +ctctaagaaacacggactccctctaggcaaactcacgtaaccaattttaatgtcaaacaa\n\ +aacgctcgaaaagattttgccgtgtaatgacctggtacattgactggtcaggaatacatc\n\ +actgtagttgccgtagtgtcctgttggtgttccatcaagacacatcgtataacgcaattt\n\ +acgacggacatcagatcaagttatacagattatttaagtatcacgtgtgcattgggacat\n\ +aagggatctcacacatgccttggaacatttttgctttgtgccgctttttcgctgcactac\n\ +caatccttacttaccagtatattcaaaggtcgttaacagaatgagaaaggttagggctct\n\ +aagttatcgtcgattgggatagacgagacatttgcgagcgccctccacggatacgaatct\n\ +cccatatcaatgtgaactggatgctatgcagtttagttcttacgtctcctagtggtaaaa\n\ +atcaaagtagcactcgcatagcagttattcagaacctaatacacaaaaccgtcaaacatt\n\ +ttctaattctaggtatgggccgatcataggagctaaggtgaaactcataaatgttttgtt\n\ +agatctagcatcctaaaaagatgcatatactgagtagctggcgtgcattctctcaattgt\n\ +atcctttttaactgaactagtcggtcccatttcgtgactgagatctattaaccgataaga\n\ +ttaataacactcgcattcgtatcagctcagagtgaagtttttcaataatttgactgatat\n\ +attaacttctaaaataaccctttaagcctcggatccgtttcccaatcacatcaaaaattc\n\ +ttattccaactatctacggattaacaacgtgcatggggatcgtagtaagaacttgttccg\n\ +atcactttgagtatatcaagttgacggcccggttattattgaatagaaacattcacctgc\n\ +taaattaaataccgcacatcggatacccgatttcagagggccgtcttactaagggcaggc\n\ +tttgttcggtttaactgagatgttcattattttacagtatgcttcaactaatatgtaacg\n\ +aaggacagtggatctgtctccatagtagatcttcagtcgtgaatttcataccgctcctat\n\ +ttaagttcgcgttcgagttgttgatcatggcacgtgaaagcaacccctagtattctagac\n\ +gaaaattttttctagttcatctgataatttgccaattcaaaaacaaccgctggtttcccg\n\ +gcgcattctctaaaatggaagtcgaacctagagccattatttgtcggtaacccatgagtt\n\ +ccttcttttcagaagttaatacactgtggtcctatacagaggaaaaacagcggttatata\n\ +cgatcgtggcataacaacattggatcaagatagcaatttggctacctattctaattctca\n\ +ctagattcggtattccactacaatatcggcagattaggattggatgaataatcggtgttt\n\ +aagtccggttgcgtctccaatctcctaatttttattaatattgatcttggtgacctattg\n\ +taaataaaaacttcaagactttgaataacggtgaaaagatagaagactcatttgaaaatg\n\ +gatcatccacagatccaaacattagcaagacactaatccccaactagctattctgatcgc\n\ +gatcgtgctgcagtactcctgtcacaatagtctgttcatgatctaattctttttgggctt\n\ +tgttcgatggtgattcagaatctttatccggtcgcttccctgtagctactttgtggggat\n\ +attgcccggggattatagggttgagatcgtttcctaaaagtatttaaaccaagtagactt\n\ +caactaaactacatcagaacatcgtgaagacaccatacgcggtacctttatttaccgata\n\ +acatttcttcaagaaataccggtaagcagcataatgaccctaaacagctcggggtatcgt\n\ +cgtagttttaaattttatttaggttactgctcaaggaataaaaactaactatttaattta\n\ +taataatattacaaggctcacactgattagatttgtctataagacttcgcgatcccccat\n\ +taccggattgtcttaagaataaactagataaaccatgcattttctagataaggcctttag\n\ +tctaattagatacaaaaaacacgatagttgcatccttaatttattgtgtcaaacctggaa\n\ +ccttttaattacccgcaaatcactttatgtcgagactacctctgaaatttattatctacc\n\ +taccgcatgaggacttgaaccatcttgtaggagttatgtttattagctaagattcgttta\n\ +tcctgtagcggtccatgtatattcaacaagcaaaaagcactcagaattgtttttagttga\n\ +gtcaagactgatatataaataagtttccctagttttttcgtggtgggacgatattgaatt\n\ +gaatcttaaccgaagagtttcccactctgtcgcacaataatacacgccaatatttccagc\n\ +cctgcttatgccttaatcggttactcaatctcccattgaagttcattttgatctgcatag\n\ +aagtttcgggcccagccttttttctgccaccttcctccaagctctgtagacgcactctaa\n\ +gattgatgctcacatgtattaattctacattaacataaatatataagtcatgcatcttcg\n\ +agtaaaatatctggttctccaacatgtcctggcacgtatcgttataatgcccatacatgt\n\ +agtattaaaatgattgggttaactggatattaagatcatcgaaattgtaaagtcaaatta\n\ +acaatactgtctcaagaccgtgtattcctcgtgctcggaagggctattacgcttacttcc\n\ +gttttggtatcttaatatgactttcaaaaattaagttgcagtgagtcctacctgcgtgca\n\ +tcggttagcaagagtataaaagttgtttaaacgaactacttgctttacaataccggtcgt\n\ +atatatcgccgtgaatccagaagattgtcttctttggattatcaaccgagatcctgtgga\n\ +ccgatgttttgggaccttcacagaggactccaggtagagctcgcttttgcattaatctaa\n\ +gaattgtacctctctaaaagatctaaaacagtgaatgtgtatttcatggaaaaacacaga\n\ +gaaacgtaaattactttaggccgaaaggcacatgagttattatacatatacgagatggtg\n\ +gtatacatcgaattcggggcatacactatagttgcattgtatttagctgctttaaataat\n\ +atgatattaccttccttacataagacattaccggcataccctggttttcaacttgtgggg\n\ +ctttttgacgatcgcactctcatttgatccgagtagggcggtgacccctgcttttcaaat\n\ +acaaaaatttcgctatgaaggtaatagattacttttcgctgttatgatagaaacggtaaa\n\ +tttaaaattgaaacttctagaaaagtaaagtaacgagaaatgattttgtgaataatgcgg\n\ +tcatgattgcgcaagtaagaaaaaaaggcaaaaggatgcgcggaatagaaacttatcagt\n\ +cacgggtatcttgatttcattcttcttgtcaattgccgacataggatgaaatcagattcc\n\ +aatgcaatacacagtaacccccacccttgattgtaatgtcgatttgaagttgtacgcgtc\n\ +gacgaagtggatagtatacgggccttttgtacggtgcgatcaactatgaatctcggcgag\n\ +ttagatggtcgtacaatctcacacatagaggtcacttgcctgtaatgacgaattttcggc\n\ +taggtactcgaactttattagaagtaaaaatgtgggcaaaagaaggattccattttacaa\n\ +gacgattacaatgagttacatgtctctcaacgtagtctttccctagtagtctttgaacta\n\ +tttaggtactccagaaaattttagcaaagggtttctgtgtgaatccgccattcatgttta\n\ +tgatggaacaataagaataacgccctcgtatgttatcgacagtgaagtcagcagttcggc\n\ +caaaaacatattcaatttagtacagatccccagaagttaagctaagtgctctaaaatggc\n\ +ctaaacggttatcaaagtaggtctaattactatactaacgggtgcatcgtaataactgct\n\ +gtcgatgcaacactatatgatagtgtcgttttgctatatatgtacaatgtgacaaagaag\n\ +ccttagcgattcttgcaaacttaggacttcggattctcaatcttaaatgtccgaaaacgc\n\ +aaagattcaaaaatttaatctatgagcagatatgcctgatggtgactacgcgtatgttaa\n\ +ggctaaatgttgacaaccgcacacataatcgaactattgatagtcgggagcataaccagg\n\ +tgaacgtactttgttcacgacatttattgacatgttctaaatacgtctcaaaatcacggc\n\ +gcactagaaaacgcaatcaaatcattgtcctggtttaagggccgtaatgccggtagtgtc\n\ +aaacttcatgagaactttagctggcttttggccagtatttagggaccaagagcactagcc\n\ +ttaagctgaatattttgccatttatctactgttataactttaaaacttggtggcaccaga\n\ +cttgtcgatacacacgcatcaatctgtaacgtaaaaggtttactaagaacaagcgtagga\n\ +attgagtttatattatatttaaactaaaagatgatattagcttctgagggcgatagggct\n\ +ccaaatcataaagaggaatatattattacacgattagaaacccacaacatacctcgaatc\n\ +gcccaaaagtttgacgaaacttggcagtactccacatctcagtaatacagttgggagagt\n\ +ctcaaatgttgttttattactcaatgaaccaccctcataatttcactgctgttccattaa\n\ +atttgcaaacgatcatttgctttgaagaaacgtaaaatcgacaaaattacagataagtag\n\ +atgcataataaaaaaaactgctcgctataacacgatcatcgtgcattcttacttaggagc\n\ +atcacccgcacaataacgtaccttaaactacaacactattagaccgagtactgtaattca\n\ +cgaaagctcaagctcgcattgtaaagaacttgctctctcgtaaaatgtgataatagtttg\n\ +cggagaggattcaattattttccattgcacctactccactagattcgataaaagaaggtg\n\ +gtcctcccttaaaaagaaatgttaagtaacatcggaaccataagcaaagcatgtaagtga\n\ +accgtcatccttccctaagaaacataaaggtttttaataatgtcgactgtgaactataac\n\ +tgcatcctttcctgacctactccggttccttgttgttatttctgaacgagaccagtagat\n\ +aaacaatgtaaaccacagtgggtaccaatggtgcatgtgacgctaccgttgttttaagtg\n\ +cccgtacaaacataagaagtcataatcttacttgaaattaattttgccttttattttttt\n\ +tcaggctcgaaattaatgatttgttttttttgaccttctagttacgctaatatgcggtcg\n\ +cctgtggtttctattgagtcctataacgggatgggatctaatacgtttggttactagtaa\n\ +acaaggtataaatttgataccggagtatcaactgtataacatcaagctttatgactcata\n\ +cgcgaagtaatgacacaaggctttcaggagatcgcgagtacagagccactaaggggtgta\n\ +ttacgatagtgacaccaccgagcgcactcactccccaagtagatttatgatcctacgcta\n\ +agtattagatatataaccaaagaggttctagtcagtgcaactcttagaataataattagc\n\ +cggttttgcctttttaggcctaatgcaatattcagctagcccttatgtatctcgcgttcc\n\ +acagcaccactcatggcacgcgtttaaactaatcaaatataatctatgaatgttatgcca\n\ +gtacttgaataaatcaggttttttataagtccttgcatactctcgttatatactgttaga\n\ +gtcttaccccatagaaattctttcatctgcaaacttagaagaattctcagctacggggag\n\ +cataaagtccccaggatgttgacaaatacaacaaatgtggcttatacaaacactccatat\n\ +gaaaatcgaaccctcgtggtagttttagccgaaccttgtacggataaatccctccatttt\n\ +ccaatagcagatacctatcctactacctcgtggtattaaattaaagcttgaaatatagag\n\ +ctgcatagcttatccaattcccaagcacgagtctaccgtcgtaaccacgatttgatttac\n\ +agacgctagagcaaacccatctttaaacatataagtaaaaattaaagggtgagtgcgtac\n\ +gtgtttactagcaacttcgcttattaagacaattgtttataagccataattaaaaacata\n\ +tgttcaacaggttcattgatatttgtaattgcacaggtttttaataaggatctacgtaag\n\ +tataatgaacaaactttttaccagagttatattctgtactttgaaaatgctcctctaccg\n\ +ccttagagactttcaattagattttttgcagttaatctatgcgtaagtgaaccatgcaag\n\ +ggatgcgattcaaccgcctcgtgctaaccctatcgtctgtctcataactgtaggtctaat\n\ +ataattttcagttttcgaacacataaccctttgaaaatctgctatttaatgtctcacctg\n\ +catgcactatcttctatactgctcagaacggctatacgtcactatgctccaagtgacgat\n\ +ttaaacgaagcaaggaataataggtttattttagtgcaaaacaattaagtgcggactacg\n\ +tgctctttacaataagccttgtgattgggctataggttaagtcccatattaacgatctcc\n\ +aatgtacaaaatcgacaatcgctttgcattacccggttactagtcgaattacagatagct\n\ +gttagatactcactctaattttggacaacaatcccaatcttggggtcgtctatcgcctga\n\ +agctcgtaaatccttccatcttaaacgattacatattatagacttgttcggggtagagat\n\ +atcacagttgtgcaaacattgtaaatcgatactagtttatgttggtagtctagttgcttt\n\ +taccattccccgaaaaacttgatctactatttcgacaacagtaaacttgaactaggtaag\n\ +tgaaaacagagaatgcctcatagtgccactatttgtccactatatgtaagtgtagcttta\n\ +cataatccactatgactgagatcattacggcctaggaaagcagcgtagaaaaaaagggcc\n\ +cggatattacgactgtaactataaaactagttactggtagcgcgccatgtatagatttgt\n\ +tttaccggttgtggttgcgttaacgaatttcagccgcgaaaattgatccgttaaccagtc\n\ +catctcgacttctataaaacgataaagtaaagttgatgttcagcctccttcttatggttg\n\ +catcgagagtacactactcagtgggaaatagatcggggttcctacttcagattgtattat\n\ +ctaggcaattgccgattgtgccatacctggataaaataagctacctacatgtgatgctta\n\ +tctattatcgtcatactaccttagggtgtcctgttgaacgctacattaatctttagccgt\n\ +ttgagatgttccaatggataggagtctaacgcatgatgaagtttaggaaggcagagcatc\n\ +ccactaagtatgtgacagtgtatttcgaaacgagacgttataaatagaaaaaaggtcctt\n\ +ctggttctattctgctgaactattgaatggaaagattggttgacctacgtactatttgct\n\ +tgaagtcatcaatttgacggggtgagagacatatggtgcatactttacggactctatatt\n\ +ttagatcagaagcttagcagtcttctctacaccccctcacgacataattgcttttaagaa\n\ +tctatgtttgattcctctacgggaattcggatccgttcgcatgtgcggtttatctaaacc\n\ +aggggacatatgttcagctaaagcatacgaacactttgctaactagacgtatgtatagta\n\ +gctataaatcccgacgatatttacaaaaagaaatgagactcaaatatatacatagcgacc\n\ +ctacacttattcgcaccctgatctaggcgatcctagcacccacacccgaaagtgagcact\n\ +agtgtcttccgtattaaatttactgcagttgagattttagttgtctactaaggattactc\n\ +taacccgtaataaggatcaagactcggtactagctttactatcattccctatgtgttttc\n\ +ctaactcacaagggtacgtaccagcctatgtaattacaataatgataaagacacaaagga\n\ +agtaactttacaaatgagtctccagttacactagcttagtccctcccatcttgctttgaa\n\ +gtctaaatacgcaatctctgaggatatacagcagaagaacactcataacgttggagtcca\n\ +agaattagactcatagggcccccaacatttaatatgtactgtgagtttgaaggtgttcta\n\ +ttgttaattcctgctcttgatacatgacacgtactccgtgtttaaggcttcggactgact\n\ +ttctttcataagttgagcaacgaaaatttcagaatcgataagttggattcactaactaat\n\ +acggctgattgaaaactccactccggacctatatggtcgacctttatacgtaaccgatat\n\ +aaaacttataggctggtatatcgagccttcctagcgcaatttcggatggggtttcttcta\n\ +ctactcaacaacggaatagtctttgtttagtaaaccagagctcaggacgcccaatacgta\n\ +ggagagcgctgtggagcatgtgtcattatggactggagcactcttaaatcactctgcgtg\n\ +tgctaaacgatagatcataacatgtcctgagtaaattttcttgatacgtcgcaatatacc\n\ +gttattagttaaacgttctcatccgtcatgcgtgaaatacggctgtcgtgctcagatata\n\ +ctattagcgactcatctcgcctaacacgcacacgtataaactcggaatgactgccgctct\n\ +tacatattagaaatacagactacaccacggaagcattgggtcattctcaaccgctgtata\n\ +aaagatgattagtcttataataagattaccaaagaggcagaatcatgggtagtaaatcta\n\ +ttattcaagtgattaccgtcgtgtaggcagggagtgaggacgagatggtactcaggacaa\n\ +atattaaccggacgaagtggtttacgtcgtactttcactattagtagtaaatacaaggta\n\ +acaccggggaatagtactaaatataatgatatctatcttcgggagaacgagtcgtctatt\n\ +gctttgaacattctcaaggcgtaaaatgtgctgacttatagcatgatacaaccgattgtt\n\ +acttttgtctattcaaaagattgaatagttttttatacaaaagccgcatacttatgacgg\n\ +ctagtatacagtttcatcccctagcatcaatgctatggacagtattgaacttataggaaa\n\ +ttcttctaatagggcaaatccgtcgtgatgcctattttttttcagtcacatcctcaaatg\n\ +gcactagtattgtcgggatcccattaacaggctcaaccacgagctcacgcgaggacatgt\n\ +agtccgtatctttaacgaagcgacagcgacagaactcccatggataaccaattataaggc\n\ +ccgtaatcctctagacatcgtttaccaataaatccgctttctccgtaatcatgttgaata\n\ +ccccagagtagtccagatgataaccgatgaaacacaagtctttctcaatgcacttacggt\n\ +gaacttattaccgccaacgtagctcatcaaggttgcgacatctagttgtgtgtttgcgac\n\ +gagcccagcgaacttcatcaactttcgtatattcaacgccttgtaattttactttaagac\n\ +gcctggtgatgtagattcttagataatcagtttgttatcggctgtactttaccataattt\n\ +cacaggtttcaggtcaagaagattatagctgtatatacagttccatgctcggtgcacaga\n\ +aacgtgatcggataataatcaatcgcttatgtcgtctttaggcgtatccaatacatgccc\n\ +cgataccgcagtgtatttcgacatgtaggtataccgtcgcatttgagctcgagtcaggac\n\ +gtcagctagattagattccttaatagaatataccgacctctagtccgaactaaactatag\n\ +ataacgccaacttcaggttaattgtctagtcgtctgtttgcagatgggattcttagatga\n\ +gtgagtatcggccatattggttcgagcactttagtttttgatgcataggatatgcaatgt\n\ +atagctgaaagtactttatctgtttcaaactcacattgattaaaccggtaaacctttaaa\n\ +gactacaagaaaatattcagtgagggcaattttgtcaatcacaatcttccagctagagat\n\ +acttcacaatttgtcttgaggctacgcaacattagacggattttcgcgttttattgaaat\n\ +aatcgaggggcccaagagtatccatagttcattttgtaagatttctttacaggcttatta\n\ +cagcttcttcagactcctacatgcttacgagttatatgctagcatgtgaacaatagatta\n\ +atatacaggaaaacgtacattgagagagatgaccctacacagcgcaaccgttgagtactt\n\ +tcattaaagggtaacgctctcgagacagcatccttaagatggccttattgtcaaatcatt\n\ +tgcagaagtacgcaagatccctaaccaacgtagaagaatccctacaaacacatgagacgc\n\ +ggtgaaaatagacagggtgttagtattcaatcttcggagtatcaatttcgccaatcttgg\n\ +tgagaaagcataccctttcttcagagaaagaagatcaatcataacactatctttaacgag\n\ +gtacgcacgcgcatcattacctgcctccatggatctttaggatagcggaaagtattggca\n\ +gcgtattgtgatttcgttcctactttatcaatttcacattcatatacatgtcttttatca\n\ +aaatcgccaataagataggatgagctatattagatgctagtagagttcgcgccaacatca\n\ +tcgataggaatactcaggacagcgtgataggacttttcaatccctaatactctctataat\n\ +tataactctctcttaagtttggaggcagtaacgcgctctatataatcagtttgctgcacc\n\ +attcttcagcctctgatacatacaaataaattccacagcagtaagagggtttaattgaga\n\ +catcttgggaacttaggattttactctaacatcaccgaaacgattattggataccgtacc\n\ +taaacgaactttctcaaggcagtaatataggacatccgcaataacacaaatgctgcctcc\n\ +ccaggagttatgtcttcctggaggctatatcttacacccactcactataggcaaactaaa\n\ +gtttaaatgttgattgtctaaaaaaaagatagataagagttggccggcgtagcacatgcg\n\ +aaagtgaatcgtaagctataattctctggacttgaagttctgtcctgttcctctgcaaga\n\ +aacaaacttcctttaaagctatttacgacgcacatctcagcaagttataaacatgttgga\n\ +agtttctagtcggaattcccaaagaacggatctatctaatgcattcctacatttttcctg\n\ +tctgccgatggtgccatcctattcaaagaatttcttaaaagtagattaaatgggactttt\n\ +aacaatgagtaaccttacgcctctaagggttcctcgagtgccatacaccagtcaggtccg\n\ +agccacatacacggagaacattctaacatagcattctcaactcgatcatttgcaggttac\n\ +ttctttcctatcctagtgctaaaaatcatacttgcaatcccatagcacggattaagaacc\n\ +taagaaacaattcagtaaaacatgttcgaattcttggtatgggaacatcattgcagctat\n\ +ggtctaacgcattaatgtttgggtacatcttccatcatataaacaggaagagtctgacga\n\ +cagggagtgcttgcgatcatgtctatcattgtgaaatcaaattgtagctcacatgtcgtc\n\ +tatgagagcgtgtatccgataagatttagaaaaatagaagtcgtataagatctcactgaa\n\ +cttttgaatgaatgtgaagcatatatgatctgctttaataaaactttatccataggatac\n\ +gtttccaaatcaattcaataattattagtcaaaatagataaggatgaacaacctgaaggc\n\ +cgatcggacgtagaaagtggtcccatcactttgagttgatattgttgaaccacacgttat\n\ +tatggttttcaaacagtctcaggatattgtatatacagataatccgataccagttgtctg\n\ +acgcccctcttacgtaccccaccctttgtgacgtttaaagcagttgttcagtattttaaa\n\ +ctaggcggcaactaatttggaaagaagcacagtggatatgtctaaattcttgttattcag\n\ +gcctgaatttaatacaccgcatagttaacttcgcggtagagttgttcatcatgcctcctc\n\ +taagctaccacttctatgatacaccaatagttgttctacggaatctgataattggccaag\n\ +tcataaacttccgctgcgttcaacccccttgctcgaatatccaactcgaaaagacagcct\n\ +tttggtgtccggaacaaatcagttacttcttttctgatgttaattctctgtggtcagata\n\ +cagaccaaaaactccgcggatttaccatcctccaagaacaaatttgcatcaacatagcat\n\ +tttggctacatattctaagtctcaatagtttaggttttcaactacattatcccaacatta\n\ +ggattggaggaataatagctgggtaagtccccttgcgtctacaatcgactattttttatg\n\ +aatatgcttctgccgcacctatggttattaaaaaagtcatgactttgaagaaccctgaaa\n\ +agatagatgaatcaggtgtaatggcagcagccaaagagcatataattagcaacactctaa\n\ +gaacattatagatatgatgatagcgatcgtcatgatgttatccggtcacaatagtagctt\n\ +catcagctaattcgttttgccagtggtgacttgcgctggaagaatcgttatacggtccct\n\ +tccctcttgatacggtgggggcttattcaaccgcgtggattgggttgtcatacttgcatt\n\ +aaacgatgtaaaccatctagtagtcaactatactaaatcacaaaatagtgatcaatacat\n\ +acccgcttcatggttttaaccatttaattgattaaagatattccgctaagaaccattatc\n\ +tacctaaactgatcgccgtatcctagtagtttgaaatttgatgtaccgtaatgatcaacg\n\ +aagtaaaacgttatattgtatgtagaataataggtcttggagctaaatgatgtgattggt\n\ +agtgaagacttacccttacaactttaccggtttctcggaagaatatactagagaatcaat\n\ +gcatgggctacataagcactttagtctaatgagataaaaaatacacgagtcttccatcat\n\ +gaattttttgtcgaaaaactcgaacctggtaatttaaaccatatatctttatgtcgtcaa\n\ +taactctcatatgttttatataacttcccaatcacgacttgtaactgcttgttcgactga\n\ +gctgtttgagctatgaggccgggatccggttgagctacatctatttgctacaagaaaaat\n\ +gaaagcacatttgttgggagttctggctacactcatagagaaataagtggcccgagtggg\n\ +tgcggcctgcctccatattcaagtgtatcttaaaccaagtggttccaacgctcgcgctaa\n\ +agaattaaagcctttatttcctccacggagtagcccgtaatccggttcgaaagagaccat\n\ +tgaagttaattttcatatccagtgaagtttaggcacaagcatgtgttctgccacatgcct\n\ +caaagcgctcttcaaccaagatatgattcatcctaacttcgatgaatgcgtctgtaacat\n\ +aaatatagaaggaatgattcggcgagttaattttcgccttctccaacatggcatccctac\n\ +gttcgttataaggaccatacatgtaggttttaaaggtttgcggttaatcgatatttacat\n\ +catagaaattctatagtcaaatttacaagactctagatactcactcgttgcagccggcta\n\ +ggaagcgctttgtaccttacttcccttttcgttgcgtaatatgaatttcatatagtaagt\n\ +tcaaggcactcatacctccgtgaagagggtagatagactattaaagttgtttaatagtac\n\ +gtattgatggaaatgacccgtaggagatttaccactcaatccacaagattcgctgctgtg\n\ +cattatcaaaacagtgcatgtcgaaacatgggttgggtccttcaaacacgaatccaggta\n\ +gagatacctttgcaattttt\n"; + +dnaInput = dnaInput + dnaInput + dnaInput; + +var ilen, clen, + seqs = [ + /agggtaaa|tttaccct/ig, + /[cgt]gggtaaa|tttaccc[acg]/ig, + /a[act]ggtaaa|tttacc[agt]t/ig, + /ag[act]gtaaa|tttac[agt]ct/ig, + /agg[act]taaa|ttta[agt]cct/ig, + /aggg[acg]aaa|ttt[cgt]ccct/ig, + /agggt[cgt]aa|tt[acg]accct/ig, + /agggta[cgt]a|t[acg]taccct/ig, + /agggtaa[cgt]|[acg]ttaccct/ig], + subs = { + B: '(c|g|t)', D: '(a|g|t)', H: '(a|c|t)', K: '(g|t)', + M: '(a|c)', N: '(a|c|g|t)', R: '(a|g)', S: '(c|t)', + V: '(a|c|g)', W: '(a|t)', Y: '(c|t)' } + +ilen = dnaInput.length; + +// There is no in-place substitution +dnaInput = dnaInput.replace(/>.*\n|\n/g,"") +clen = dnaInput.length + +var dnaOutputString = ""; + +for(i in seqs) + dnaOutputString += seqs[i].source + " " + (dnaInput.match(seqs[i]) || []).length + "\n"; + // match returns null if no matches, so replace with empty + +for(k in subs) + dnaInput = dnaInput.replace(k, subs[k]) // FIXME: Would like this to be a global substitution in a future version of SunSpider. + // search string, replacement string, flags + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/string-base64.html b/build/pgo/js-input/sunspider/string-base64.html new file mode 100644 index 0000000000..53280ef2bb --- /dev/null +++ b/build/pgo/js-input/sunspider/string-base64.html @@ -0,0 +1,151 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider string-base64</title> + +</head> + +<body> +<h3>string-base64</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +/* 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/. */ + +// From: http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956 + +/* Convert data (an array of integers) to a Base64 string. */ +var toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +var base64Pad = '='; + +function toBase64(data) { + var result = ''; + var length = data.length; + var i; + // Convert every three bytes to 4 ascii characters. + for (i = 0; i < (length - 2); i += 3) { + result += toBase64Table[data[i] >> 2]; + result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)]; + result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)]; + result += toBase64Table[data[i+2] & 0x3f]; + } + + // Convert the remaining 1 or 2 bytes, pad out to 4 characters. + if (length%3) { + i = length - (length%3); + result += toBase64Table[data[i] >> 2]; + if ((length%3) == 2) { + result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)]; + result += toBase64Table[(data[i+1] & 0x0f) << 2]; + result += base64Pad; + } else { + result += toBase64Table[(data[i] & 0x03) << 4]; + result += base64Pad + base64Pad; + } + } + + return result; +} + +/* Convert Base64 data to a string */ +var toBinaryTable = [ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +]; + +function base64ToString(data) { + var result = ''; + var leftbits = 0; // number of bits decoded, but yet to be appended + var leftdata = 0; // bits decoded, but yet to be appended + + // Convert one by one. + for (var i = 0; i < data.length; i++) { + var c = toBinaryTable[data.charCodeAt(i) & 0x7f]; + var padding = (data[i] == base64Pad); + // Skip illegal characters and whitespace + if (c == -1) continue; + + // Collect data into leftdata, update bitcount + leftdata = (leftdata << 6) | c; + leftbits += 6; + + // If we have 8 or more bits, append 8 bits to the result + if (leftbits >= 8) { + leftbits -= 8; + // Append if not padding. + if (!padding) + result += String.fromCharCode((leftdata >> leftbits) & 0xff); + leftdata &= (1 << leftbits) - 1; + } + } + + // If there are any bits left, the base64 string was corrupted + if (leftbits) + throw Components.Exception('Corrupted base64 string'); + + return result; +} + +var str = ""; + +for ( var i = 0; i < 8192; i++ ) + str += String.fromCharCode( (25 * Math.random()) + 97 ); + +for ( var i = 8192; i <= 16384; i *= 2 ) { + + var base64; + + base64 = toBase64(str); + base64ToString(base64); + + // Double the string + str += str; +} + +toBinaryTable = null; + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/string-fasta.html b/build/pgo/js-input/sunspider/string-fasta.html new file mode 100644 index 0000000000..240e60147c --- /dev/null +++ b/build/pgo/js-input/sunspider/string-fasta.html @@ -0,0 +1,135 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider string-fasta</title> + +</head> + +<body> +<h3>string-fasta</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// The Great Computer Language Shootout +// http://shootout.alioth.debian.org +// +// Contributed by Ian Osgood + +var last = 42, A = 3877, C = 29573, M = 139968; + +function rand(max) { + last = (last * A + C) % M; + return max * last / M; +} + +var ALU = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +var IUB = { + a:0.27, c:0.12, g:0.12, t:0.27, + B:0.02, D:0.02, H:0.02, K:0.02, + M:0.02, N:0.02, R:0.02, S:0.02, + V:0.02, W:0.02, Y:0.02 +} + +var HomoSap = { + a: 0.3029549426680, + c: 0.1979883004921, + g: 0.1975473066391, + t: 0.3015094502008 +} + +function makeCumulative(table) { + var last = null; + for (var c in table) { + if (last) table[c] += table[last]; + last = c; + } +} + +function fastaRepeat(n, seq) { + var seqi = 0, lenOut = 60; + while (n>0) { + if (n<lenOut) lenOut = n; + if (seqi + lenOut < seq.length) { + ret = seq.substring(seqi, seqi+lenOut); + seqi += lenOut; + } else { + var s = seq.substring(seqi); + seqi = lenOut - s.length; + ret = s + seq.substring(0, seqi); + } + n -= lenOut; + } +} + +function fastaRandom(n, table) { + var line = new Array(60); + makeCumulative(table); + while (n>0) { + if (n<line.length) line = new Array(n); + for (var i=0; i<line.length; i++) { + var r = rand(1); + for (var c in table) { + if (r < table[c]) { + line[i] = c; + break; + } + } + } + ret = line.join(''); + n -= line.length; + } +} + +var ret; + +var count = 7; +ret = fastaRepeat(2*count*100000, ALU); +ret = fastaRandom(3*count*1000, IUB); +ret = fastaRandom(5*count*1000, HomoSap); + + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/string-tagcloud.html b/build/pgo/js-input/sunspider/string-tagcloud.html new file mode 100644 index 0000000000..893a927acd --- /dev/null +++ b/build/pgo/js-input/sunspider/string-tagcloud.html @@ -0,0 +1,315 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider string-tagcloud</title> + +</head> + +<body> +<h3>string-tagcloud</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + Portions from: + json.js + 2007-10-10 + + Public Domain +*/ + +// This test parses a JSON string giving tag names and popularity, and +// generates html markup for a "tagcloud" view. + +if (!Object.prototype.toJSONString) { + + Array.prototype.toJSONString = function (w) { + var a = [], // The array holding the partial texts. + i, // Loop counter. + l = this.length, + v; // The value to be stringified. + + for (i = 0; i < l; i += 1) { + v = this[i]; + switch (typeof v) { + case 'object': + + if (v && typeof v.toJSONString === 'function') { + a.push(v.toJSONString(w)); + } else { + a.push('null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(v.toJSONString()); + break; + default: + a.push('null'); + } + } + + return '[' + a.join(',') + ']'; + }; + + + Boolean.prototype.toJSONString = function () { + return String(this); + }; + + + Date.prototype.toJSONString = function () { + + function f(n) { + + return n < 10 ? '0' + n : n; + } + + return '"' + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z"'; + }; + + + Number.prototype.toJSONString = function () { + + return isFinite(this) ? String(this) : 'null'; + }; + + + Object.prototype.toJSONString = function (w) { + var a = [], // The array holding the partial texts. + k, // The current key. + i, // The loop counter. + v; // The current value. + + if (w) { + for (i = 0; i < w.length; i += 1) { + k = w[i]; + if (typeof k === 'string') { + v = this[k]; + switch (typeof v) { + case 'object': + + if (v) { + if (typeof v.toJSONString === 'function') { + a.push(k.toJSONString() + ':' + + v.toJSONString(w)); + } + } else { + a.push(k.toJSONString() + ':null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(k.toJSONString() + ':' + v.toJSONString()); + + } + } + } + } else { + + for (k in this) { + if (typeof k === 'string' && + Object.prototype.hasOwnProperty.apply(this, [k])) { + v = this[k]; + switch (typeof v) { + case 'object': + + if (v) { + if (typeof v.toJSONString === 'function') { + a.push(k.toJSONString() + ':' + + v.toJSONString()); + } + } else { + a.push(k.toJSONString() + ':null'); + } + break; + + case 'string': + case 'number': + case 'boolean': + a.push(k.toJSONString() + ':' + v.toJSONString()); + + } + } + } + } + + return '{' + a.join(',') + '}'; + }; + + + (function (s) { + + var m = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }; + + + s.parseJSON = function (filter) { + var j; + + function walk(k, v) { + var i, n; + if (v && typeof v === 'object') { + for (i in v) { + if (Object.prototype.hasOwnProperty.apply(v, [i])) { + n = walk(i, v[i]); + if (n !== undefined) { + v[i] = n; + } + } + } + } + return filter(k, v); + } + + if (/^[\],:{}\s]*$/.test(this.replace(/\\./g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + + j = eval('(' + this + ')'); + + return typeof filter === 'function' ? walk('', j) : j; + } + + throw new SyntaxError('parseJSON'); + }; + + + s.toJSONString = function () { + + if (/["\\\x00-\x1f]/.test(this)) { + return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) { + var c = m[a]; + if (c) { + return c; + } + c = a.charCodeAt(); + return '\\u00' + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + }) + '"'; + } + return '"' + this + '"'; + }; + })(String.prototype); +} + +var tagInfoJSON = '[\n {\n \"tag\": "titillation",\n \"popularity\": 4294967296\n },\n {\n \"tag\": "foamless",\n \"popularity\": 1257718401\n },\n {\n \"tag\": "snarler",\n \"popularity\": 613166183\n },\n {\n \"tag\": "multangularness",\n \"popularity\": 368304452\n },\n {\n \"tag\": "Fesapo unventurous",\n \"popularity\": 248026512\n },\n {\n \"tag\": "esthesioblast",\n \"popularity\": 179556755\n },\n {\n \"tag\": "echeneidoid",\n \"popularity\": 136641578\n },\n {\n \"tag\": "embryoctony",\n \"popularity\": 107852576\n },\n {\n \"tag\": "undilatory",\n \"popularity\": 87537981\n },\n {\n \"tag\": "predisregard",\n \"popularity\": 72630939\n },\n {\n \"tag\": "allergenic",\n \"popularity\": 61345190\n },\n {\n \"tag\": "uncloudy",\n \"popularity\": 52580571\n },\n {\n \"tag\": "unforeseeably",\n \"popularity\": 45628109\n },\n {\n \"tag\": "sturniform",\n \"popularity\": 40013489\n },\n {\n \"tag\": "anesthetize",\n \"popularity\": 35409226\n },\n {\n \"tag\": "ametabolia",\n \"popularity\": 31583050\n },\n {\n \"tag\": "angiopathy",\n \"popularity\": 28366350\n },\n {\n \"tag\": "sultanaship",\n \"popularity\": 25634218\n },\n {\n \"tag\": "Frenchwise",\n \"popularity\": 23292461\n },\n {\n \"tag\": "cerviconasal",\n \"popularity\": 21268909\n },\n {\n \"tag\": "mercurialness",\n \"popularity\": 19507481\n },\n {\n \"tag\": "glutelin venditate",\n \"popularity\": 17964042\n },\n {\n \"tag\": "acred overblack",\n \"popularity\": 16603454\n },\n {\n \"tag\": "Atik",\n \"popularity\": 15397451\n },\n {\n \"tag\": "puncturer",\n \"popularity\": 14323077\n },\n {\n \"tag\": "pukatea",\n \"popularity\": 13361525\n },\n {\n \"tag\": "suberize",\n \"popularity\": 12497261\n },\n {\n \"tag\": "Godfrey",\n \"popularity\": 11717365\n },\n {\n \"tag\": "tetraptote",\n \"popularity\": 11011011\n },\n {\n \"tag\": "lucidness",\n \"popularity\": 10369074\n },\n {\n \"tag\": "tartness",\n \"popularity\": 9783815\n },\n {\n \"tag\": "axfetch",\n \"popularity\": 9248634\n },\n {\n \"tag\": "preacquittal",\n \"popularity\": 8757877\n },\n {\n \"tag\": "matris",\n \"popularity\": 8306671\n },\n {\n \"tag\": "hyphenate",\n \"popularity\": 7890801\n },\n {\n \"tag\": "semifabulous",\n \"popularity\": 7506606\n },\n {\n \"tag\": "oppressiveness",\n \"popularity\": 7150890\n },\n {\n \"tag\": "Protococcales",\n \"popularity\": 6820856\n },\n {\n \"tag\": "unpreventive",\n \"popularity\": 6514045\n },\n {\n \"tag\": "Cordia",\n \"popularity\": 6228289\n },\n {\n \"tag\": "Wakamba leaflike",\n \"popularity\": 5961668\n },\n {\n \"tag\": "dacryoma",\n \"popularity\": 5712480\n },\n {\n \"tag\": "inguinal",\n \"popularity\": 5479211\n },\n {\n \"tag\": "responseless",\n \"popularity\": 5260507\n },\n {\n \"tag\": "supplementarily",\n \"popularity\": 5055158\n },\n {\n \"tag\": "emu",\n \"popularity\": 4862079\n },\n {\n \"tag\": "countermeet",\n \"popularity\": 4680292\n },\n {\n \"tag\": "purrer",\n \"popularity\": 4508918\n },\n {\n \"tag\": "Corallinaceae",\n \"popularity\": 4347162\n },\n {\n \"tag\": "speculum",\n \"popularity\": 4194304\n },\n {\n \"tag\": "crimpness",\n \"popularity\": 4049690\n },\n {\n \"tag\": "antidetonant",\n \"popularity\": 3912727\n },\n {\n \"tag\": "topeewallah",\n \"popularity\": 3782875\n },\n {\n \"tag\": "fidalgo ballant",\n \"popularity\": 3659640\n },\n {\n \"tag\": "utriculose",\n \"popularity\": 3542572\n },\n {\n \"tag\": "testata",\n \"popularity\": 3431259\n },\n {\n \"tag\": "beltmaking",\n \"popularity\": 3325322\n },\n {\n \"tag\": "necrotype",\n \"popularity\": 3224413\n },\n {\n \"tag\": "ovistic",\n \"popularity\": 3128215\n },\n {\n \"tag\": "swindlership",\n \"popularity\": 3036431\n },\n {\n \"tag\": "augustal",\n \"popularity\": 2948792\n },\n {\n \"tag\": "Titoist",\n \"popularity\": 2865047\n },\n {\n \"tag\": "trisoctahedral",\n \"popularity\": 2784963\n },\n {\n \"tag\": "sequestrator",\n \"popularity\": 2708327\n },\n {\n \"tag\": "sideburns",\n \"popularity\": 2634939\n },\n {\n \"tag\": "paraphrasia",\n \"popularity\": 2564616\n },\n {\n \"tag\": "graminology unbay",\n \"popularity\": 2497185\n },\n {\n \"tag\": "acaridomatium emargination",\n \"popularity\": 2432487\n },\n {\n \"tag\": "roofward",\n \"popularity\": 2370373\n },\n {\n \"tag\": "lauder",\n \"popularity\": 2310705\n },\n {\n \"tag\": "subjunctive",\n \"popularity\": 2253354\n },\n {\n \"tag\": "subelongate",\n \"popularity\": 2198199\n },\n {\n \"tag\": "guacimo",\n \"popularity\": 2145128\n },\n {\n \"tag\": "cockade",\n \"popularity\": 2094033\n },\n {\n \"tag\": "misgauge",\n \"popularity\": 2044818\n },\n {\n \"tag\": "unexpensive",\n \"popularity\": 1997388\n },\n {\n \"tag\": "chebel",\n \"popularity\": 1951657\n },\n {\n \"tag\": "unpursuing",\n \"popularity\": 1907543\n },\n {\n \"tag\": "kilobar",\n \"popularity\": 1864969\n },\n {\n \"tag\": "obsecration",\n \"popularity\": 1823863\n },\n {\n \"tag\": "nacarine",\n \"popularity\": 1784157\n },\n {\n \"tag\": "spirituosity",\n \"popularity\": 1745787\n },\n {\n \"tag\": "movableness deity",\n \"popularity\": 1708692\n },\n {\n \"tag\": "exostracism",\n \"popularity\": 1672816\n },\n {\n \"tag\": "archipterygium",\n \"popularity\": 1638104\n },\n {\n \"tag\": "monostrophic",\n \"popularity\": 1604506\n },\n {\n \"tag\": "gynecide",\n \"popularity\": 1571974\n },\n {\n \"tag\": "gladden",\n \"popularity\": 1540462\n },\n {\n \"tag\": "throughbred",\n \"popularity\": 1509927\n },\n {\n \"tag\": "groper",\n \"popularity\": 1480329\n },\n {\n \"tag\": "Xenosaurus",\n \"popularity\": 1451628\n },\n {\n \"tag\": "photoetcher",\n \"popularity\": 1423788\n },\n {\n \"tag\": "glucosid",\n \"popularity\": 1396775\n },\n {\n \"tag\": "Galtonian",\n \"popularity\": 1370555\n },\n {\n \"tag\": "mesosporic",\n \"popularity\": 1345097\n },\n {\n \"tag\": "theody",\n \"popularity\": 1320370\n },\n {\n \"tag\": "zaffer",\n \"popularity\": 1296348\n },\n {\n \"tag\": "probiology",\n \"popularity\": 1273003\n },\n {\n \"tag\": "rhizomic",\n \"popularity\": 1250308\n },\n {\n \"tag\": "superphosphate",\n \"popularity\": 1228240\n },\n {\n \"tag\": "Hippolytan",\n \"popularity\": 1206776\n },\n {\n \"tag\": "garget",\n \"popularity\": 1185892\n },\n {\n \"tag\": "diploplacula",\n \"popularity\": 1165568\n },\n {\n \"tag\": "orohydrographical",\n \"popularity\": 1145785\n },\n {\n \"tag\": "enhypostatize",\n \"popularity\": 1126521\n },\n {\n \"tag\": "polisman",\n \"popularity\": 1107759\n },\n {\n \"tag\": "acetometer",\n \"popularity\": 1089482\n },\n {\n \"tag\": "unsnatched",\n \"popularity\": 1071672\n },\n {\n \"tag\": "yabber",\n \"popularity\": 1054313\n },\n {\n \"tag\": "demiwolf",\n \"popularity\": 1037390\n },\n {\n \"tag\": "chromascope",\n \"popularity\": 1020888\n },\n {\n \"tag\": "seamanship",\n \"popularity\": 1004794\n },\n {\n \"tag\": "nonfenestrated",\n \"popularity\": 989092\n },\n {\n \"tag\": "hydrophytism",\n \"popularity\": 973771\n },\n {\n \"tag\": "dotter",\n \"popularity\": 958819\n },\n {\n \"tag\": "thermoperiodism",\n \"popularity\": 944222\n },\n {\n \"tag\": "unlawyerlike",\n \"popularity\": 929970\n },\n {\n \"tag\": "enantiomeride citywards",\n \"popularity\": 916052\n },\n {\n \"tag\": "unmetallurgical",\n \"popularity\": 902456\n },\n {\n \"tag\": "prickled",\n \"popularity\": 889174\n },\n {\n \"tag\": "strangerwise manioc",\n \"popularity\": 876195\n },\n {\n \"tag\": "incisorial",\n \"popularity\": 863510\n },\n {\n \"tag\": "irrationalize",\n \"popularity\": 851110\n },\n {\n \"tag\": "nasology",\n \"popularity\": 838987\n },\n {\n \"tag\": "fatuism",\n \"popularity\": 827131\n },\n {\n \"tag\": "Huk",\n \"popularity\": 815535\n },\n {\n \"tag\": "properispomenon",\n \"popularity\": 804192\n },\n {\n \"tag\": "unpummelled",\n \"popularity\": 793094\n },\n {\n \"tag\": "technographically",\n \"popularity\": 782233\n },\n {\n \"tag\": "underfurnish",\n \"popularity\": 771603\n },\n {\n \"tag\": "sinter",\n \"popularity\": 761198\n },\n {\n \"tag\": "lateroanterior",\n \"popularity\": 751010\n },\n {\n \"tag\": "nonpersonification",\n \"popularity\": 741034\n },\n {\n \"tag\": "Sitophilus",\n \"popularity\": 731264\n },\n {\n \"tag\": "unstudded overexerted",\n \"popularity\": 721694\n },\n {\n \"tag\": "tracheation",\n \"popularity\": 712318\n },\n {\n \"tag\": "thirteenth begloze",\n \"popularity\": 703131\n },\n {\n \"tag\": "bespice",\n \"popularity\": 694129\n },\n {\n \"tag\": "doppia",\n \"popularity\": 685305\n },\n {\n \"tag\": "unadorned",\n \"popularity\": 676656\n },\n {\n \"tag\": "dovelet engraff",\n \"popularity\": 668176\n },\n {\n \"tag\": "diphyozooid",\n \"popularity\": 659862\n },\n {\n \"tag\": "mure",\n \"popularity\": 651708\n },\n {\n \"tag\": "Tripitaka",\n \"popularity\": 643710\n },\n {\n \"tag\": "Billjim",\n \"popularity\": 635865\n },\n {\n \"tag\": "pyramidical",\n \"popularity\": 628169\n },\n {\n \"tag\": "circumlocutionist",\n \"popularity\": 620617\n },\n {\n \"tag\": "slapstick",\n \"popularity\": 613207\n },\n {\n \"tag\": "preobedience",\n \"popularity\": 605934\n },\n {\n \"tag\": "unfriarlike",\n \"popularity\": 598795\n },\n {\n \"tag\": "microchromosome",\n \"popularity\": 591786\n },\n {\n \"tag\": "Orphicism",\n \"popularity\": 584905\n },\n {\n \"tag\": "peel",\n \"popularity\": 578149\n },\n {\n \"tag\": "obediential",\n \"popularity\": 571514\n },\n {\n \"tag\": "Peripatidea",\n \"popularity\": 564997\n },\n {\n \"tag\": "undoubtful",\n \"popularity\": 558596\n },\n {\n \"tag\": "lodgeable",\n \"popularity\": 552307\n },\n {\n \"tag\": "pustulated woodchat",\n \"popularity\": 546129\n },\n {\n \"tag\": "antepast",\n \"popularity\": 540057\n },\n {\n \"tag\": "sagittoid matrimoniously",\n \"popularity\": 534091\n },\n {\n \"tag\": "Albizzia",\n \"popularity\": 528228\n },\n {\n \"tag\": "Elateridae unnewness",\n \"popularity\": 522464\n },\n {\n \"tag\": "convertingness",\n \"popularity\": 516798\n },\n {\n \"tag\": "Pelew",\n \"popularity\": 511228\n },\n {\n \"tag\": "recapitulation",\n \"popularity\": 505751\n },\n {\n \"tag\": "shack",\n \"popularity\": 500365\n },\n {\n \"tag\": "unmellowed",\n \"popularity\": 495069\n },\n {\n \"tag\": "pavis capering",\n \"popularity\": 489859\n },\n {\n \"tag\": "fanfare",\n \"popularity\": 484735\n },\n {\n \"tag\": "sole",\n \"popularity\": 479695\n },\n {\n \"tag\": "subarcuate",\n \"popularity\": 474735\n },\n {\n \"tag\": "multivious",\n \"popularity\": 469856\n },\n {\n \"tag\": "squandermania",\n \"popularity\": 465054\n },\n {\n \"tag\": "scintle",\n \"popularity\": 460329\n },\n {\n \"tag\": "hash chirognomic",\n \"popularity\": 455679\n },\n {\n \"tag\": "linseed",\n \"popularity\": 451101\n },\n {\n \"tag\": "redoubtable",\n \"popularity\": 446596\n },\n {\n \"tag\": "poachy reimpact",\n \"popularity\": 442160\n },\n {\n \"tag\": "limestone",\n \"popularity\": 437792\n },\n {\n \"tag\": "serranid",\n \"popularity\": 433492\n },\n {\n \"tag\": "pohna",\n \"popularity\": 429258\n },\n {\n \"tag\": "warwolf",\n \"popularity\": 425088\n },\n {\n \"tag\": "ruthenous",\n \"popularity\": 420981\n },\n {\n \"tag\": "dover",\n \"popularity\": 416935\n },\n {\n \"tag\": "deuteroalbumose",\n \"popularity\": 412950\n },\n {\n \"tag\": "pseudoprophetic",\n \"popularity\": 409025\n },\n {\n \"tag\": "dissoluteness",\n \"popularity\": 405157\n },\n {\n \"tag\": "preinvention",\n \"popularity\": 401347\n },\n {\n \"tag\": "swagbellied",\n \"popularity\": 397592\n },\n {\n \"tag\": "Ophidia",\n \"popularity\": 393892\n },\n {\n \"tag\": "equanimity",\n \"popularity\": 390245\n },\n {\n \"tag\": "troutful",\n \"popularity\": 386651\n },\n {\n \"tag\": "uke",\n \"popularity\": 383108\n },\n {\n \"tag\": "preacquaint",\n \"popularity\": 379616\n },\n {\n \"tag\": "shoq",\n \"popularity\": 376174\n },\n {\n \"tag\": "yox",\n \"popularity\": 372780\n },\n {\n \"tag\": "unelemental",\n \"popularity\": 369434\n },\n {\n \"tag\": "Yavapai",\n \"popularity\": 366134\n },\n {\n \"tag\": "joulean",\n \"popularity\": 362880\n },\n {\n \"tag\": "dracontine",\n \"popularity\": 359672\n },\n {\n \"tag\": "hardmouth",\n \"popularity\": 356507\n },\n {\n \"tag\": "sylvanize",\n \"popularity\": 353386\n },\n {\n \"tag\": "intraparenchymatous meadowbur",\n \"popularity\": 350308\n },\n {\n \"tag\": "uncharily",\n \"popularity\": 347271\n },\n {\n \"tag\": "redtab flexibly",\n \"popularity\": 344275\n },\n {\n \"tag\": "centervelic",\n \"popularity\": 341319\n },\n {\n \"tag\": "unravellable",\n \"popularity\": 338403\n },\n {\n \"tag\": "infortunately",\n \"popularity\": 335526\n },\n {\n \"tag\": "cannel",\n \"popularity\": 332687\n },\n {\n \"tag\": "oxyblepsia",\n \"popularity\": 329885\n },\n {\n \"tag\": "Damon",\n \"popularity\": 327120\n },\n {\n \"tag\": "etherin",\n \"popularity\": 324391\n },\n {\n \"tag\": "luminal",\n \"popularity\": 321697\n },\n {\n \"tag\": "interrogatorily presbyte",\n \"popularity\": 319038\n },\n {\n \"tag\": "hemiclastic",\n \"popularity\": 316414\n },\n {\n \"tag\": "poh flush",\n \"popularity\": 313823\n },\n {\n \"tag\": "Psoroptes",\n \"popularity\": 311265\n },\n {\n \"tag\": "dispirit",\n \"popularity\": 308740\n },\n {\n \"tag\": "nashgab",\n \"popularity\": 306246\n },\n {\n \"tag\": "Aphidiinae",\n \"popularity\": 303784\n },\n {\n \"tag\": "rhapsody nonconstruction",\n \"popularity\": 301353\n },\n {\n \"tag\": "Osmond",\n \"popularity\": 298952\n },\n {\n \"tag\": "Leonis",\n \"popularity\": 296581\n },\n {\n \"tag\": "Lemnian",\n \"popularity\": 294239\n },\n {\n \"tag\": "acetonic gnathonic",\n \"popularity\": 291926\n },\n {\n \"tag\": "surculus",\n \"popularity\": 289641\n },\n {\n \"tag\": "diagonally",\n \"popularity\": 287384\n },\n {\n \"tag\": "counterpenalty",\n \"popularity\": 285154\n },\n {\n \"tag\": "Eugenie",\n \"popularity\": 282952\n },\n {\n \"tag\": "hornbook",\n \"popularity\": 280776\n },\n {\n \"tag\": "miscoin",\n \"popularity\": 278626\n },\n {\n \"tag\": "admi",\n \"popularity\": 276501\n },\n {\n \"tag\": "Tarmac",\n \"popularity\": 274402\n },\n {\n \"tag\": "inexplicable",\n \"popularity\": 272328\n },\n {\n \"tag\": "rascallion",\n \"popularity\": 270278\n },\n {\n \"tag\": "dusterman",\n \"popularity\": 268252\n },\n {\n \"tag\": "osteostomous unhoroscopic",\n \"popularity\": 266250\n },\n {\n \"tag\": "spinibulbar",\n \"popularity\": 264271\n },\n {\n \"tag\": "phototelegraphically",\n \"popularity\": 262315\n },\n {\n \"tag\": "Manihot",\n \"popularity\": 260381\n },\n {\n \"tag\": "neighborhood",\n \"popularity\": 258470\n },\n {\n \"tag\": "Vincetoxicum",\n \"popularity\": 256581\n },\n {\n \"tag\": "khirka",\n \"popularity\": 254713\n },\n {\n \"tag\": "conscriptive",\n \"popularity\": 252866\n },\n {\n \"tag\": "synechthran",\n \"popularity\": 251040\n },\n {\n \"tag\": "Guttiferales",\n \"popularity\": 249235\n },\n {\n \"tag\": "roomful",\n \"popularity\": 247450\n },\n {\n \"tag\": "germinal",\n \"popularity\": 245685\n },\n {\n \"tag\": "untraitorous",\n \"popularity\": 243939\n },\n {\n \"tag\": "nondissenting",\n \"popularity\": 242213\n },\n {\n \"tag\": "amotion",\n \"popularity\": 240506\n },\n {\n \"tag\": "badious",\n \"popularity\": 238817\n },\n {\n \"tag\": "sumpit",\n \"popularity\": 237147\n },\n {\n \"tag\": "ectozoic",\n \"popularity\": 235496\n },\n {\n \"tag\": "elvet",\n \"popularity\": 233862\n },\n {\n \"tag\": "underclerk",\n \"popularity\": 232246\n },\n {\n \"tag\": "reticency",\n \"popularity\": 230647\n },\n {\n \"tag\": "neutroclusion",\n \"popularity\": 229065\n },\n {\n \"tag\": "unbelieving",\n \"popularity\": 227500\n },\n {\n \"tag\": "histogenetic",\n \"popularity\": 225952\n },\n {\n \"tag\": "dermamyiasis",\n \"popularity\": 224421\n },\n {\n \"tag\": "telenergy",\n \"popularity\": 222905\n },\n {\n \"tag\": "axiomatic",\n \"popularity\": 221406\n },\n {\n \"tag\": "undominoed",\n \"popularity\": 219922\n },\n {\n \"tag\": "periosteoma",\n \"popularity\": 218454\n },\n {\n \"tag\": "justiciaryship",\n \"popularity\": 217001\n },\n {\n \"tag\": "autoluminescence",\n \"popularity\": 215563\n },\n {\n \"tag\": "osmous",\n \"popularity\": 214140\n },\n {\n \"tag\": "borgh",\n \"popularity\": 212731\n },\n {\n \"tag\": "bedebt",\n \"popularity\": 211337\n },\n {\n \"tag\": "considerableness adenoidism",\n \"popularity\": 209957\n },\n {\n \"tag\": "sailorizing",\n \"popularity\": 208592\n },\n {\n \"tag\": "Montauk",\n \"popularity\": 207240\n },\n {\n \"tag\": "Bridget",\n \"popularity\": 205901\n },\n {\n \"tag\": "Gekkota",\n \"popularity\": 204577\n },\n {\n \"tag\": "subcorymbose",\n \"popularity\": 203265\n },\n {\n \"tag\": "undersap",\n \"popularity\": 201967\n },\n {\n \"tag\": "poikilothermic",\n \"popularity\": 200681\n },\n {\n \"tag\": "enneatical",\n \"popularity\": 199409\n },\n {\n \"tag\": "martinetism",\n \"popularity\": 198148\n },\n {\n \"tag\": "sustanedly",\n \"popularity\": 196901\n },\n {\n \"tag\": "declaration",\n \"popularity\": 195665\n },\n {\n \"tag\": "myringoplasty",\n \"popularity\": 194442\n },\n {\n \"tag\": "Ginkgo",\n \"popularity\": 193230\n },\n {\n \"tag\": "unrecurrent",\n \"popularity\": 192031\n },\n {\n \"tag\": "proprecedent",\n \"popularity\": 190843\n },\n {\n \"tag\": "roadman",\n \"popularity\": 189666\n },\n {\n \"tag\": "elemin",\n \"popularity\": 188501\n },\n {\n \"tag\": "maggot",\n \"popularity\": 187347\n },\n {\n \"tag\": "alitrunk",\n \"popularity\": 186204\n },\n {\n \"tag\": "introspection",\n \"popularity\": 185071\n },\n {\n \"tag\": "batiker",\n \"popularity\": 183950\n },\n {\n \"tag\": "backhatch oversettle",\n \"popularity\": 182839\n },\n {\n \"tag\": "thresherman",\n \"popularity\": 181738\n },\n {\n \"tag\": "protemperance",\n \"popularity\": 180648\n },\n {\n \"tag\": "undern",\n \"popularity\": 179568\n },\n {\n \"tag\": "tweeg",\n \"popularity\": 178498\n },\n {\n \"tag\": "crosspath",\n \"popularity\": 177438\n },\n {\n \"tag\": "Tangaridae",\n \"popularity\": 176388\n },\n {\n \"tag\": "scrutation",\n \"popularity\": 175348\n },\n {\n \"tag\": "piecemaker",\n \"popularity\": 174317\n },\n {\n \"tag\": "paster",\n \"popularity\": 173296\n },\n {\n \"tag\": "unpretendingness",\n \"popularity\": 172284\n },\n {\n \"tag\": "inframundane",\n \"popularity\": 171281\n },\n {\n \"tag\": "kiblah",\n \"popularity\": 170287\n },\n {\n \"tag\": "playwrighting",\n \"popularity\": 169302\n },\n {\n \"tag\": "gonepoiesis snowslip",\n \"popularity\": 168326\n },\n {\n \"tag\": "hoodwise",\n \"popularity\": 167359\n },\n {\n \"tag\": "postseason",\n \"popularity\": 166401\n },\n {\n \"tag\": "equivocality",\n \"popularity\": 165451\n },\n {\n \"tag\": "Opiliaceae nuclease",\n \"popularity\": 164509\n },\n {\n \"tag\": "sextipara",\n \"popularity\": 163576\n },\n {\n \"tag\": "weeper",\n \"popularity\": 162651\n },\n {\n \"tag\": "frambesia",\n \"popularity\": 161735\n },\n {\n \"tag\": "answerable",\n \"popularity\": 160826\n },\n {\n \"tag\": "Trichosporum",\n \"popularity\": 159925\n },\n {\n \"tag\": "cajuputol",\n \"popularity\": 159033\n },\n {\n \"tag\": "pleomorphous",\n \"popularity\": 158148\n },\n {\n \"tag\": "aculeolate",\n \"popularity\": 157270\n },\n {\n \"tag\": "wherever",\n \"popularity\": 156400\n },\n {\n \"tag\": "collapse",\n \"popularity\": 155538\n },\n {\n \"tag\": "porky",\n \"popularity\": 154683\n },\n {\n \"tag\": "perule",\n \"popularity\": 153836\n },\n {\n \"tag\": "Nevada",\n \"popularity\": 152996\n },\n {\n \"tag\": "conalbumin",\n \"popularity\": 152162\n },\n {\n \"tag\": "tsunami",\n \"popularity\": 151336\n },\n {\n \"tag\": "Gulf",\n \"popularity\": 150517\n },\n {\n \"tag\": "hertz",\n \"popularity\": 149705\n },\n {\n \"tag\": "limmock",\n \"popularity\": 148900\n },\n {\n \"tag\": "Tartarize",\n \"popularity\": 148101\n },\n {\n \"tag\": "entosphenoid",\n \"popularity\": 147310\n },\n {\n \"tag\": "ibis",\n \"popularity\": 146524\n },\n {\n \"tag\": "unyeaned",\n \"popularity\": 145746\n },\n {\n \"tag\": "tritural",\n \"popularity\": 144973\n },\n {\n \"tag\": "hundredary",\n \"popularity\": 144207\n },\n {\n \"tag\": "stolonlike",\n \"popularity\": 143448\n },\n {\n \"tag\": "chorister",\n \"popularity\": 142694\n },\n {\n \"tag\": "mismove",\n \"popularity\": 141947\n },\n {\n \"tag\": "Andine",\n \"popularity\": 141206\n },\n {\n \"tag\": "Annette proneur escribe",\n \"popularity\": 140471\n },\n {\n \"tag\": "exoperidium",\n \"popularity\": 139742\n },\n {\n \"tag\": "disedge",\n \"popularity\": 139019\n },\n {\n \"tag\": "hypochloruria",\n \"popularity\": 138302\n },\n {\n \"tag\": "prepupa",\n \"popularity\": 137590\n },\n {\n \"tag\": "assent",\n \"popularity\": 136884\n },\n {\n \"tag\": "hydrazobenzene",\n \"popularity\": 136184\n },\n {\n \"tag\": "emballonurid",\n \"popularity\": 135489\n },\n {\n \"tag\": "roselle",\n \"popularity\": 134800\n },\n {\n \"tag\": "unifiedly",\n \"popularity\": 134117\n },\n {\n \"tag\": "clang",\n \"popularity\": 133439\n },\n {\n \"tag\": "acetolytic",\n \"popularity\": 132766\n },\n {\n \"tag\": "cladodont",\n \"popularity\": 132098\n },\n {\n \"tag\": "recoast",\n \"popularity\": 131436\n },\n {\n \"tag\": "celebrated tydie Eocarboniferous",\n \"popularity\": 130779\n },\n {\n \"tag\": "superconsciousness",\n \"popularity\": 130127\n },\n {\n \"tag\": "soberness",\n \"popularity\": 129480\n },\n {\n \"tag\": "panoramist",\n \"popularity\": 128838\n },\n {\n \"tag\": "Orbitolina",\n \"popularity\": 128201\n },\n {\n \"tag\": "overlewd",\n \"popularity\": 127569\n },\n {\n \"tag\": "demiquaver",\n \"popularity\": 126942\n },\n {\n \"tag\": "kamelaukion",\n \"popularity\": 126319\n },\n {\n \"tag\": "flancard",\n \"popularity\": 125702\n },\n {\n \"tag\": "tricuspid",\n \"popularity\": 125089\n },\n {\n \"tag\": "bepelt",\n \"popularity\": 124480\n },\n {\n \"tag\": "decuplet",\n \"popularity\": 123877\n },\n {\n \"tag\": "Rockies",\n \"popularity\": 123278\n },\n {\n \"tag\": "unforgeability",\n \"popularity\": 122683\n },\n {\n \"tag\": "mocha",\n \"popularity\": 122093\n },\n {\n \"tag\": "scrunge",\n \"popularity\": 121507\n },\n {\n \"tag\": "delighter",\n \"popularity\": 120926\n },\n {\n \"tag\": "willey Microtinae",\n \"popularity\": 120349\n },\n {\n \"tag\": "unhuntable",\n \"popularity\": 119777\n },\n {\n \"tag\": "historically",\n \"popularity\": 119208\n },\n {\n \"tag\": "vicegerentship",\n \"popularity\": 118644\n },\n {\n \"tag\": "hemangiosarcoma",\n \"popularity\": 118084\n },\n {\n \"tag\": "harpago",\n \"popularity\": 117528\n },\n {\n \"tag\": "unionoid",\n \"popularity\": 116976\n },\n {\n \"tag\": "wiseman",\n \"popularity\": 116429\n },\n {\n \"tag\": "diclinism",\n \"popularity\": 115885\n },\n {\n \"tag\": "Maud",\n \"popularity\": 115345\n },\n {\n \"tag\": "scaphocephalism",\n \"popularity\": 114809\n },\n {\n \"tag\": "obtenebration",\n \"popularity\": 114277\n },\n {\n \"tag\": "cymar predreadnought",\n \"popularity\": 113749\n },\n {\n \"tag\": "discommend",\n \"popularity\": 113225\n },\n {\n \"tag\": "crude",\n \"popularity\": 112704\n },\n {\n \"tag\": "upflash",\n \"popularity\": 112187\n },\n {\n \"tag\": "saltimbank",\n \"popularity\": 111674\n },\n {\n \"tag\": "posthysterical",\n \"popularity\": 111165\n },\n {\n \"tag\": "trample",\n \"popularity\": 110659\n },\n {\n \"tag\": "ungirthed",\n \"popularity\": 110157\n },\n {\n \"tag\": "unshakable",\n \"popularity\": 109658\n },\n {\n \"tag\": "hepatocystic",\n \"popularity\": 109163\n },\n {\n \"tag\": "psammophyte",\n \"popularity\": 108671\n },\n {\n \"tag\": "millionfold",\n \"popularity\": 108183\n },\n {\n \"tag\": "outtaste",\n \"popularity\": 107698\n },\n {\n \"tag\": "poppycockish",\n \"popularity\": 107217\n },\n {\n \"tag\": "viduine",\n \"popularity\": 106739\n },\n {\n \"tag\": "pleasureman",\n \"popularity\": 106264\n },\n {\n \"tag\": "cholesterolemia",\n \"popularity\": 105792\n },\n {\n \"tag\": "hostlerwife",\n \"popularity\": 105324\n },\n {\n \"tag\": "figure undergrass",\n \"popularity\": 104859\n },\n {\n \"tag\": "bedrape",\n \"popularity\": 104398\n },\n {\n \"tag\": "nuttishness",\n \"popularity\": 103939\n },\n {\n \"tag\": "fow",\n \"popularity\": 103484\n },\n {\n \"tag\": "rachianesthesia",\n \"popularity\": 103031\n },\n {\n \"tag\": "recruitable",\n \"popularity\": 102582\n },\n {\n \"tag\": "semianatomical Oenotheraceae",\n \"popularity\": 102136\n },\n {\n \"tag\": "extracapsular",\n \"popularity\": 101693\n },\n {\n \"tag\": "unsigneted",\n \"popularity\": 101253\n },\n {\n \"tag\": "fissural",\n \"popularity\": 100816\n },\n {\n \"tag\": "ayous",\n \"popularity\": 100381\n },\n {\n \"tag\": "crestfallenness odontograph",\n \"popularity\": 99950\n },\n {\n \"tag\": "monopodium",\n \"popularity\": 99522\n },\n {\n \"tag\": "germfree",\n \"popularity\": 99096\n },\n {\n \"tag\": "dauphin",\n \"popularity\": 98673\n },\n {\n \"tag\": "nonagesimal",\n \"popularity\": 98254\n },\n {\n \"tag\": "waterchat",\n \"popularity\": 97836\n },\n {\n \"tag\": "Entelodon",\n \"popularity\": 97422\n },\n {\n \"tag\": "semischolastic",\n \"popularity\": 97010\n },\n {\n \"tag\": "somata",\n \"popularity\": 96602\n },\n {\n \"tag\": "expositorily",\n \"popularity\": 96195\n },\n {\n \"tag\": "bass",\n \"popularity\": 95792\n },\n {\n \"tag\": "calorimetry",\n \"popularity\": 95391\n },\n {\n \"tag\": "entireness",\n \"popularity\": 94993\n },\n {\n \"tag\": "ratline soppiness",\n \"popularity\": 94597\n },\n {\n \"tag\": "shor",\n \"popularity\": 94204\n },\n {\n \"tag\": "coprecipitation",\n \"popularity\": 93813\n },\n {\n \"tag\": "unblushingly",\n \"popularity\": 93425\n },\n {\n \"tag\": "macarize",\n \"popularity\": 93040\n },\n {\n \"tag\": "scruplesomeness",\n \"popularity\": 92657\n },\n {\n \"tag\": "offsaddle",\n \"popularity\": 92276\n },\n {\n \"tag\": "hypertragical",\n \"popularity\": 91898\n },\n {\n \"tag\": "uncassock loined",\n \"popularity\": 91522\n },\n {\n \"tag\": "interlobate",\n \"popularity\": 91149\n },\n {\n \"tag\": "releasor orrisroot stoloniferously",\n \"popularity\": 90778\n },\n {\n \"tag\": "elementoid",\n \"popularity\": 90410\n },\n {\n \"tag\": "Lentilla",\n \"popularity\": 90043\n },\n {\n \"tag\": "distressing",\n \"popularity\": 89679\n },\n {\n \"tag\": "hydrodrome",\n \"popularity\": 89318\n },\n {\n \"tag\": "Jeannette",\n \"popularity\": 88958\n },\n {\n \"tag\": "Kuli",\n \"popularity\": 88601\n },\n {\n \"tag\": "taxinomist",\n \"popularity\": 88246\n },\n {\n \"tag\": "southwestwardly",\n \"popularity\": 87894\n },\n {\n \"tag\": "polyparia",\n \"popularity\": 87543\n },\n {\n \"tag\": "exmeridian",\n \"popularity\": 87195\n },\n {\n \"tag\": "splenius regimentaled",\n \"popularity\": 86849\n },\n {\n \"tag\": "Sphaeropsidaceae",\n \"popularity\": 86505\n },\n {\n \"tag\": "unbegun",\n \"popularity\": 86163\n },\n {\n \"tag\": "something",\n \"popularity\": 85823\n },\n {\n \"tag\": "contaminable nonexpulsion",\n \"popularity\": 85486\n },\n {\n \"tag\": "douser",\n \"popularity\": 85150\n },\n {\n \"tag\": "prostrike",\n \"popularity\": 84817\n },\n {\n \"tag\": "worky",\n \"popularity\": 84485\n },\n {\n \"tag\": "folliful",\n \"popularity\": 84156\n },\n {\n \"tag\": "prioracy",\n \"popularity\": 83828\n },\n {\n \"tag\": "undermentioned",\n \"popularity\": 83503\n },\n {\n \"tag\": "Judaica",\n \"popularity\": 83179\n },\n {\n \"tag\": "multifarious",\n \"popularity\": 82858\n },\n {\n \"tag\": "poogye",\n \"popularity\": 82538\n },\n {\n \"tag\": "Sparganium",\n \"popularity\": 82221\n },\n {\n \"tag\": "thurrock",\n \"popularity\": 81905\n },\n {\n \"tag\": "outblush",\n \"popularity\": 81591\n },\n {\n \"tag\": "Strophanthus supraordination",\n \"popularity\": 81279\n },\n {\n \"tag\": "gingerroot",\n \"popularity\": 80969\n },\n {\n \"tag\": "unconscient",\n \"popularity\": 80661\n },\n {\n \"tag\": "unconstitutionally",\n \"popularity\": 80354\n },\n {\n \"tag\": "plaguily",\n \"popularity\": 80050\n },\n {\n \"tag\": "waterily equatorwards",\n \"popularity\": 79747\n },\n {\n \"tag\": "nondeposition",\n \"popularity\": 79446\n },\n {\n \"tag\": "dronishly",\n \"popularity\": 79147\n },\n {\n \"tag\": "gateado",\n \"popularity\": 78849\n },\n {\n \"tag\": "dislink",\n \"popularity\": 78553\n },\n {\n \"tag\": "Joceline",\n \"popularity\": 78259\n },\n {\n \"tag\": "amphiboliferous",\n \"popularity\": 77967\n },\n {\n \"tag\": "bushrope",\n \"popularity\": 77676\n },\n {\n \"tag\": "plumicorn sulphosalicylic",\n \"popularity\": 77387\n },\n {\n \"tag\": "nonefficiency",\n \"popularity\": 77100\n },\n {\n \"tag\": "hieroscopy",\n \"popularity\": 76815\n },\n {\n \"tag\": "causativeness",\n \"popularity\": 76531\n },\n {\n \"tag\": "swird paleoeremology",\n \"popularity\": 76249\n },\n {\n \"tag\": "camphoric",\n \"popularity\": 75968\n },\n {\n \"tag\": "retaining",\n \"popularity\": 75689\n },\n {\n \"tag\": "thyreoprotein",\n \"popularity\": 75411\n },\n {\n \"tag\": "carbona",\n \"popularity\": 75136\n },\n {\n \"tag\": "protectively",\n \"popularity\": 74861\n },\n {\n \"tag\": "mosasaur",\n \"popularity\": 74589\n },\n {\n \"tag\": "reciprocator",\n \"popularity\": 74317\n },\n {\n \"tag\": "detentive",\n \"popularity\": 74048\n },\n {\n \"tag\": "supravital",\n \"popularity\": 73780\n },\n {\n \"tag\": "Vespertilionidae",\n \"popularity\": 73513\n },\n {\n \"tag\": "parka",\n \"popularity\": 73248\n },\n {\n \"tag\": "pickaway",\n \"popularity\": 72984\n },\n {\n \"tag\": "oleaceous",\n \"popularity\": 72722\n },\n {\n \"tag\": "anticogitative",\n \"popularity\": 72462\n },\n {\n \"tag\": "woe",\n \"popularity\": 72203\n },\n {\n \"tag\": "skeuomorph",\n \"popularity\": 71945\n },\n {\n \"tag\": "helpmeet",\n \"popularity\": 71689\n },\n {\n \"tag\": "Hexactinellida brickmaking",\n \"popularity\": 71434\n },\n {\n \"tag\": "resink",\n \"popularity\": 71180\n },\n {\n \"tag\": "diluter",\n \"popularity\": 70928\n },\n {\n \"tag\": "micromicron",\n \"popularity\": 70677\n },\n {\n \"tag\": "parentage",\n \"popularity\": 70428\n },\n {\n \"tag\": "galactorrhoea",\n \"popularity\": 70180\n },\n {\n \"tag\": "gey",\n \"popularity\": 69934\n },\n {\n \"tag\": "gesticulatory",\n \"popularity\": 69689\n },\n {\n \"tag\": "wergil",\n \"popularity\": 69445\n },\n {\n \"tag\": "Lecanora",\n \"popularity\": 69202\n },\n {\n \"tag\": "malanders karst",\n \"popularity\": 68961\n },\n {\n \"tag\": "vibetoite",\n \"popularity\": 68721\n },\n {\n \"tag\": "unrequitedness",\n \"popularity\": 68483\n },\n {\n \"tag\": "outwash",\n \"popularity\": 68245\n },\n {\n \"tag\": "unsacred",\n \"popularity\": 68009\n },\n {\n \"tag\": "unabetted dividend",\n \"popularity\": 67775\n },\n {\n \"tag\": "untraveling",\n \"popularity\": 67541\n },\n {\n \"tag\": "thermobattery",\n \"popularity\": 67309\n },\n {\n \"tag\": "polypragmist",\n \"popularity\": 67078\n },\n {\n \"tag\": "irrefutableness",\n \"popularity\": 66848\n },\n {\n \"tag\": "remiges",\n \"popularity\": 66620\n },\n {\n \"tag\": "implode",\n \"popularity\": 66393\n },\n {\n \"tag\": "superfluousness",\n \"popularity\": 66166\n },\n {\n \"tag\": "croakily unalleviated",\n \"popularity\": 65942\n },\n {\n \"tag\": "edicule",\n \"popularity\": 65718\n },\n {\n \"tag\": "entophytous",\n \"popularity\": 65495\n },\n {\n \"tag\": "benefactorship Toryish",\n \"popularity\": 65274\n },\n {\n \"tag\": "pseudoamateurish",\n \"popularity\": 65054\n },\n {\n \"tag\": "flueless Iguanodontoidea snipnose",\n \"popularity\": 64835\n },\n {\n \"tag\": "zealotical Zamicrus interpole",\n \"popularity\": 64617\n },\n {\n \"tag\": "whereabout",\n \"popularity\": 64401\n },\n {\n \"tag\": "benzazide",\n \"popularity\": 64185\n },\n {\n \"tag\": "pokeweed",\n \"popularity\": 63971\n },\n {\n \"tag\": "calamitoid",\n \"popularity\": 63757\n },\n {\n \"tag\": "sporozoal",\n \"popularity\": 63545\n },\n {\n \"tag\": "physcioid Welshwoman",\n \"popularity\": 63334\n },\n {\n \"tag\": "wanting",\n \"popularity\": 63124\n },\n {\n \"tag\": "unencumbering",\n \"popularity\": 62915\n },\n {\n \"tag\": "Tupi",\n \"popularity\": 62707\n },\n {\n \"tag\": "potbank",\n \"popularity\": 62501\n },\n {\n \"tag\": "bulked",\n \"popularity\": 62295\n },\n {\n \"tag\": "uparise",\n \"popularity\": 62090\n },\n {\n \"tag\": "Sudra",\n \"popularity\": 61887\n },\n {\n \"tag\": "hyperscrupulosity",\n \"popularity\": 61684\n },\n {\n \"tag\": "subterraneously unmaid",\n \"popularity\": 61483\n },\n {\n \"tag\": "poisonousness",\n \"popularity\": 61282\n },\n {\n \"tag\": "phare",\n \"popularity\": 61083\n },\n {\n \"tag\": "dicynodont",\n \"popularity\": 60884\n },\n {\n \"tag\": "chewer",\n \"popularity\": 60687\n },\n {\n \"tag\": "uliginous",\n \"popularity\": 60490\n },\n {\n \"tag\": "tinman",\n \"popularity\": 60295\n },\n {\n \"tag\": "coconut",\n \"popularity\": 60100\n },\n {\n \"tag\": "phryganeoid",\n \"popularity\": 59907\n },\n {\n \"tag\": "bismillah",\n \"popularity\": 59714\n },\n {\n \"tag\": "tautomeric",\n \"popularity\": 59523\n },\n {\n \"tag\": "jerquer",\n \"popularity\": 59332\n },\n {\n \"tag\": "Dryopithecinae",\n \"popularity\": 59143\n },\n {\n \"tag\": "ghizite",\n \"popularity\": 58954\n },\n {\n \"tag\": "unliveable",\n \"popularity\": 58766\n },\n {\n \"tag\": "craftsmaster",\n \"popularity\": 58579\n },\n {\n \"tag\": "semiscenic",\n \"popularity\": 58394\n },\n {\n \"tag\": "danaid",\n \"popularity\": 58209\n },\n {\n \"tag\": "flawful",\n \"popularity\": 58025\n },\n {\n \"tag\": "risibleness",\n \"popularity\": 57841\n },\n {\n \"tag\": "Muscovite",\n \"popularity\": 57659\n },\n {\n \"tag\": "snaringly",\n \"popularity\": 57478\n },\n {\n \"tag\": "brilliantwise",\n \"popularity\": 57297\n },\n {\n \"tag\": "plebeity",\n \"popularity\": 57118\n },\n {\n \"tag\": "historicalness",\n \"popularity\": 56939\n },\n {\n \"tag\": "piecemeal",\n \"popularity\": 56761\n },\n {\n \"tag\": "maxillipedary",\n \"popularity\": 56584\n },\n {\n \"tag\": "Hypenantron",\n \"popularity\": 56408\n },\n {\n \"tag\": "quaintness avigate",\n \"popularity\": 56233\n },\n {\n \"tag\": "ave",\n \"popularity\": 56059\n },\n {\n \"tag\": "mediaevally",\n \"popularity\": 55885\n },\n {\n \"tag\": "brucite",\n \"popularity\": 55712\n },\n {\n \"tag\": "Schwendenerian",\n \"popularity\": 55541\n },\n {\n \"tag\": "julole",\n \"popularity\": 55370\n },\n {\n \"tag\": "palaeolith",\n \"popularity\": 55199\n },\n {\n \"tag\": "cotyledonary",\n \"popularity\": 55030\n },\n {\n \"tag\": "rond",\n \"popularity\": 54861\n },\n {\n \"tag\": "boomster tassoo",\n \"popularity\": 54694\n },\n {\n \"tag\": "cattishly",\n \"popularity\": 54527\n },\n {\n \"tag\": "tonguefence",\n \"popularity\": 54360\n },\n {\n \"tag\": "hexastylar triskele",\n \"popularity\": 54195\n },\n {\n \"tag\": "ariot",\n \"popularity\": 54030\n },\n {\n \"tag\": "intarsist",\n \"popularity\": 53867\n },\n {\n \"tag\": "Oscines",\n \"popularity\": 53704\n },\n {\n \"tag\": "Spaniolize",\n \"popularity\": 53541\n },\n {\n \"tag\": "smellfungus",\n \"popularity\": 53380\n },\n {\n \"tag\": "redisplay",\n \"popularity\": 53219\n },\n {\n \"tag\": "phosphene",\n \"popularity\": 53059\n },\n {\n \"tag\": "phycomycete",\n \"popularity\": 52900\n },\n {\n \"tag\": "prophetic",\n \"popularity\": 52741\n },\n {\n \"tag\": "overtrustful",\n \"popularity\": 52584\n },\n {\n \"tag\": "pinitol",\n \"popularity\": 52427\n },\n {\n \"tag\": "asthmatic",\n \"popularity\": 52270\n },\n {\n \"tag\": "convulsive",\n \"popularity\": 52115\n },\n {\n \"tag\": "draughtswoman",\n \"popularity\": 51960\n },\n {\n \"tag\": "unetymologizable",\n \"popularity\": 51806\n },\n {\n \"tag\": "centrarchoid",\n \"popularity\": 51652\n },\n {\n \"tag\": "mesioincisal",\n \"popularity\": 51500\n },\n {\n \"tag\": "transbaikal",\n \"popularity\": 51348\n },\n {\n \"tag\": "silveriness",\n \"popularity\": 51196\n },\n {\n \"tag\": "costotomy",\n \"popularity\": 51046\n },\n {\n \"tag\": "caracore",\n \"popularity\": 50896\n },\n {\n \"tag\": "depotentiation",\n \"popularity\": 50747\n },\n {\n \"tag\": "glossoepiglottidean",\n \"popularity\": 50598\n },\n {\n \"tag\": "upswell",\n \"popularity\": 50450\n },\n {\n \"tag\": "flecnodal",\n \"popularity\": 50303\n },\n {\n \"tag\": "coventrate",\n \"popularity\": 50157\n },\n {\n \"tag\": "duchesse",\n \"popularity\": 50011\n },\n {\n \"tag\": "excisemanship trophied",\n \"popularity\": 49866\n },\n {\n \"tag\": "cytinaceous",\n \"popularity\": 49721\n },\n {\n \"tag\": "assuringly",\n \"popularity\": 49577\n },\n {\n \"tag\": "unconducted upliftitis",\n \"popularity\": 49434\n },\n {\n \"tag\": "rachicentesis",\n \"popularity\": 49292\n },\n {\n \"tag\": "antiangular",\n \"popularity\": 49150\n },\n {\n \"tag\": "advisal",\n \"popularity\": 49008\n },\n {\n \"tag\": "birdcatcher",\n \"popularity\": 48868\n },\n {\n \"tag\": "secularistic",\n \"popularity\": 48728\n },\n {\n \"tag\": "grandeeism superinformal",\n \"popularity\": 48588\n },\n {\n \"tag\": "unapprehension",\n \"popularity\": 48449\n },\n {\n \"tag\": "excipulum",\n \"popularity\": 48311\n },\n {\n \"tag\": "decimole",\n \"popularity\": 48174\n },\n {\n \"tag\": "semidrachm",\n \"popularity\": 48037\n },\n {\n \"tag\": "uvulotome",\n \"popularity\": 47901\n },\n {\n \"tag\": "Lemaneaceae",\n \"popularity\": 47765\n },\n {\n \"tag\": "corrade",\n \"popularity\": 47630\n },\n {\n \"tag\": "Kuroshio",\n \"popularity\": 47495\n },\n {\n \"tag\": "Araliophyllum",\n \"popularity\": 47361\n },\n {\n \"tag\": "victoriousness cardiosphygmograph",\n \"popularity\": 47228\n },\n {\n \"tag\": "reinvent",\n \"popularity\": 47095\n },\n {\n \"tag\": "Macrotolagus",\n \"popularity\": 46963\n },\n {\n \"tag\": "strenuousness",\n \"popularity\": 46831\n },\n {\n \"tag\": "deviability",\n \"popularity\": 46700\n },\n {\n \"tag\": "phyllospondylous",\n \"popularity\": 46570\n },\n {\n \"tag\": "bisect rudderhole",\n \"popularity\": 46440\n },\n {\n \"tag\": "crownwork",\n \"popularity\": 46311\n },\n {\n \"tag\": "Ascalabota",\n \"popularity\": 46182\n },\n {\n \"tag\": "prostatomyomectomy",\n \"popularity\": 46054\n },\n {\n \"tag\": "neurosyphilis",\n \"popularity\": 45926\n },\n {\n \"tag\": "tabloid scraplet",\n \"popularity\": 45799\n },\n {\n \"tag\": "nonmedullated servility",\n \"popularity\": 45673\n },\n {\n \"tag\": "melopoeic practicalization",\n \"popularity\": 45547\n },\n {\n \"tag\": "nonrhythmic",\n \"popularity\": 45421\n },\n {\n \"tag\": "deplorer",\n \"popularity\": 45296\n },\n {\n \"tag\": "Ophion",\n \"popularity\": 45172\n },\n {\n \"tag\": "subprioress",\n \"popularity\": 45048\n },\n {\n \"tag\": "semiregular",\n \"popularity\": 44925\n },\n {\n \"tag\": "praelection",\n \"popularity\": 44802\n },\n {\n \"tag\": "discinct",\n \"popularity\": 44680\n },\n {\n \"tag\": "preplace",\n \"popularity\": 44558\n },\n {\n \"tag\": "paternoster",\n \"popularity\": 44437\n },\n {\n \"tag\": "suboccipital",\n \"popularity\": 44316\n },\n {\n \"tag\": "Teutophil",\n \"popularity\": 44196\n },\n {\n \"tag\": "tracheole",\n \"popularity\": 44076\n },\n {\n \"tag\": "subsmile",\n \"popularity\": 43957\n },\n {\n \"tag\": "nonapostatizing",\n \"popularity\": 43839\n },\n {\n \"tag\": "cleidotomy",\n \"popularity\": 43720\n },\n {\n \"tag\": "hingle",\n \"popularity\": 43603\n },\n {\n \"tag\": "jocoque",\n \"popularity\": 43486\n },\n {\n \"tag\": "trundler notidanian",\n \"popularity\": 43369\n },\n {\n \"tag\": "strangling misdaub",\n \"popularity\": 43253\n },\n {\n \"tag\": "noncancellable",\n \"popularity\": 43137\n },\n {\n \"tag\": "lavabo",\n \"popularity\": 43022\n },\n {\n \"tag\": "lanterloo",\n \"popularity\": 42907\n },\n {\n \"tag\": "uncitizenly",\n \"popularity\": 42793\n },\n {\n \"tag\": "autoturning",\n \"popularity\": 42679\n },\n {\n \"tag\": "Haganah",\n \"popularity\": 42566\n },\n {\n \"tag\": "Glecoma",\n \"popularity\": 42453\n },\n {\n \"tag\": "membered",\n \"popularity\": 42341\n },\n {\n \"tag\": "consuetudinal",\n \"popularity\": 42229\n },\n {\n \"tag\": "gatehouse",\n \"popularity\": 42117\n },\n {\n \"tag\": "tetherball",\n \"popularity\": 42006\n },\n {\n \"tag\": "counterrevolutionist numismatical",\n \"popularity\": 41896\n },\n {\n \"tag\": "pagehood plateiasmus",\n \"popularity\": 41786\n },\n {\n \"tag\": "pelterer",\n \"popularity\": 41676\n },\n {\n \"tag\": "splenemphraxis",\n \"popularity\": 41567\n },\n {\n \"tag\": "Crypturidae",\n \"popularity\": 41458\n },\n {\n \"tag\": "caboodle",\n \"popularity\": 41350\n },\n {\n \"tag\": "Filaria",\n \"popularity\": 41242\n },\n {\n \"tag\": "noninvincibility",\n \"popularity\": 41135\n },\n {\n \"tag\": "preadvertisement",\n \"popularity\": 41028\n },\n {\n \"tag\": "bathrobe",\n \"popularity\": 40921\n },\n {\n \"tag\": "nitrifier",\n \"popularity\": 40815\n },\n {\n \"tag\": "furthermore",\n \"popularity\": 40709\n },\n {\n \"tag\": "recrate",\n \"popularity\": 40604\n },\n {\n \"tag\": "inexist",\n \"popularity\": 40499\n },\n {\n \"tag\": "Mocoan",\n \"popularity\": 40395\n },\n {\n \"tag\": "forint",\n \"popularity\": 40291\n },\n {\n \"tag\": "cardiomyoliposis",\n \"popularity\": 40187\n },\n {\n \"tag\": "channeling",\n \"popularity\": 40084\n },\n {\n \"tag\": "quebrachine",\n \"popularity\": 39981\n },\n {\n \"tag\": "magistery",\n \"popularity\": 39879\n },\n {\n \"tag\": "koko",\n \"popularity\": 39777\n },\n {\n \"tag\": "nobilify",\n \"popularity\": 39676\n },\n {\n \"tag\": "articulate taprooted",\n \"popularity\": 39575\n },\n {\n \"tag\": "cardiotonic Nicaragua",\n \"popularity\": 39474\n },\n {\n \"tag\": "assertiveness",\n \"popularity\": 39374\n },\n {\n \"tag\": "springtail",\n \"popularity\": 39274\n },\n {\n \"tag\": "spontoon",\n \"popularity\": 39174\n },\n {\n \"tag\": "plesiobiosis",\n \"popularity\": 39075\n },\n {\n \"tag\": "rooinek",\n \"popularity\": 38976\n },\n {\n \"tag\": "hairif falsehood",\n \"popularity\": 38878\n },\n {\n \"tag\": "synodally",\n \"popularity\": 38780\n },\n {\n \"tag\": "biodynamics",\n \"popularity\": 38683\n },\n {\n \"tag\": "trickling",\n \"popularity\": 38585\n },\n {\n \"tag\": "oxfly daystar",\n \"popularity\": 38489\n },\n {\n \"tag\": "epicycloidal",\n \"popularity\": 38392\n },\n {\n \"tag\": "shorthand",\n \"popularity\": 38296\n },\n {\n \"tag\": "herpolhode",\n \"popularity\": 38201\n },\n {\n \"tag\": "polysynthesism",\n \"popularity\": 38105\n },\n {\n \"tag\": "cany",\n \"popularity\": 38010\n },\n {\n \"tag\": "sideage",\n \"popularity\": 37916\n },\n {\n \"tag\": "strainableness",\n \"popularity\": 37822\n },\n {\n \"tag\": "superformidable",\n \"popularity\": 37728\n },\n {\n \"tag\": "slendang",\n \"popularity\": 37634\n },\n {\n \"tag\": "impropriation",\n \"popularity\": 37541\n },\n {\n \"tag\": "ficklehearted",\n \"popularity\": 37449\n },\n {\n \"tag\": "wintrify",\n \"popularity\": 37356\n },\n {\n \"tag\": "geomorphogenist",\n \"popularity\": 37264\n },\n {\n \"tag\": "smuggleable",\n \"popularity\": 37173\n },\n {\n \"tag\": "delapsion",\n \"popularity\": 37081\n },\n {\n \"tag\": "projective",\n \"popularity\": 36990\n },\n {\n \"tag\": "unglue exfoliation",\n \"popularity\": 36900\n },\n {\n \"tag\": "Acerae",\n \"popularity\": 36810\n },\n {\n \"tag\": "unstaged",\n \"popularity\": 36720\n },\n {\n \"tag\": "ranal",\n \"popularity\": 36630\n },\n {\n \"tag\": "worrier",\n \"popularity\": 36541\n },\n {\n \"tag\": "unhid",\n \"popularity\": 36452\n },\n {\n \"tag\": "adequation",\n \"popularity\": 36363\n },\n {\n \"tag\": "strongylid Sokotri",\n \"popularity\": 36275\n },\n {\n \"tag\": "fumingly",\n \"popularity\": 36187\n },\n {\n \"tag\": "gynosporangium phaenogenetic",\n \"popularity\": 36100\n },\n {\n \"tag\": "uniunguiculate",\n \"popularity\": 36012\n },\n {\n \"tag\": "prudelike",\n \"popularity\": 35926\n },\n {\n \"tag\": "seminomata",\n \"popularity\": 35839\n },\n {\n \"tag\": "trinklet",\n \"popularity\": 35753\n },\n {\n \"tag\": "risorial",\n \"popularity\": 35667\n },\n {\n \"tag\": "pericardiocentesis",\n \"popularity\": 35581\n },\n {\n \"tag\": "filmist",\n \"popularity\": 35496\n },\n {\n \"tag\": "Nana",\n \"popularity\": 35411\n },\n {\n \"tag\": "cynipoid",\n \"popularity\": 35326\n },\n {\n \"tag\": "cteniform",\n \"popularity\": 35242\n },\n {\n \"tag\": "semiflex",\n \"popularity\": 35158\n },\n {\n \"tag\": "solstitially",\n \"popularity\": 35074\n },\n {\n \"tag\": "Algarsife",\n \"popularity\": 34991\n },\n {\n \"tag\": "noncriminal",\n \"popularity\": 34908\n },\n {\n \"tag\": "compassion",\n \"popularity\": 34825\n },\n {\n \"tag\": "Buddhic",\n \"popularity\": 34743\n },\n {\n \"tag\": "vellicative dactylically hotfoot",\n \"popularity\": 34661\n },\n {\n \"tag\": "chicory",\n \"popularity\": 34579\n },\n {\n \"tag\": "transperitoneally",\n \"popularity\": 34497\n },\n {\n \"tag\": "pennae",\n \"popularity\": 34416\n },\n {\n \"tag\": "Flamandize",\n \"popularity\": 34335\n },\n {\n \"tag\": "underviewer",\n \"popularity\": 34254\n },\n {\n \"tag\": "assoil",\n \"popularity\": 34174\n },\n {\n \"tag\": "saccharobacillus",\n \"popularity\": 34094\n },\n {\n \"tag\": "biacetylene",\n \"popularity\": 34014\n },\n {\n \"tag\": "mouchardism",\n \"popularity\": 33935\n },\n {\n \"tag\": "anisomeric",\n \"popularity\": 33856\n },\n {\n \"tag\": "digestive",\n \"popularity\": 33777\n },\n {\n \"tag\": "darlingly",\n \"popularity\": 33698\n },\n {\n \"tag\": "liman",\n \"popularity\": 33620\n },\n {\n \"tag\": "soldanrie",\n \"popularity\": 33542\n },\n {\n \"tag\": "sully",\n \"popularity\": 33464\n },\n {\n \"tag\": "brightsmith",\n \"popularity\": 33387\n },\n {\n \"tag\": "inwrap antiliturgist ureterocervical",\n \"popularity\": 33309\n },\n {\n \"tag\": "discommodity",\n \"popularity\": 33232\n },\n {\n \"tag\": "typical aggrandizer",\n \"popularity\": 33156\n },\n {\n \"tag\": "xenogeny",\n \"popularity\": 33079\n },\n {\n \"tag\": "uncountrified",\n \"popularity\": 33003\n },\n {\n \"tag\": "Podarge",\n \"popularity\": 32928\n },\n {\n \"tag\": "uninterviewed",\n \"popularity\": 32852\n },\n {\n \"tag\": "underprior",\n \"popularity\": 32777\n },\n {\n \"tag\": "leiomyomatous",\n \"popularity\": 32702\n },\n {\n \"tag\": "postdysenteric",\n \"popularity\": 32627\n },\n {\n \"tag\": "Fusicladium",\n \"popularity\": 32553\n },\n {\n \"tag\": "Dulcinea",\n \"popularity\": 32478\n },\n {\n \"tag\": "interspersion",\n \"popularity\": 32404\n },\n {\n \"tag\": "preobligate",\n \"popularity\": 32331\n },\n {\n \"tag\": "subaggregate",\n \"popularity\": 32257\n },\n {\n \"tag\": "grammarianism",\n \"popularity\": 32184\n },\n {\n \"tag\": "palikar",\n \"popularity\": 32111\n },\n {\n \"tag\": "facileness",\n \"popularity\": 32039\n },\n {\n \"tag\": "deuterofibrinose",\n \"popularity\": 31966\n },\n {\n \"tag\": "pseudesthesia",\n \"popularity\": 31894\n },\n {\n \"tag\": "sedimentary",\n \"popularity\": 31822\n },\n {\n \"tag\": "typewrite",\n \"popularity\": 31751\n },\n {\n \"tag\": "immemorable",\n \"popularity\": 31679\n },\n {\n \"tag\": "Myrtus",\n \"popularity\": 31608\n },\n {\n \"tag\": "hauchecornite",\n \"popularity\": 31537\n },\n {\n \"tag\": "galleylike",\n \"popularity\": 31467\n },\n {\n \"tag\": "thimber",\n \"popularity\": 31396\n },\n {\n \"tag\": "Hegelianism",\n \"popularity\": 31326\n },\n {\n \"tag\": "strig",\n \"popularity\": 31256\n },\n {\n \"tag\": "skyre",\n \"popularity\": 31187\n },\n {\n \"tag\": "eupepticism",\n \"popularity\": 31117\n },\n {\n \"tag\": "eponymism",\n \"popularity\": 31048\n },\n {\n \"tag\": "flunkeyhood",\n \"popularity\": 30979\n },\n {\n \"tag\": "Abama",\n \"popularity\": 30911\n },\n {\n \"tag\": "adiadochokinesis",\n \"popularity\": 30842\n },\n {\n \"tag\": "spendthrifty",\n \"popularity\": 30774\n },\n {\n \"tag\": "chalcedony",\n \"popularity\": 30706\n },\n {\n \"tag\": "authorism",\n \"popularity\": 30638\n },\n {\n \"tag\": "nasturtium",\n \"popularity\": 30571\n },\n {\n \"tag\": "Acanthocereus",\n \"popularity\": 30504\n },\n {\n \"tag\": "uncollapsible",\n \"popularity\": 30437\n },\n {\n \"tag\": "excursionist",\n \"popularity\": 30370\n },\n {\n \"tag\": "fogbow",\n \"popularity\": 30303\n },\n {\n \"tag\": "overlie",\n \"popularity\": 30237\n },\n {\n \"tag\": "velours",\n \"popularity\": 30171\n },\n {\n \"tag\": "zoodendria madrigal stagbush",\n \"popularity\": 30105\n },\n {\n \"tag\": "imi",\n \"popularity\": 30039\n },\n {\n \"tag\": "cojudge",\n \"popularity\": 29974\n },\n {\n \"tag\": "depurate argal",\n \"popularity\": 29909\n },\n {\n \"tag\": "unrecognition",\n \"popularity\": 29844\n },\n {\n \"tag\": "paunchful",\n \"popularity\": 29779\n },\n {\n \"tag\": "invalued",\n \"popularity\": 29714\n },\n {\n \"tag\": "probang",\n \"popularity\": 29650\n },\n {\n \"tag\": "chetvert",\n \"popularity\": 29586\n },\n {\n \"tag\": "enactable",\n \"popularity\": 29522\n },\n {\n \"tag\": "detoxicate adhibit",\n \"popularity\": 29458\n },\n {\n \"tag\": "kullaite",\n \"popularity\": 29395\n },\n {\n \"tag\": "undazzling",\n \"popularity\": 29332\n },\n {\n \"tag\": "excalation",\n \"popularity\": 29269\n },\n {\n \"tag\": "sievings",\n \"popularity\": 29206\n },\n {\n \"tag\": "disenthral",\n \"popularity\": 29143\n },\n {\n \"tag\": "disinterestedly",\n \"popularity\": 29081\n },\n {\n \"tag\": "stanner",\n \"popularity\": 29018\n },\n {\n \"tag\": "recapitulative",\n \"popularity\": 28956\n },\n {\n \"tag\": "objectivist",\n \"popularity\": 28895\n },\n {\n \"tag\": "hypermetropia",\n \"popularity\": 28833\n },\n {\n \"tag\": "incumbency",\n \"popularity\": 28772\n },\n {\n \"tag\": "protegee",\n \"popularity\": 28711\n },\n {\n \"tag\": "zealotic",\n \"popularity\": 28650\n },\n {\n \"tag\": "predebit",\n \"popularity\": 28589\n },\n {\n \"tag\": "cupolar",\n \"popularity\": 28528\n },\n {\n \"tag\": "unattributed",\n \"popularity\": 28468\n },\n {\n \"tag\": "louisine",\n \"popularity\": 28408\n },\n {\n \"tag\": "illustrate",\n \"popularity\": 28348\n },\n {\n \"tag\": "inofficiousness",\n \"popularity\": 28288\n },\n {\n \"tag\": "Americawards",\n \"popularity\": 28228\n },\n {\n \"tag\": "foreflap",\n \"popularity\": 28169\n },\n {\n \"tag\": "eruditeness",\n \"popularity\": 28110\n },\n {\n \"tag\": "copiopsia",\n \"popularity\": 28051\n },\n {\n \"tag\": "sporuliferous",\n \"popularity\": 27992\n },\n {\n \"tag\": "muttering",\n \"popularity\": 27934\n },\n {\n \"tag\": "prepsychology adrip",\n \"popularity\": 27875\n },\n {\n \"tag\": "unfriendly",\n \"popularity\": 27817\n },\n {\n \"tag\": "sulphanilic",\n \"popularity\": 27759\n },\n {\n \"tag\": "Coelococcus",\n \"popularity\": 27701\n },\n {\n \"tag\": "undoubtfulness",\n \"popularity\": 27643\n },\n {\n \"tag\": "flaringly",\n \"popularity\": 27586\n },\n {\n \"tag\": "unordain",\n \"popularity\": 27529\n },\n {\n \"tag\": "fratchety",\n \"popularity\": 27472\n },\n {\n \"tag\": "decadentism dolefully",\n \"popularity\": 27415\n },\n {\n \"tag\": "synthronus",\n \"popularity\": 27358\n },\n {\n \"tag\": "maiid",\n \"popularity\": 27301\n },\n {\n \"tag\": "rhinobyon",\n \"popularity\": 27245\n },\n {\n \"tag\": "Didynamia",\n \"popularity\": 27189\n },\n {\n \"tag\": "millionairedom",\n \"popularity\": 27133\n },\n {\n \"tag\": "mulierine",\n \"popularity\": 27077\n },\n {\n \"tag\": "Mayo",\n \"popularity\": 27021\n },\n {\n \"tag\": "perceivedness",\n \"popularity\": 26966\n },\n {\n \"tag\": "unadoration",\n \"popularity\": 26911\n },\n {\n \"tag\": "regraft",\n \"popularity\": 26856\n },\n {\n \"tag\": "witch",\n \"popularity\": 26801\n },\n {\n \"tag\": "ungrow",\n \"popularity\": 26746\n },\n {\n \"tag\": "glossopharyngeus",\n \"popularity\": 26691\n },\n {\n \"tag\": "unstirrable",\n \"popularity\": 26637\n },\n {\n \"tag\": "synodsman",\n \"popularity\": 26583\n },\n {\n \"tag\": "placentalian",\n \"popularity\": 26529\n },\n {\n \"tag\": "corpulently",\n \"popularity\": 26475\n },\n {\n \"tag\": "photochromoscope",\n \"popularity\": 26421\n },\n {\n \"tag\": "indusiate retinasphaltum chokestrap",\n \"popularity\": 26368\n },\n {\n \"tag\": "murdrum",\n \"popularity\": 26314\n },\n {\n \"tag\": "belatedness",\n \"popularity\": 26261\n },\n {\n \"tag\": "Cochin",\n \"popularity\": 26208\n },\n {\n \"tag\": "Leonist",\n \"popularity\": 26155\n },\n {\n \"tag\": "keeker confined",\n \"popularity\": 26102\n },\n {\n \"tag\": "unintellectual",\n \"popularity\": 26050\n },\n {\n \"tag\": "nymphaline bait",\n \"popularity\": 25997\n },\n {\n \"tag\": "sarcosporidiosis",\n \"popularity\": 25945\n },\n {\n \"tag\": "catawamptiously",\n \"popularity\": 25893\n },\n {\n \"tag\": "outshame",\n \"popularity\": 25841\n },\n {\n \"tag\": "animalism",\n \"popularity\": 25790\n },\n {\n \"tag\": "epithalamial",\n \"popularity\": 25738\n },\n {\n \"tag\": "ganner",\n \"popularity\": 25687\n },\n {\n \"tag\": "desilicify",\n \"popularity\": 25635\n },\n {\n \"tag\": "dandyism",\n \"popularity\": 25584\n },\n {\n \"tag\": "hyleg",\n \"popularity\": 25533\n },\n {\n \"tag\": "photophysical",\n \"popularity\": 25483\n },\n {\n \"tag\": "underload",\n \"popularity\": 25432\n },\n {\n \"tag\": "unintrusive",\n \"popularity\": 25382\n },\n {\n \"tag\": "succinamic",\n \"popularity\": 25331\n },\n {\n \"tag\": "matchy",\n \"popularity\": 25281\n },\n {\n \"tag\": "concordal",\n \"popularity\": 25231\n },\n {\n \"tag\": "exteriority",\n \"popularity\": 25181\n },\n {\n \"tag\": "sterculiad",\n \"popularity\": 25132\n },\n {\n \"tag\": "sulfoxylic",\n \"popularity\": 25082\n },\n {\n \"tag\": "oversubscription",\n \"popularity\": 25033\n },\n {\n \"tag\": "chiasmic",\n \"popularity\": 24984\n },\n {\n \"tag\": "pseudoparthenogenesis",\n \"popularity\": 24935\n },\n {\n \"tag\": "indorse",\n \"popularity\": 24886\n },\n {\n \"tag\": "Krishnaite",\n \"popularity\": 24837\n },\n {\n \"tag\": "calcinize",\n \"popularity\": 24788\n },\n {\n \"tag\": "rhodium",\n \"popularity\": 24740\n },\n {\n \"tag\": "tragopan",\n \"popularity\": 24692\n },\n {\n \"tag\": "overwhelmingly",\n \"popularity\": 24643\n },\n {\n \"tag\": "procidence accorporate",\n \"popularity\": 24595\n },\n {\n \"tag\": "polemize speelless",\n \"popularity\": 24548\n },\n {\n \"tag\": "radiocarpal goran",\n \"popularity\": 24500\n },\n {\n \"tag\": "counteroffer Pelodytes",\n \"popularity\": 24452\n },\n {\n \"tag\": "lionhearted",\n \"popularity\": 24405\n },\n {\n \"tag\": "paramastoid",\n \"popularity\": 24358\n },\n {\n \"tag\": "murine",\n \"popularity\": 24310\n },\n {\n \"tag\": "woodbined",\n \"popularity\": 24263\n },\n {\n \"tag\": "packthread",\n \"popularity\": 24217\n },\n {\n \"tag\": "citreous",\n \"popularity\": 24170\n },\n {\n \"tag\": "unfallaciously",\n \"popularity\": 24123\n },\n {\n \"tag\": "tentwork reincarnadine",\n \"popularity\": 24077\n },\n {\n \"tag\": "verminousness",\n \"popularity\": 24030\n },\n {\n \"tag\": "sillometer",\n \"popularity\": 23984\n },\n {\n \"tag\": "jointy",\n \"popularity\": 23938\n },\n {\n \"tag\": "streptolysin",\n \"popularity\": 23892\n },\n {\n \"tag\": "Florentinism",\n \"popularity\": 23847\n },\n {\n \"tag\": "monosomatous",\n \"popularity\": 23801\n },\n {\n \"tag\": "capsulociliary",\n \"popularity\": 23756\n },\n {\n \"tag\": "organum",\n \"popularity\": 23710\n },\n {\n \"tag\": "overtly",\n \"popularity\": 23665\n },\n {\n \"tag\": "ophthalmoscopical",\n \"popularity\": 23620\n },\n {\n \"tag\": "supposititiously",\n \"popularity\": 23575\n },\n {\n \"tag\": "radiochemistry",\n \"popularity\": 23530\n },\n {\n \"tag\": "flaxtail",\n \"popularity\": 23486\n },\n {\n \"tag\": "pretympanic",\n \"popularity\": 23441\n },\n {\n \"tag\": "auscultation",\n \"popularity\": 23397\n },\n {\n \"tag\": "hairdresser",\n \"popularity\": 23352\n },\n {\n \"tag\": "chaffless",\n \"popularity\": 23308\n },\n {\n \"tag\": "polioencephalitis",\n \"popularity\": 23264\n },\n {\n \"tag\": "axolotl",\n \"popularity\": 23220\n },\n {\n \"tag\": "smous",\n \"popularity\": 23177\n },\n {\n \"tag\": "morgen disenamour toothed",\n \"popularity\": 23133\n },\n {\n \"tag\": "chaiseless",\n \"popularity\": 23089\n },\n {\n \"tag\": "frugally",\n \"popularity\": 23046\n },\n {\n \"tag\": "combustive antievolutionist cinenegative",\n \"popularity\": 23003\n },\n {\n \"tag\": "malacolite",\n \"popularity\": 22960\n },\n {\n \"tag\": "borne",\n \"popularity\": 22917\n },\n {\n \"tag\": "mercaptole",\n \"popularity\": 22874\n },\n {\n \"tag\": "judicatory",\n \"popularity\": 22831\n },\n {\n \"tag\": "noctivagation",\n \"popularity\": 22789\n },\n {\n \"tag\": "synthete",\n \"popularity\": 22746\n },\n {\n \"tag\": "tomboyism",\n \"popularity\": 22704\n },\n {\n \"tag\": "serranoid",\n \"popularity\": 22661\n },\n {\n \"tag\": "impostorism",\n \"popularity\": 22619\n },\n {\n \"tag\": "flagellosis Talitha",\n \"popularity\": 22577\n },\n {\n \"tag\": "pseudoviscous",\n \"popularity\": 22535\n },\n {\n \"tag\": "Galleriidae",\n \"popularity\": 22494\n },\n {\n \"tag\": "undulation didelph Comintern",\n \"popularity\": 22452\n },\n {\n \"tag\": "triangulopyramidal",\n \"popularity\": 22411\n },\n {\n \"tag\": "middlings",\n \"popularity\": 22369\n },\n {\n \"tag\": "piperazin",\n \"popularity\": 22328\n },\n {\n \"tag\": "endostitis",\n \"popularity\": 22287\n },\n {\n \"tag\": "swordlike",\n \"popularity\": 22246\n },\n {\n \"tag\": "forthwith",\n \"popularity\": 22205\n },\n {\n \"tag\": "menaceful",\n \"popularity\": 22164\n },\n {\n \"tag\": "explantation defective",\n \"popularity\": 22123\n },\n {\n \"tag\": "arrear",\n \"popularity\": 22083\n },\n {\n \"tag\": "engraft",\n \"popularity\": 22042\n },\n {\n \"tag\": "revolunteer",\n \"popularity\": 22002\n },\n {\n \"tag\": "foliaceous",\n \"popularity\": 21962\n },\n {\n \"tag\": "pseudograph",\n \"popularity\": 21922\n },\n {\n \"tag\": "maenaite",\n \"popularity\": 21882\n },\n {\n \"tag\": "interfinger",\n \"popularity\": 21842\n },\n {\n \"tag\": "macroscopically",\n \"popularity\": 21802\n },\n {\n \"tag\": "bluewood",\n \"popularity\": 21762\n },\n {\n \"tag\": "chikara",\n \"popularity\": 21723\n },\n {\n \"tag\": "reprehension diazeuxis nickelous",\n \"popularity\": 21683\n },\n {\n \"tag\": "vacuation",\n \"popularity\": 21644\n },\n {\n \"tag\": "Sartish",\n \"popularity\": 21605\n },\n {\n \"tag\": "pseudogyny",\n \"popularity\": 21566\n },\n {\n \"tag\": "friedcake",\n \"popularity\": 21527\n },\n {\n \"tag\": "thraw",\n \"popularity\": 21488\n },\n {\n \"tag\": "bifid",\n \"popularity\": 21449\n },\n {\n \"tag\": "truthlessly",\n \"popularity\": 21411\n },\n {\n \"tag\": "lungy",\n \"popularity\": 21372\n },\n {\n \"tag\": "fluoborite",\n \"popularity\": 21334\n },\n {\n \"tag\": "anthropolithic",\n \"popularity\": 21295\n },\n {\n \"tag\": "coachee straw",\n \"popularity\": 21257\n },\n {\n \"tag\": "dehorner Grecize",\n \"popularity\": 21219\n },\n {\n \"tag\": "spondylopyosis",\n \"popularity\": 21181\n },\n {\n \"tag\": "institutionary",\n \"popularity\": 21143\n },\n {\n \"tag\": "agentry",\n \"popularity\": 21105\n },\n {\n \"tag\": "musing bietle",\n \"popularity\": 21068\n },\n {\n \"tag\": "cormophyte",\n \"popularity\": 21030\n },\n {\n \"tag\": "semielliptic",\n \"popularity\": 20993\n },\n {\n \"tag\": "ependytes",\n \"popularity\": 20955\n },\n {\n \"tag\": "coachmaster",\n \"popularity\": 20918\n },\n {\n \"tag\": "overexuberant",\n \"popularity\": 20881\n },\n {\n \"tag\": "selectable",\n \"popularity\": 20844\n },\n {\n \"tag\": "saclike",\n \"popularity\": 20807\n },\n {\n \"tag\": "mullion",\n \"popularity\": 20770\n },\n {\n \"tag\": "pantheonize prevalency",\n \"popularity\": 20733\n },\n {\n \"tag\": "trophosperm",\n \"popularity\": 20697\n },\n {\n \"tag\": "paraphrasist",\n \"popularity\": 20660\n },\n {\n \"tag\": "undercarry",\n \"popularity\": 20624\n },\n {\n \"tag\": "thallogenic",\n \"popularity\": 20587\n },\n {\n \"tag\": "bulgy forbid",\n \"popularity\": 20551\n },\n {\n \"tag\": "proliquor gratulatory",\n \"popularity\": 20515\n },\n {\n \"tag\": "booker",\n \"popularity\": 20479\n },\n {\n \"tag\": "wizen",\n \"popularity\": 20443\n },\n {\n \"tag\": "synchondrosially",\n \"popularity\": 20407\n },\n {\n \"tag\": "herbless",\n \"popularity\": 20371\n },\n {\n \"tag\": "arfvedsonite",\n \"popularity\": 20336\n },\n {\n \"tag\": "Neuroptera",\n \"popularity\": 20300\n },\n {\n \"tag\": "fingerstone",\n \"popularity\": 20265\n },\n {\n \"tag\": "Odontoglossae",\n \"popularity\": 20229\n },\n {\n \"tag\": "transmigrator",\n \"popularity\": 20194\n },\n {\n \"tag\": "Dehaites",\n \"popularity\": 20159\n },\n {\n \"tag\": "Molinist",\n \"popularity\": 20124\n },\n {\n \"tag\": "novelistic",\n \"popularity\": 20089\n },\n {\n \"tag\": "astelic",\n \"popularity\": 20054\n },\n {\n \"tag\": "pyelometry",\n \"popularity\": 20019\n },\n {\n \"tag\": "pigmentation",\n \"popularity\": 19984\n },\n {\n \"tag\": "epinaos",\n \"popularity\": 19950\n },\n {\n \"tag\": "outdare",\n \"popularity\": 19915\n },\n {\n \"tag\": "Funje philaristocracy",\n \"popularity\": 19881\n },\n {\n \"tag\": "keddah",\n \"popularity\": 19846\n },\n {\n \"tag\": "axoidean",\n \"popularity\": 19812\n },\n {\n \"tag\": "ovule",\n \"popularity\": 19778\n },\n {\n \"tag\": "solidify",\n \"popularity\": 19744\n },\n {\n \"tag\": "noncelestial",\n \"popularity\": 19710\n },\n {\n \"tag\": "overmultiplication",\n \"popularity\": 19676\n },\n {\n \"tag\": "hexatetrahedron",\n \"popularity\": 19642\n },\n {\n \"tag\": "pliciform",\n \"popularity\": 19609\n },\n {\n \"tag\": "zimbalon",\n \"popularity\": 19575\n },\n {\n \"tag\": "annexational",\n \"popularity\": 19542\n },\n {\n \"tag\": "eurhodol",\n \"popularity\": 19508\n },\n {\n \"tag\": "yark",\n \"popularity\": 19475\n },\n {\n \"tag\": "illegality nitroalizarin",\n \"popularity\": 19442\n },\n {\n \"tag\": "quadratum",\n \"popularity\": 19409\n },\n {\n \"tag\": "saccharine",\n \"popularity\": 19376\n },\n {\n \"tag\": "unemploy",\n \"popularity\": 19343\n },\n {\n \"tag\": "uniclinal unipotent",\n \"popularity\": 19310\n },\n {\n \"tag\": "turbo",\n \"popularity\": 19277\n },\n {\n \"tag\": "sybarism",\n \"popularity\": 19244\n },\n {\n \"tag\": "motacilline",\n \"popularity\": 19212\n },\n {\n \"tag\": "weaselly",\n \"popularity\": 19179\n },\n {\n \"tag\": "plastid",\n \"popularity\": 19147\n },\n {\n \"tag\": "wasting",\n \"popularity\": 19114\n },\n {\n \"tag\": "begrime fluting",\n \"popularity\": 19082\n },\n {\n \"tag\": "Nephilinae",\n \"popularity\": 19050\n },\n {\n \"tag\": "disregardance",\n \"popularity\": 19018\n },\n {\n \"tag\": "Shakerlike",\n \"popularity\": 18986\n },\n {\n \"tag\": "uniped",\n \"popularity\": 18954\n },\n {\n \"tag\": "knap",\n \"popularity\": 18922\n },\n {\n \"tag\": "electivism undergardener",\n \"popularity\": 18890\n },\n {\n \"tag\": "hulverheaded",\n \"popularity\": 18858\n },\n {\n \"tag\": "unruptured",\n \"popularity\": 18827\n },\n {\n \"tag\": "solemnize credently",\n \"popularity\": 18795\n },\n {\n \"tag\": "pentastomoid possessingly",\n \"popularity\": 18764\n },\n {\n \"tag\": "octose",\n \"popularity\": 18733\n },\n {\n \"tag\": "psithurism indefensibility",\n \"popularity\": 18701\n },\n {\n \"tag\": "torrentuous cyanometer subcrenate",\n \"popularity\": 18670\n },\n {\n \"tag\": "photoplaywright tapaculo",\n \"popularity\": 18639\n },\n {\n \"tag\": "univalence",\n \"popularity\": 18608\n },\n {\n \"tag\": "Porthetria",\n \"popularity\": 18577\n },\n {\n \"tag\": "funambulo",\n \"popularity\": 18546\n },\n {\n \"tag\": "pedion",\n \"popularity\": 18515\n },\n {\n \"tag\": "horticulturally",\n \"popularity\": 18485\n },\n {\n \"tag\": "marennin",\n \"popularity\": 18454\n },\n {\n \"tag\": "horselaugh",\n \"popularity\": 18423\n },\n {\n \"tag\": "semiexecutive",\n \"popularity\": 18393\n },\n {\n \"tag\": "Monopteridae",\n \"popularity\": 18363\n },\n {\n \"tag\": "commonable",\n \"popularity\": 18332\n },\n {\n \"tag\": "dreariment",\n \"popularity\": 18302\n },\n {\n \"tag\": "disbud",\n \"popularity\": 18272\n },\n {\n \"tag\": "monocled",\n \"popularity\": 18242\n },\n {\n \"tag\": "hurlbarrow",\n \"popularity\": 18212\n },\n {\n \"tag\": "opiateproof",\n \"popularity\": 18182\n },\n {\n \"tag\": "Fahrenheit",\n \"popularity\": 18152\n },\n {\n \"tag\": "writhed",\n \"popularity\": 18122\n },\n {\n \"tag\": "Volstead",\n \"popularity\": 18093\n },\n {\n \"tag\": "yesternight",\n \"popularity\": 18063\n },\n {\n \"tag\": "readmittance",\n \"popularity\": 18033\n },\n {\n \"tag\": "reiterable",\n \"popularity\": 18004\n },\n {\n \"tag\": "triquetral",\n \"popularity\": 17975\n },\n {\n \"tag\": "guillotinement",\n \"popularity\": 17945\n },\n {\n \"tag\": "repermission",\n \"popularity\": 17916\n },\n {\n \"tag\": "assishly",\n \"popularity\": 17887\n },\n {\n \"tag\": "daidle",\n \"popularity\": 17858\n },\n {\n \"tag\": "prismatoid",\n \"popularity\": 17829\n },\n {\n \"tag\": "irreptitious",\n \"popularity\": 17800\n },\n {\n \"tag\": "sourdeline",\n \"popularity\": 17771\n },\n {\n \"tag\": "Austrian",\n \"popularity\": 17742\n },\n {\n \"tag\": "psychorrhagic",\n \"popularity\": 17713\n },\n {\n \"tag\": "Monumbo",\n \"popularity\": 17685\n },\n {\n \"tag\": "cloiochoanitic",\n \"popularity\": 17656\n },\n {\n \"tag\": "hant",\n \"popularity\": 17628\n },\n {\n \"tag\": "roily pulldown",\n \"popularity\": 17599\n },\n {\n \"tag\": "recongratulation",\n \"popularity\": 17571\n },\n {\n \"tag\": "Peking",\n \"popularity\": 17543\n },\n {\n \"tag\": "erdvark",\n \"popularity\": 17514\n },\n {\n \"tag\": "antimnemonic",\n \"popularity\": 17486\n },\n {\n \"tag\": "noncapillarity",\n \"popularity\": 17458\n },\n {\n \"tag\": "irrepressive",\n \"popularity\": 17430\n },\n {\n \"tag\": "Petromyzontes",\n \"popularity\": 17402\n },\n {\n \"tag\": "piscatorially",\n \"popularity\": 17374\n },\n {\n \"tag\": "cholesterosis",\n \"popularity\": 17346\n },\n {\n \"tag\": "denunciate",\n \"popularity\": 17319\n },\n {\n \"tag\": "unmetalled",\n \"popularity\": 17291\n },\n {\n \"tag\": "Tigris enruin",\n \"popularity\": 17263\n },\n {\n \"tag\": "anaspalin",\n \"popularity\": 17236\n },\n {\n \"tag\": "monodromy",\n \"popularity\": 17208\n },\n {\n \"tag\": "Canichanan",\n \"popularity\": 17181\n },\n {\n \"tag\": "mesolabe",\n \"popularity\": 17154\n },\n {\n \"tag\": "trichothallic overcunningness",\n \"popularity\": 17127\n },\n {\n \"tag\": "spinsterishly",\n \"popularity\": 17099\n },\n {\n \"tag\": "sensilla",\n \"popularity\": 17072\n },\n {\n \"tag\": "wifelkin",\n \"popularity\": 17045\n },\n {\n \"tag\": "suppositionless",\n \"popularity\": 17018\n },\n {\n \"tag\": "irksomeness",\n \"popularity\": 16991\n },\n {\n \"tag\": "sanbenito",\n \"popularity\": 16964\n },\n {\n \"tag\": "nonstatement",\n \"popularity\": 16938\n },\n {\n \"tag\": "phenoloid",\n \"popularity\": 16911\n },\n {\n \"tag\": "Steinberger",\n \"popularity\": 16884\n },\n {\n \"tag\": "replicated boom",\n \"popularity\": 16858\n },\n {\n \"tag\": "sciomachiology",\n \"popularity\": 16831\n },\n {\n \"tag\": "starwise",\n \"popularity\": 16805\n },\n {\n \"tag\": "prerich",\n \"popularity\": 16778\n },\n {\n \"tag\": "unspawned",\n \"popularity\": 16752\n },\n {\n \"tag\": "unindentable",\n \"popularity\": 16726\n },\n {\n \"tag\": "stromatic",\n \"popularity\": 16700\n },\n {\n \"tag\": "fetishize",\n \"popularity\": 16673\n },\n {\n \"tag\": "dihydroxy",\n \"popularity\": 16647\n },\n {\n \"tag\": "precaudal",\n \"popularity\": 16621\n },\n {\n \"tag\": "Madagascar",\n \"popularity\": 16595\n },\n {\n \"tag\": "repinement",\n \"popularity\": 16570\n },\n {\n \"tag\": "noncathedral wenzel",\n \"popularity\": 16544\n },\n {\n \"tag\": "corollike",\n \"popularity\": 16518\n },\n {\n \"tag\": "pubes unamortization",\n \"popularity\": 16492\n },\n {\n \"tag\": "brickcroft",\n \"popularity\": 16467\n },\n {\n \"tag\": "intertrabecular",\n \"popularity\": 16441\n },\n {\n \"tag\": "formulaic",\n \"popularity\": 16416\n },\n {\n \"tag\": "arienzo",\n \"popularity\": 16390\n },\n {\n \"tag\": "Mazzinian",\n \"popularity\": 16365\n },\n {\n \"tag\": "wallowishly",\n \"popularity\": 16339\n },\n {\n \"tag\": "sysselman",\n \"popularity\": 16314\n },\n {\n \"tag\": "seligmannite",\n \"popularity\": 16289\n },\n {\n \"tag\": "harlequinery",\n \"popularity\": 16264\n },\n {\n \"tag\": "zucchetto",\n \"popularity\": 16239\n },\n {\n \"tag\": "malonyl",\n \"popularity\": 16214\n },\n {\n \"tag\": "patwari",\n \"popularity\": 16189\n },\n {\n \"tag\": "neoholmia venturesomeness",\n \"popularity\": 16164\n },\n {\n \"tag\": "Dehwar",\n \"popularity\": 16139\n },\n {\n \"tag\": "fetiferous",\n \"popularity\": 16114\n },\n {\n \"tag\": "chromatophore",\n \"popularity\": 16090\n },\n {\n \"tag\": "reregistration",\n \"popularity\": 16065\n },\n {\n \"tag\": "alienor",\n \"popularity\": 16040\n },\n {\n \"tag\": "Hexagynia",\n \"popularity\": 16016\n },\n {\n \"tag\": "cerebrotonia",\n \"popularity\": 15991\n },\n {\n \"tag\": "deedbox",\n \"popularity\": 15967\n },\n {\n \"tag\": "staab",\n \"popularity\": 15943\n },\n {\n \"tag\": "uratemia",\n \"popularity\": 15918\n },\n {\n \"tag\": "flaunt",\n \"popularity\": 15894\n },\n {\n \"tag\": "bogy",\n \"popularity\": 15870\n },\n {\n \"tag\": "subcartilaginous",\n \"popularity\": 15846\n },\n {\n \"tag\": "protonephridial",\n \"popularity\": 15822\n },\n {\n \"tag\": "Boswellia",\n \"popularity\": 15798\n },\n {\n \"tag\": "relaxant untiaraed protoepiphyte",\n \"popularity\": 15774\n },\n {\n \"tag\": "nesslerization",\n \"popularity\": 15750\n },\n {\n \"tag\": "precession",\n \"popularity\": 15726\n },\n {\n \"tag\": "peat",\n \"popularity\": 15702\n },\n {\n \"tag\": "unbit",\n \"popularity\": 15678\n },\n {\n \"tag\": "snailish",\n \"popularity\": 15655\n },\n {\n \"tag\": "porismatical",\n \"popularity\": 15631\n },\n {\n \"tag\": "hooflike",\n \"popularity\": 15608\n },\n {\n \"tag\": "resuppose phene cranic",\n \"popularity\": 15584\n },\n {\n \"tag\": "peptonization kipskin",\n \"popularity\": 15561\n },\n {\n \"tag\": "birdstone",\n \"popularity\": 15537\n },\n {\n \"tag\": "empty inferoanterior",\n \"popularity\": 15514\n },\n {\n \"tag\": "androtauric",\n \"popularity\": 15491\n },\n {\n \"tag\": "triamide",\n \"popularity\": 15467\n },\n {\n \"tag\": "showmanry",\n \"popularity\": 15444\n },\n {\n \"tag\": "doing",\n \"popularity\": 15421\n },\n {\n \"tag\": "bouchaleen",\n \"popularity\": 15398\n },\n {\n \"tag\": "precollude",\n \"popularity\": 15375\n },\n {\n \"tag\": "finger",\n \"popularity\": 15352\n },\n {\n \"tag\": "limnetic intermessenger",\n \"popularity\": 15329\n },\n {\n \"tag\": "uncharitable picrotoxic",\n \"popularity\": 15306\n },\n {\n \"tag\": "nationalizer Phasmidae",\n \"popularity\": 15283\n },\n {\n \"tag\": "laughingstock",\n \"popularity\": 15261\n },\n {\n \"tag\": "nondeferential",\n \"popularity\": 15238\n },\n {\n \"tag\": "uproariously",\n \"popularity\": 15215\n },\n {\n \"tag\": "manzanilla",\n \"popularity\": 15193\n },\n {\n \"tag\": "khahoon",\n \"popularity\": 15170\n },\n {\n \"tag\": "olericulturally longshanks",\n \"popularity\": 15148\n },\n {\n \"tag\": "enthusiastically methionic",\n \"popularity\": 15125\n },\n {\n \"tag\": "pobs",\n \"popularity\": 15103\n },\n {\n \"tag\": "tricarpellate",\n \"popularity\": 15081\n },\n {\n \"tag\": "souterrain",\n \"popularity\": 15058\n },\n {\n \"tag\": "tethelin",\n \"popularity\": 15036\n },\n {\n \"tag\": "tartle",\n \"popularity\": 15014\n },\n {\n \"tag\": "tidelike",\n \"popularity\": 14992\n },\n {\n \"tag\": "cosmoramic",\n \"popularity\": 14970\n },\n {\n \"tag\": "pretardiness",\n \"popularity\": 14948\n },\n {\n \"tag\": "insoul",\n \"popularity\": 14926\n },\n {\n \"tag\": "anthroxan",\n \"popularity\": 14904\n },\n {\n \"tag\": "jilter",\n \"popularity\": 14882\n },\n {\n \"tag\": "pectinibranchian trematode",\n \"popularity\": 14860\n },\n {\n \"tag\": "Renaissancist",\n \"popularity\": 14838\n },\n {\n \"tag\": "imaginant",\n \"popularity\": 14817\n },\n {\n \"tag\": "supercensure",\n \"popularity\": 14795\n },\n {\n \"tag\": "festilogy",\n \"popularity\": 14773\n },\n {\n \"tag\": "regression",\n \"popularity\": 14752\n },\n {\n \"tag\": "mesobregmate languorously",\n \"popularity\": 14730\n },\n {\n \"tag\": "unsupernaturalized",\n \"popularity\": 14709\n },\n {\n \"tag\": "boobyish",\n \"popularity\": 14687\n },\n {\n \"tag\": "scopolamine",\n \"popularity\": 14666\n },\n {\n \"tag\": "reamputation unchristianly",\n \"popularity\": 14645\n },\n {\n \"tag\": "cuneatic",\n \"popularity\": 14623\n },\n {\n \"tag\": "heathberry",\n \"popularity\": 14602\n },\n {\n \"tag\": "hate",\n \"popularity\": 14581\n },\n {\n \"tag\": "redeemableness",\n \"popularity\": 14560\n },\n {\n \"tag\": "damasse",\n \"popularity\": 14539\n },\n {\n \"tag\": "thrillsome",\n \"popularity\": 14518\n },\n {\n \"tag\": "disseverment",\n \"popularity\": 14497\n },\n {\n \"tag\": "underbishopric Ostyak",\n \"popularity\": 14476\n },\n {\n \"tag\": "Exoascales",\n \"popularity\": 14455\n },\n {\n \"tag\": "soiled",\n \"popularity\": 14434\n },\n {\n \"tag\": "Cain",\n \"popularity\": 14413\n },\n {\n \"tag\": "mismanageable arenae",\n \"popularity\": 14392\n },\n {\n \"tag\": "manducate unhinderably",\n \"popularity\": 14372\n },\n {\n \"tag\": "peregrin",\n \"popularity\": 14351\n },\n {\n \"tag\": "musicianly",\n \"popularity\": 14330\n },\n {\n \"tag\": "aln",\n \"popularity\": 14310\n },\n {\n \"tag\": "intercentrum",\n \"popularity\": 14289\n },\n {\n \"tag\": "roothold",\n \"popularity\": 14269\n },\n {\n \"tag\": "jane aneurism",\n \"popularity\": 14248\n },\n {\n \"tag\": "insinuatively forefeel phytolatrous",\n \"popularity\": 14228\n },\n {\n \"tag\": "kanchil",\n \"popularity\": 14208\n },\n {\n \"tag\": "Austrophile",\n \"popularity\": 14187\n },\n {\n \"tag\": "unterrorized",\n \"popularity\": 14167\n },\n {\n \"tag\": "admeasure",\n \"popularity\": 14147\n },\n {\n \"tag\": "electrodissolution",\n \"popularity\": 14127\n },\n {\n \"tag\": "unweddedly",\n \"popularity\": 14107\n },\n {\n \"tag\": "unannoying",\n \"popularity\": 14087\n },\n {\n \"tag\": "uningenuous",\n \"popularity\": 14067\n },\n {\n \"tag\": "omnibenevolent",\n \"popularity\": 14047\n },\n {\n \"tag\": "commissure",\n \"popularity\": 14027\n },\n {\n \"tag\": "tellureted",\n \"popularity\": 14007\n },\n {\n \"tag\": "suffragan",\n \"popularity\": 13987\n },\n {\n \"tag\": "sphaeriaceous",\n \"popularity\": 13967\n },\n {\n \"tag\": "unfearing",\n \"popularity\": 13947\n },\n {\n \"tag\": "stentoriousness precounsellor",\n \"popularity\": 13928\n },\n {\n \"tag\": "haemaspectroscope",\n \"popularity\": 13908\n },\n {\n \"tag\": "teras",\n \"popularity\": 13888\n },\n {\n \"tag\": "pulicine",\n \"popularity\": 13869\n },\n {\n \"tag\": "colicystopyelitis",\n \"popularity\": 13849\n },\n {\n \"tag\": "Physalia",\n \"popularity\": 13830\n },\n {\n \"tag\": "Saxicolidae",\n \"popularity\": 13810\n },\n {\n \"tag\": "peritonital",\n \"popularity\": 13791\n },\n {\n \"tag\": "dysphotic",\n \"popularity\": 13771\n },\n {\n \"tag\": "unabandoned",\n \"popularity\": 13752\n },\n {\n \"tag\": "rashful",\n \"popularity\": 13733\n },\n {\n \"tag\": "goodyness Manobo",\n \"popularity\": 13714\n },\n {\n \"tag\": "glaring",\n \"popularity\": 13694\n },\n {\n \"tag\": "horrorful",\n \"popularity\": 13675\n },\n {\n \"tag\": "intercepting",\n \"popularity\": 13656\n },\n {\n \"tag\": "semifine",\n \"popularity\": 13637\n },\n {\n \"tag\": "Gaypoo",\n \"popularity\": 13618\n },\n {\n \"tag\": "Metrosideros",\n \"popularity\": 13599\n },\n {\n \"tag\": "thoracicolumbar",\n \"popularity\": 13580\n },\n {\n \"tag\": "unserried",\n \"popularity\": 13561\n },\n {\n \"tag\": "keeperess cauterization",\n \"popularity\": 13542\n },\n {\n \"tag\": "administrant",\n \"popularity\": 13523\n },\n {\n \"tag\": "unpropitiatedness",\n \"popularity\": 13505\n },\n {\n \"tag\": "pensileness",\n \"popularity\": 13486\n },\n {\n \"tag\": "quinaldic unreceivable",\n \"popularity\": 13467\n },\n {\n \"tag\": "Carnaria",\n \"popularity\": 13448\n },\n {\n \"tag\": "azothionium wurrus",\n \"popularity\": 13430\n },\n {\n \"tag\": "mistresshood",\n \"popularity\": 13411\n },\n {\n \"tag\": "Savara",\n \"popularity\": 13393\n },\n {\n \"tag\": "dasyurine",\n \"popularity\": 13374\n },\n {\n \"tag\": "superideal",\n \"popularity\": 13356\n },\n {\n \"tag\": "Parisianize",\n \"popularity\": 13337\n },\n {\n \"tag\": "underearth",\n \"popularity\": 13319\n },\n {\n \"tag\": "athrogenic",\n \"popularity\": 13301\n },\n {\n \"tag\": "communicate",\n \"popularity\": 13282\n },\n {\n \"tag\": "denervation enworthed",\n \"popularity\": 13264\n },\n {\n \"tag\": "subbromide",\n \"popularity\": 13246\n },\n {\n \"tag\": "stenocoriasis",\n \"popularity\": 13228\n },\n {\n \"tag\": "facetiousness",\n \"popularity\": 13209\n },\n {\n \"tag\": "twaddling",\n \"popularity\": 13191\n },\n {\n \"tag\": "tetartoconid",\n \"popularity\": 13173\n },\n {\n \"tag\": "audiophile",\n \"popularity\": 13155\n },\n {\n \"tag\": "fustigate",\n \"popularity\": 13137\n },\n {\n \"tag\": "Sorbian cacophonia",\n \"popularity\": 13119\n },\n {\n \"tag\": "fondish",\n \"popularity\": 13101\n },\n {\n \"tag\": "endomastoiditis",\n \"popularity\": 13084\n },\n {\n \"tag\": "sniptious",\n \"popularity\": 13066\n },\n {\n \"tag\": "glochidiate",\n \"popularity\": 13048\n },\n {\n \"tag\": "polycarboxylic",\n \"popularity\": 13030\n },\n {\n \"tag\": "stamp",\n \"popularity\": 13012\n },\n {\n \"tag\": "tritonymph endotoxoid",\n \"popularity\": 12995\n },\n {\n \"tag\": "wolfskin",\n \"popularity\": 12977\n },\n {\n \"tag\": "oncosimeter",\n \"popularity\": 12959\n },\n {\n \"tag\": "outward",\n \"popularity\": 12942\n },\n {\n \"tag\": "circumscribed",\n \"popularity\": 12924\n },\n {\n \"tag\": "autohemolytic",\n \"popularity\": 12907\n },\n {\n \"tag\": "isorhamnose",\n \"popularity\": 12889\n },\n {\n \"tag\": "monarchomachic",\n \"popularity\": 12872\n },\n {\n \"tag\": "phaenomenon",\n \"popularity\": 12855\n },\n {\n \"tag\": "angiopressure",\n \"popularity\": 12837\n },\n {\n \"tag\": "similarize",\n \"popularity\": 12820\n },\n {\n \"tag\": "unseeable",\n \"popularity\": 12803\n },\n {\n \"tag\": "Toryize",\n \"popularity\": 12785\n },\n {\n \"tag\": "fruitling",\n \"popularity\": 12768\n },\n {\n \"tag\": "axle",\n \"popularity\": 12751\n },\n {\n \"tag\": "priestal cocked",\n \"popularity\": 12734\n },\n {\n \"tag\": "serotoxin",\n \"popularity\": 12717\n },\n {\n \"tag\": "unmovably",\n \"popularity\": 12700\n },\n {\n \"tag\": "darbha",\n \"popularity\": 12683\n },\n {\n \"tag\": "Mongolize",\n \"popularity\": 12666\n },\n {\n \"tag\": "clusteringly",\n \"popularity\": 12649\n },\n {\n \"tag\": "tendence",\n \"popularity\": 12632\n },\n {\n \"tag\": "foziness",\n \"popularity\": 12615\n },\n {\n \"tag\": "brickkiln lithify",\n \"popularity\": 12598\n },\n {\n \"tag\": "unpriest",\n \"popularity\": 12581\n },\n {\n \"tag\": "convincer",\n \"popularity\": 12564\n },\n {\n \"tag\": "mornlike",\n \"popularity\": 12548\n },\n {\n \"tag\": "overaddiction ostentatiousness",\n \"popularity\": 12531\n },\n {\n \"tag\": "diffusively moccasin pendom",\n \"popularity\": 12514\n },\n {\n \"tag\": "boose",\n \"popularity\": 12498\n },\n {\n \"tag\": "myonosus",\n \"popularity\": 12481\n },\n {\n \"tag\": "handsome",\n \"popularity\": 12464\n },\n {\n \"tag\": "paroxysmic",\n \"popularity\": 12448\n },\n {\n \"tag\": "Ulidian",\n \"popularity\": 12431\n },\n {\n \"tag\": "heartache",\n \"popularity\": 12415\n },\n {\n \"tag\": "torporize",\n \"popularity\": 12398\n },\n {\n \"tag\": "hippish",\n \"popularity\": 12382\n },\n {\n \"tag\": "stigmal militation",\n \"popularity\": 12366\n },\n {\n \"tag\": "matmaker",\n \"popularity\": 12349\n },\n {\n \"tag\": "marantaceous bivoluminous",\n \"popularity\": 12333\n },\n {\n \"tag\": "Uraniidae",\n \"popularity\": 12317\n },\n {\n \"tag\": "risper",\n \"popularity\": 12301\n },\n {\n \"tag\": "tintinnabulation",\n \"popularity\": 12284\n },\n {\n \"tag\": "tributorian",\n \"popularity\": 12268\n },\n {\n \"tag\": "ashamedly",\n \"popularity\": 12252\n },\n {\n \"tag\": "Macrourus",\n \"popularity\": 12236\n },\n {\n \"tag\": "Chora",\n \"popularity\": 12220\n },\n {\n \"tag\": "caul",\n \"popularity\": 12204\n },\n {\n \"tag\": "exsector",\n \"popularity\": 12188\n },\n {\n \"tag\": "acutish",\n \"popularity\": 12172\n },\n {\n \"tag\": "amphichrome",\n \"popularity\": 12156\n },\n {\n \"tag\": "guarder",\n \"popularity\": 12140\n },\n {\n \"tag\": "sculpturally",\n \"popularity\": 12124\n },\n {\n \"tag\": "benightmare",\n \"popularity\": 12108\n },\n {\n \"tag\": "chucky",\n \"popularity\": 12093\n },\n {\n \"tag\": "Venetian",\n \"popularity\": 12077\n },\n {\n \"tag\": "autotheater",\n \"popularity\": 12061\n },\n {\n \"tag\": "planarioid",\n \"popularity\": 12045\n },\n {\n \"tag\": "handkerchiefful",\n \"popularity\": 12030\n },\n {\n \"tag\": "fuliginousness potentize",\n \"popularity\": 12014\n },\n {\n \"tag\": "pantheum",\n \"popularity\": 11998\n },\n {\n \"tag\": "heavyweight",\n \"popularity\": 11983\n },\n {\n \"tag\": "unbrick",\n \"popularity\": 11967\n },\n {\n \"tag\": "duomachy",\n \"popularity\": 11952\n },\n {\n \"tag\": "polyphyodont",\n \"popularity\": 11936\n },\n {\n \"tag\": "hibernacle",\n \"popularity\": 11921\n },\n {\n \"tag\": "undistend",\n \"popularity\": 11905\n },\n {\n \"tag\": "hystericky",\n \"popularity\": 11890\n },\n {\n \"tag\": "paleolimnology",\n \"popularity\": 11875\n },\n {\n \"tag\": "cedarware",\n \"popularity\": 11859\n },\n {\n \"tag\": "overwrested",\n \"popularity\": 11844\n },\n {\n \"tag\": "Syriacism",\n \"popularity\": 11829\n },\n {\n \"tag\": "pretan",\n \"popularity\": 11813\n },\n {\n \"tag\": "formant",\n \"popularity\": 11798\n },\n {\n \"tag\": "pharmacopoeist Fedia",\n \"popularity\": 11783\n },\n {\n \"tag\": "exorcist eerisome",\n \"popularity\": 11768\n },\n {\n \"tag\": "separation",\n \"popularity\": 11753\n },\n {\n \"tag\": "infancy",\n \"popularity\": 11738\n },\n {\n \"tag\": "ecrasite",\n \"popularity\": 11723\n },\n {\n \"tag\": "propolize",\n \"popularity\": 11708\n },\n {\n \"tag\": "uncram phyllin",\n \"popularity\": 11693\n },\n {\n \"tag\": "thymopathy",\n \"popularity\": 11678\n },\n {\n \"tag\": "omniscient",\n \"popularity\": 11663\n },\n {\n \"tag\": "coussinet hazer",\n \"popularity\": 11648\n },\n {\n \"tag\": "contributiveness",\n \"popularity\": 11633\n },\n {\n \"tag\": "septifluous",\n \"popularity\": 11618\n },\n {\n \"tag\": "halfness",\n \"popularity\": 11603\n },\n {\n \"tag\": "tocher",\n \"popularity\": 11589\n },\n {\n \"tag\": "monotonist",\n \"popularity\": 11574\n },\n {\n \"tag\": "headchair",\n \"popularity\": 11559\n },\n {\n \"tag\": "everywhence",\n \"popularity\": 11544\n },\n {\n \"tag\": "gerate",\n \"popularity\": 11530\n },\n {\n \"tag\": "unrepellent",\n \"popularity\": 11515\n },\n {\n \"tag\": "inidoneous",\n \"popularity\": 11500\n },\n {\n \"tag\": "Rifi",\n \"popularity\": 11486\n },\n {\n \"tag\": "unstop",\n \"popularity\": 11471\n },\n {\n \"tag\": "conformer",\n \"popularity\": 11457\n },\n {\n \"tag\": "vivisectionally",\n \"popularity\": 11442\n },\n {\n \"tag\": "nonfinishing",\n \"popularity\": 11428\n },\n {\n \"tag\": "tyranness",\n \"popularity\": 11413\n },\n {\n \"tag\": "shepherdage havoc",\n \"popularity\": 11399\n },\n {\n \"tag\": "coronale",\n \"popularity\": 11385\n },\n {\n \"tag\": "airmarker",\n \"popularity\": 11370\n },\n {\n \"tag\": "subpanel",\n \"popularity\": 11356\n },\n {\n \"tag\": "conciliation",\n \"popularity\": 11342\n },\n {\n \"tag\": "supergun",\n \"popularity\": 11327\n },\n {\n \"tag\": "photoheliography",\n \"popularity\": 11313\n },\n {\n \"tag\": "cacosmia",\n \"popularity\": 11299\n },\n {\n \"tag\": "caressant",\n \"popularity\": 11285\n },\n {\n \"tag\": "swivet",\n \"popularity\": 11270\n },\n {\n \"tag\": "coddler",\n \"popularity\": 11256\n },\n {\n \"tag\": "rakehellish",\n \"popularity\": 11242\n },\n {\n \"tag\": "recohabitation",\n \"popularity\": 11228\n },\n {\n \"tag\": "postillator",\n \"popularity\": 11214\n },\n {\n \"tag\": "receipt",\n \"popularity\": 11200\n },\n {\n \"tag\": "nonconformistical",\n \"popularity\": 11186\n },\n {\n \"tag\": "unglorified",\n \"popularity\": 11172\n },\n {\n \"tag\": "unordinariness",\n \"popularity\": 11158\n },\n {\n \"tag\": "tetrahydroxy",\n \"popularity\": 11144\n },\n {\n \"tag\": "haploperistomic corporeity",\n \"popularity\": 11130\n },\n {\n \"tag\": "varical",\n \"popularity\": 11117\n },\n {\n \"tag\": "pilferment",\n \"popularity\": 11103\n },\n {\n \"tag\": "reverentially playcraft",\n \"popularity\": 11089\n },\n {\n \"tag\": "unretentive",\n \"popularity\": 11075\n },\n {\n \"tag\": "readiness",\n \"popularity\": 11061\n },\n {\n \"tag\": "thermomagnetism",\n \"popularity\": 11048\n },\n {\n \"tag\": "spotless",\n \"popularity\": 11034\n },\n {\n \"tag\": "semishrubby",\n \"popularity\": 11020\n },\n {\n \"tag\": "metrotomy",\n \"popularity\": 11007\n },\n {\n \"tag\": "hocker",\n \"popularity\": 10993\n },\n {\n \"tag\": "anecdotal",\n \"popularity\": 10979\n },\n {\n \"tag\": "tetrabelodont",\n \"popularity\": 10966\n },\n {\n \"tag\": "Ramillied",\n \"popularity\": 10952\n },\n {\n \"tag\": "sympatheticism",\n \"popularity\": 10939\n },\n {\n \"tag\": "kiskatom",\n \"popularity\": 10925\n },\n {\n \"tag\": "concyclically",\n \"popularity\": 10912\n },\n {\n \"tag\": "tunicless",\n \"popularity\": 10899\n },\n {\n \"tag\": "formalistic",\n \"popularity\": 10885\n },\n {\n \"tag\": "thermacogenesis",\n \"popularity\": 10872\n },\n {\n \"tag\": "multimotored",\n \"popularity\": 10858\n },\n {\n \"tag\": "inversive",\n \"popularity\": 10845\n },\n {\n \"tag\": "Jatki",\n \"popularity\": 10832\n },\n {\n \"tag\": "highest",\n \"popularity\": 10818\n },\n {\n \"tag\": "rubidic",\n \"popularity\": 10805\n },\n {\n \"tag\": "acranial",\n \"popularity\": 10792\n },\n {\n \"tag\": "pulvinulus",\n \"popularity\": 10779\n },\n {\n \"tag\": "nattiness",\n \"popularity\": 10766\n },\n {\n \"tag\": "antisimoniacal",\n \"popularity\": 10752\n },\n {\n \"tag\": "tetanize",\n \"popularity\": 10739\n },\n {\n \"tag\": "spectrophobia",\n \"popularity\": 10726\n },\n {\n \"tag\": "monopolitical",\n \"popularity\": 10713\n },\n {\n \"tag\": "teallite",\n \"popularity\": 10700\n },\n {\n \"tag\": "alicyclic interpellator",\n \"popularity\": 10687\n },\n {\n \"tag\": "nonsynthesized",\n \"popularity\": 10674\n },\n {\n \"tag\": "wheelwrighting",\n \"popularity\": 10661\n },\n {\n \"tag\": "pelliculate",\n \"popularity\": 10648\n },\n {\n \"tag\": "Euphyllopoda",\n \"popularity\": 10635\n },\n {\n \"tag\": "graver",\n \"popularity\": 10622\n },\n {\n \"tag\": "automorph",\n \"popularity\": 10609\n },\n {\n \"tag\": "underhanded",\n \"popularity\": 10597\n },\n {\n \"tag\": "causal",\n \"popularity\": 10584\n },\n {\n \"tag\": "odoom",\n \"popularity\": 10571\n },\n {\n \"tag\": "apodictical",\n \"popularity\": 10558\n },\n {\n \"tag\": "foundery",\n \"popularity\": 10545\n },\n {\n \"tag\": "unneighbored",\n \"popularity\": 10533\n },\n {\n \"tag\": "woolshearing",\n \"popularity\": 10520\n },\n {\n \"tag\": "boschveld",\n \"popularity\": 10507\n },\n {\n \"tag\": "unhardened lipopod",\n \"popularity\": 10495\n },\n {\n \"tag\": "unenriching",\n \"popularity\": 10482\n },\n {\n \"tag\": "spak",\n \"popularity\": 10469\n },\n {\n \"tag\": "yogasana",\n \"popularity\": 10457\n },\n {\n \"tag\": "depoetize",\n \"popularity\": 10444\n },\n {\n \"tag\": "parousiamania",\n \"popularity\": 10432\n },\n {\n \"tag\": "longlegs",\n \"popularity\": 10419\n },\n {\n \"tag\": "gelatinizability",\n \"popularity\": 10407\n },\n {\n \"tag\": "edeology",\n \"popularity\": 10394\n },\n {\n \"tag\": "sodwork",\n \"popularity\": 10382\n },\n {\n \"tag\": "somnambule",\n \"popularity\": 10369\n },\n {\n \"tag\": "antiquing",\n \"popularity\": 10357\n },\n {\n \"tag\": "intaker",\n \"popularity\": 10344\n },\n {\n \"tag\": "Gerberia",\n \"popularity\": 10332\n },\n {\n \"tag\": "preadmit",\n \"popularity\": 10320\n },\n {\n \"tag\": "bullhorn",\n \"popularity\": 10307\n },\n {\n \"tag\": "sororal",\n \"popularity\": 10295\n },\n {\n \"tag\": "phaeophyceous",\n \"popularity\": 10283\n },\n {\n \"tag\": "omphalopsychite",\n \"popularity\": 10271\n },\n {\n \"tag\": "substantious",\n \"popularity\": 10258\n },\n {\n \"tag\": "undemonstratively",\n \"popularity\": 10246\n },\n {\n \"tag\": "corallike blackit",\n \"popularity\": 10234\n },\n {\n \"tag\": "amoebous",\n \"popularity\": 10222\n },\n {\n \"tag\": "Polypodium",\n \"popularity\": 10210\n },\n {\n \"tag\": "blodite",\n \"popularity\": 10198\n },\n {\n \"tag\": "hordarian",\n \"popularity\": 10186\n },\n {\n \"tag\": "nonmoral",\n \"popularity\": 10174\n },\n {\n \"tag\": "dredgeful",\n \"popularity\": 10162\n },\n {\n \"tag\": "nourishingly",\n \"popularity\": 10150\n },\n {\n \"tag\": "seamy",\n \"popularity\": 10138\n },\n {\n \"tag\": "vara",\n \"popularity\": 10126\n },\n {\n \"tag\": "incorruptibleness",\n \"popularity\": 10114\n },\n {\n \"tag\": "manipulator",\n \"popularity\": 10102\n },\n {\n \"tag\": "chromodiascope uncountably",\n \"popularity\": 10090\n },\n {\n \"tag\": "typhemia",\n \"popularity\": 10078\n },\n {\n \"tag\": "Smalcaldic",\n \"popularity\": 10066\n },\n {\n \"tag\": "precontrive",\n \"popularity\": 10054\n },\n {\n \"tag\": "sowarry",\n \"popularity\": 10042\n },\n {\n \"tag\": "monopodic",\n \"popularity\": 10031\n },\n {\n \"tag\": "recodify",\n \"popularity\": 10019\n },\n {\n \"tag\": "phosphowolframic rimple",\n \"popularity\": 10007\n },\n {\n \"tag\": "triconch",\n \"popularity\": 9995\n },\n {\n \"tag\": "pycnodontoid",\n \"popularity\": 9984\n },\n {\n \"tag\": "bradyspermatism",\n \"popularity\": 9972\n },\n {\n \"tag\": "extensionist",\n \"popularity\": 9960\n },\n {\n \"tag\": "characterize",\n \"popularity\": 9949\n },\n {\n \"tag\": "anatreptic proteolytic",\n \"popularity\": 9937\n },\n {\n \"tag\": "waterboard",\n \"popularity\": 9925\n },\n {\n \"tag\": "allopathically",\n \"popularity\": 9914\n },\n {\n \"tag\": "arithmetician",\n \"popularity\": 9902\n },\n {\n \"tag\": "subsist",\n \"popularity\": 9891\n },\n {\n \"tag\": "Islamitish",\n \"popularity\": 9879\n },\n {\n \"tag\": "biddy",\n \"popularity\": 9868\n },\n {\n \"tag\": "reverberation",\n \"popularity\": 9856\n },\n {\n \"tag\": "Zaporogue",\n \"popularity\": 9845\n },\n {\n \"tag\": "soapberry",\n \"popularity\": 9833\n },\n {\n \"tag\": "physiognomics",\n \"popularity\": 9822\n },\n {\n \"tag\": "hospitalization",\n \"popularity\": 9810\n },\n {\n \"tag\": "dissembler",\n \"popularity\": 9799\n },\n {\n \"tag\": "festinate",\n \"popularity\": 9788\n },\n {\n \"tag\": "angiectopia",\n \"popularity\": 9776\n },\n {\n \"tag\": "Pulicidae",\n \"popularity\": 9765\n },\n {\n \"tag\": "beslimer",\n \"popularity\": 9754\n },\n {\n \"tag\": "nontreaty",\n \"popularity\": 9743\n },\n {\n \"tag\": "unhaggled",\n \"popularity\": 9731\n },\n {\n \"tag\": "catfall",\n \"popularity\": 9720\n },\n {\n \"tag\": "stola",\n \"popularity\": 9709\n },\n {\n \"tag\": "pataco",\n \"popularity\": 9698\n },\n {\n \"tag\": "ontologistic",\n \"popularity\": 9686\n },\n {\n \"tag\": "aerosphere",\n \"popularity\": 9675\n },\n {\n \"tag\": "deobstruent",\n \"popularity\": 9664\n },\n {\n \"tag\": "threepence",\n \"popularity\": 9653\n },\n {\n \"tag\": "cyprinoid",\n \"popularity\": 9642\n },\n {\n \"tag\": "overbank",\n \"popularity\": 9631\n },\n {\n \"tag\": "prostyle",\n \"popularity\": 9620\n },\n {\n \"tag\": "photoactivation",\n \"popularity\": 9609\n },\n {\n \"tag\": "homothetic",\n \"popularity\": 9598\n },\n {\n \"tag\": "roguedom",\n \"popularity\": 9587\n },\n {\n \"tag\": "underschool",\n \"popularity\": 9576\n },\n {\n \"tag\": "tractility",\n \"popularity\": 9565\n },\n {\n \"tag\": "gardenin",\n \"popularity\": 9554\n },\n {\n \"tag\": "Micromastictora",\n \"popularity\": 9543\n },\n {\n \"tag\": "gossypine",\n \"popularity\": 9532\n },\n {\n \"tag\": "amylodyspepsia",\n \"popularity\": 9521\n },\n {\n \"tag\": "Luciana",\n \"popularity\": 9510\n },\n {\n \"tag\": "meetly nonfisherman",\n \"popularity\": 9500\n },\n {\n \"tag\": "backhanded",\n \"popularity\": 9489\n },\n {\n \"tag\": "decrustation",\n \"popularity\": 9478\n },\n {\n \"tag\": "pinrail",\n \"popularity\": 9467\n },\n {\n \"tag\": "Mahori",\n \"popularity\": 9456\n },\n {\n \"tag\": "unsizable",\n \"popularity\": 9446\n },\n {\n \"tag\": "disawa",\n \"popularity\": 9435\n },\n {\n \"tag\": "launderability inconsidered",\n \"popularity\": 9424\n },\n {\n \"tag\": "unclassical",\n \"popularity\": 9414\n },\n {\n \"tag\": "inobtrusiveness",\n \"popularity\": 9403\n },\n {\n \"tag\": "sialogenous",\n \"popularity\": 9392\n },\n {\n \"tag\": "sulphonamide",\n \"popularity\": 9382\n },\n {\n \"tag\": "diluvion",\n \"popularity\": 9371\n },\n {\n \"tag\": "deuteranope",\n \"popularity\": 9361\n },\n {\n \"tag\": "addition",\n \"popularity\": 9350\n },\n {\n \"tag\": "bockeret",\n \"popularity\": 9339\n },\n {\n \"tag\": "unidentified",\n \"popularity\": 9329\n },\n {\n \"tag\": "caryatic",\n \"popularity\": 9318\n },\n {\n \"tag\": "misattribution",\n \"popularity\": 9308\n },\n {\n \"tag\": "outray",\n \"popularity\": 9297\n },\n {\n \"tag\": "areometrical",\n \"popularity\": 9287\n },\n {\n \"tag\": "antilogism",\n \"popularity\": 9277\n },\n {\n \"tag\": "inadjustable",\n \"popularity\": 9266\n },\n {\n \"tag\": "byssus",\n \"popularity\": 9256\n },\n {\n \"tag\": "trun",\n \"popularity\": 9245\n },\n {\n \"tag\": "thereology",\n \"popularity\": 9235\n },\n {\n \"tag\": "extort",\n \"popularity\": 9225\n },\n {\n \"tag\": "bumpkin",\n \"popularity\": 9214\n },\n {\n \"tag\": "sulphobenzide",\n \"popularity\": 9204\n },\n {\n \"tag\": "hydrogeology",\n \"popularity\": 9194\n },\n {\n \"tag\": "nidulariaceous",\n \"popularity\": 9183\n },\n {\n \"tag\": "propodiale",\n \"popularity\": 9173\n },\n {\n \"tag\": "fierily",\n \"popularity\": 9163\n },\n {\n \"tag\": "aerotonometry",\n \"popularity\": 9153\n },\n {\n \"tag\": "pelobatid oversuperstitious",\n \"popularity\": 9142\n },\n {\n \"tag\": "restringent",\n \"popularity\": 9132\n },\n {\n \"tag\": "tetrapodic",\n \"popularity\": 9122\n },\n {\n \"tag\": "heroicness Vendidad",\n \"popularity\": 9112\n },\n {\n \"tag\": "Sphingurus",\n \"popularity\": 9102\n },\n {\n \"tag\": "sclerote",\n \"popularity\": 9092\n },\n {\n \"tag\": "unkeyed",\n \"popularity\": 9082\n },\n {\n \"tag\": "superparliamentary",\n \"popularity\": 9072\n },\n {\n \"tag\": "hetericism",\n \"popularity\": 9061\n },\n {\n \"tag\": "hucklebone",\n \"popularity\": 9051\n },\n {\n \"tag\": "yojan",\n \"popularity\": 9041\n },\n {\n \"tag\": "bossed",\n \"popularity\": 9031\n },\n {\n \"tag\": "spiderwork",\n \"popularity\": 9021\n },\n {\n \"tag\": "millfeed dullery",\n \"popularity\": 9011\n },\n {\n \"tag\": "adnoun",\n \"popularity\": 9001\n },\n {\n \"tag\": "mesometric",\n \"popularity\": 8992\n },\n {\n \"tag\": "doublehandedness",\n \"popularity\": 8982\n },\n {\n \"tag\": "suppurant",\n \"popularity\": 8972\n },\n {\n \"tag\": "Berlinize",\n \"popularity\": 8962\n },\n {\n \"tag\": "sontag",\n \"popularity\": 8952\n },\n {\n \"tag\": "biplane",\n \"popularity\": 8942\n },\n {\n \"tag\": "insula",\n \"popularity\": 8932\n },\n {\n \"tag\": "unbrand",\n \"popularity\": 8922\n },\n {\n \"tag\": "Basilosaurus",\n \"popularity\": 8913\n },\n {\n \"tag\": "prenomination",\n \"popularity\": 8903\n },\n {\n \"tag\": "untextual",\n \"popularity\": 8893\n },\n {\n \"tag\": "coleslaw",\n \"popularity\": 8883\n },\n {\n \"tag\": "langsyne",\n \"popularity\": 8874\n },\n {\n \"tag\": "impede",\n \"popularity\": 8864\n },\n {\n \"tag\": "irrigator",\n \"popularity\": 8854\n },\n {\n \"tag\": "deflocculation",\n \"popularity\": 8844\n },\n {\n \"tag\": "narghile",\n \"popularity\": 8835\n },\n {\n \"tag\": "unguardedly ebenaceous",\n \"popularity\": 8825\n },\n {\n \"tag\": "conversantly subocular",\n \"popularity\": 8815\n },\n {\n \"tag\": "hydroponic",\n \"popularity\": 8806\n },\n {\n \"tag\": "anthropopsychism",\n \"popularity\": 8796\n },\n {\n \"tag\": "panoptic",\n \"popularity\": 8787\n },\n {\n \"tag\": "insufferable",\n \"popularity\": 8777\n },\n {\n \"tag\": "salema",\n \"popularity\": 8768\n },\n {\n \"tag\": "Myriapoda",\n \"popularity\": 8758\n },\n {\n \"tag\": "regarrison",\n \"popularity\": 8748\n },\n {\n \"tag\": "overlearned",\n \"popularity\": 8739\n },\n {\n \"tag\": "ultraroyalist conventical bureaucratical",\n \"popularity\": 8729\n },\n {\n \"tag\": "epicaridan",\n \"popularity\": 8720\n },\n {\n \"tag\": "poetastress",\n \"popularity\": 8711\n },\n {\n \"tag\": "monophthalmus",\n \"popularity\": 8701\n },\n {\n \"tag\": "simnel",\n \"popularity\": 8692\n },\n {\n \"tag\": "compotor",\n \"popularity\": 8682\n },\n {\n \"tag\": "hydrolase",\n \"popularity\": 8673\n },\n {\n \"tag\": "attemptless",\n \"popularity\": 8663\n },\n {\n \"tag\": "visceroptosis",\n \"popularity\": 8654\n },\n {\n \"tag\": "unpreparedly",\n \"popularity\": 8645\n },\n {\n \"tag\": "mastage",\n \"popularity\": 8635\n },\n {\n \"tag\": "preinfluence",\n \"popularity\": 8626\n },\n {\n \"tag\": "Siwan",\n \"popularity\": 8617\n },\n {\n \"tag\": "ceratotheca belvedere",\n \"popularity\": 8607\n },\n {\n \"tag\": "disenablement",\n \"popularity\": 8598\n },\n {\n \"tag\": "nine",\n \"popularity\": 8589\n },\n {\n \"tag\": "spellingdown abridgment",\n \"popularity\": 8580\n },\n {\n \"tag\": "twilightless",\n \"popularity\": 8571\n },\n {\n \"tag\": "overflow",\n \"popularity\": 8561\n },\n {\n \"tag\": "mismeasurement",\n \"popularity\": 8552\n },\n {\n \"tag\": "nawabship",\n \"popularity\": 8543\n },\n {\n \"tag\": "Phrynosoma",\n \"popularity\": 8534\n },\n {\n \"tag\": "unanticipatingly",\n \"popularity\": 8525\n },\n {\n \"tag\": "blankite",\n \"popularity\": 8516\n },\n {\n \"tag\": "role",\n \"popularity\": 8506\n },\n {\n \"tag\": "peperine edelweiss",\n \"popularity\": 8497\n },\n {\n \"tag\": "unhysterical",\n \"popularity\": 8488\n },\n {\n \"tag\": "attentiveness",\n \"popularity\": 8479\n },\n {\n \"tag\": "scintillant",\n \"popularity\": 8470\n },\n {\n \"tag\": "stenostomatous",\n \"popularity\": 8461\n },\n {\n \"tag\": "pectinite",\n \"popularity\": 8452\n },\n {\n \"tag\": "herring",\n \"popularity\": 8443\n },\n {\n \"tag\": "interroom",\n \"popularity\": 8434\n },\n {\n \"tag\": "laccol",\n \"popularity\": 8425\n },\n {\n \"tag\": "unpartably kylite",\n \"popularity\": 8416\n },\n {\n \"tag\": "spirivalve",\n \"popularity\": 8407\n },\n {\n \"tag\": "hoosegow",\n \"popularity\": 8398\n },\n {\n \"tag\": "doat",\n \"popularity\": 8389\n },\n {\n \"tag\": "amphibian",\n \"popularity\": 8380\n },\n {\n \"tag\": "exposit",\n \"popularity\": 8371\n },\n {\n \"tag\": "canopy",\n \"popularity\": 8363\n },\n {\n \"tag\": "houndlike",\n \"popularity\": 8354\n },\n {\n \"tag\": "spikebill",\n \"popularity\": 8345\n },\n {\n \"tag\": "wiseacre pyrotechnic",\n \"popularity\": 8336\n },\n {\n \"tag\": "confessingly woodman",\n \"popularity\": 8327\n },\n {\n \"tag\": "overside",\n \"popularity\": 8318\n },\n {\n \"tag\": "oftwhiles",\n \"popularity\": 8310\n },\n {\n \"tag\": "Musophagidae",\n \"popularity\": 8301\n },\n {\n \"tag\": "slumberer",\n \"popularity\": 8292\n },\n {\n \"tag\": "leiotrichy",\n \"popularity\": 8283\n },\n {\n \"tag\": "Mantispidae",\n \"popularity\": 8275\n },\n {\n \"tag\": "perceptually",\n \"popularity\": 8266\n },\n {\n \"tag\": "biller",\n \"popularity\": 8257\n },\n {\n \"tag\": "eudaemonical",\n \"popularity\": 8249\n },\n {\n \"tag\": "underfiend",\n \"popularity\": 8240\n },\n {\n \"tag\": "impartible",\n \"popularity\": 8231\n },\n {\n \"tag\": "saxicavous",\n \"popularity\": 8223\n },\n {\n \"tag\": "yapster",\n \"popularity\": 8214\n },\n {\n \"tag\": "aliseptal",\n \"popularity\": 8205\n },\n {\n \"tag\": "omniparient",\n \"popularity\": 8197\n },\n {\n \"tag\": "nishiki",\n \"popularity\": 8188\n },\n {\n \"tag\": "yuzluk",\n \"popularity\": 8180\n },\n {\n \"tag\": "solderer",\n \"popularity\": 8171\n },\n {\n \"tag\": "Pinna",\n \"popularity\": 8162\n },\n {\n \"tag\": "reinterfere",\n \"popularity\": 8154\n },\n {\n \"tag\": "superepic",\n \"popularity\": 8145\n },\n {\n \"tag\": "ronquil",\n \"popularity\": 8137\n },\n {\n \"tag\": "bratstvo",\n \"popularity\": 8128\n },\n {\n \"tag\": "Thea",\n \"popularity\": 8120\n },\n {\n \"tag\": "hermaphroditical",\n \"popularity\": 8111\n },\n {\n \"tag\": "enlief",\n \"popularity\": 8103\n },\n {\n \"tag\": "Jesuate",\n \"popularity\": 8095\n },\n {\n \"tag\": "gaysome",\n \"popularity\": 8086\n },\n {\n \"tag\": "iliohypogastric",\n \"popularity\": 8078\n },\n {\n \"tag\": "regardance",\n \"popularity\": 8069\n },\n {\n \"tag\": "cumulately",\n \"popularity\": 8061\n },\n {\n \"tag\": "haustorial nucleolocentrosome",\n \"popularity\": 8053\n },\n {\n \"tag\": "cosmocrat",\n \"popularity\": 8044\n },\n {\n \"tag\": "onyxitis",\n \"popularity\": 8036\n },\n {\n \"tag\": "Cabinda",\n \"popularity\": 8028\n },\n {\n \"tag\": "coresort",\n \"popularity\": 8019\n },\n {\n \"tag\": "drusy preformant",\n \"popularity\": 8011\n },\n {\n \"tag\": "piningly",\n \"popularity\": 8003\n },\n {\n \"tag\": "bootlessly",\n \"popularity\": 7994\n },\n {\n \"tag\": "talari",\n \"popularity\": 7986\n },\n {\n \"tag\": "amidoacetal",\n \"popularity\": 7978\n },\n {\n \"tag\": "pschent",\n \"popularity\": 7970\n },\n {\n \"tag\": "consumptional scarer titivate",\n \"popularity\": 7962\n },\n {\n \"tag\": "Anserinae",\n \"popularity\": 7953\n },\n {\n \"tag\": "flaunter",\n \"popularity\": 7945\n },\n {\n \"tag\": "reindeer",\n \"popularity\": 7937\n },\n {\n \"tag\": "disparage",\n \"popularity\": 7929\n },\n {\n \"tag\": "superheat",\n \"popularity\": 7921\n },\n {\n \"tag\": "Chromatium",\n \"popularity\": 7912\n },\n {\n \"tag\": "Tina",\n \"popularity\": 7904\n },\n {\n \"tag\": "rededicatory",\n \"popularity\": 7896\n },\n {\n \"tag\": "nontransient",\n \"popularity\": 7888\n },\n {\n \"tag\": "Phocaean brinkless",\n \"popularity\": 7880\n },\n {\n \"tag\": "ventriculose",\n \"popularity\": 7872\n },\n {\n \"tag\": "upplough",\n \"popularity\": 7864\n },\n {\n \"tag\": "succorless",\n \"popularity\": 7856\n },\n {\n \"tag\": "hayrake",\n \"popularity\": 7848\n },\n {\n \"tag\": "merriness amorphia",\n \"popularity\": 7840\n },\n {\n \"tag\": "merycism",\n \"popularity\": 7832\n },\n {\n \"tag\": "checkrow",\n \"popularity\": 7824\n },\n {\n \"tag\": "scry",\n \"popularity\": 7816\n },\n {\n \"tag\": "obvolve",\n \"popularity\": 7808\n },\n {\n \"tag\": "orchard",\n \"popularity\": 7800\n },\n {\n \"tag\": "isomerize",\n \"popularity\": 7792\n },\n {\n \"tag\": "competitrix",\n \"popularity\": 7784\n },\n {\n \"tag\": "unbannered",\n \"popularity\": 7776\n },\n {\n \"tag\": "undoctrined",\n \"popularity\": 7768\n },\n {\n \"tag\": "theologian",\n \"popularity\": 7760\n },\n {\n \"tag\": "nebby",\n \"popularity\": 7752\n },\n {\n \"tag\": "Cardiazol",\n \"popularity\": 7745\n },\n {\n \"tag\": "phagedenic",\n \"popularity\": 7737\n },\n {\n \"tag\": "nostalgic",\n \"popularity\": 7729\n },\n {\n \"tag\": "orthodoxy",\n \"popularity\": 7721\n },\n {\n \"tag\": "oversanguine",\n \"popularity\": 7713\n },\n {\n \"tag\": "lish",\n \"popularity\": 7705\n },\n {\n \"tag\": "ketogenic",\n \"popularity\": 7698\n },\n {\n \"tag\": "syndicalize",\n \"popularity\": 7690\n },\n {\n \"tag\": "leeftail",\n \"popularity\": 7682\n },\n {\n \"tag\": "bulbomedullary",\n \"popularity\": 7674\n },\n {\n \"tag\": "reletter",\n \"popularity\": 7667\n },\n {\n \"tag\": "bitterly",\n \"popularity\": 7659\n },\n {\n \"tag\": "participatory",\n \"popularity\": 7651\n },\n {\n \"tag\": "baldberry",\n \"popularity\": 7643\n },\n {\n \"tag\": "prowaterpower",\n \"popularity\": 7636\n },\n {\n \"tag\": "lexicographical",\n \"popularity\": 7628\n },\n {\n \"tag\": "Anisodactyli",\n \"popularity\": 7620\n },\n {\n \"tag\": "amphipodous",\n \"popularity\": 7613\n },\n {\n \"tag\": "triglandular",\n \"popularity\": 7605\n },\n {\n \"tag\": "xanthopsin",\n \"popularity\": 7597\n },\n {\n \"tag\": "indefinitude",\n \"popularity\": 7590\n },\n {\n \"tag\": "bookworm",\n \"popularity\": 7582\n },\n {\n \"tag\": "suffocative",\n \"popularity\": 7574\n },\n {\n \"tag\": "uncongested tyrant",\n \"popularity\": 7567\n },\n {\n \"tag\": "alow harmoniously Pamir",\n \"popularity\": 7559\n },\n {\n \"tag\": "monander",\n \"popularity\": 7552\n },\n {\n \"tag\": "bagatelle",\n \"popularity\": 7544\n },\n {\n \"tag\": "membranology",\n \"popularity\": 7537\n },\n {\n \"tag\": "parturifacient",\n \"popularity\": 7529\n },\n {\n \"tag\": "excitovascular",\n \"popularity\": 7522\n },\n {\n \"tag\": "homopolar",\n \"popularity\": 7514\n },\n {\n \"tag\": "phobiac",\n \"popularity\": 7507\n },\n {\n \"tag\": "clype",\n \"popularity\": 7499\n },\n {\n \"tag\": "unsubversive",\n \"popularity\": 7492\n },\n {\n \"tag\": "bostrychoidal scorpionwort",\n \"popularity\": 7484\n },\n {\n \"tag\": "biliteralism",\n \"popularity\": 7477\n },\n {\n \"tag\": "dentatocostate",\n \"popularity\": 7469\n },\n {\n \"tag\": "Pici",\n \"popularity\": 7462\n },\n {\n \"tag\": "sideritic",\n \"popularity\": 7454\n },\n {\n \"tag\": "syntaxis",\n \"popularity\": 7447\n },\n {\n \"tag\": "ingest",\n \"popularity\": 7440\n },\n {\n \"tag\": "rigmarolish",\n \"popularity\": 7432\n },\n {\n \"tag\": "ocreaceous",\n \"popularity\": 7425\n },\n {\n \"tag\": "hyperbrachyskelic",\n \"popularity\": 7418\n },\n {\n \"tag\": "basophobia",\n \"popularity\": 7410\n },\n {\n \"tag\": "substantialness",\n \"popularity\": 7403\n },\n {\n \"tag\": "agglutinoid",\n \"popularity\": 7396\n },\n {\n \"tag\": "longleaf",\n \"popularity\": 7388\n },\n {\n \"tag\": "electroengraving",\n \"popularity\": 7381\n },\n {\n \"tag\": "laparoenterotomy",\n \"popularity\": 7374\n },\n {\n \"tag\": "oxalylurea",\n \"popularity\": 7366\n },\n {\n \"tag\": "unattaintedly",\n \"popularity\": 7359\n },\n {\n \"tag\": "pennystone",\n \"popularity\": 7352\n },\n {\n \"tag\": "Plumbaginaceae",\n \"popularity\": 7345\n },\n {\n \"tag\": "horntip",\n \"popularity\": 7337\n },\n {\n \"tag\": "begrudge",\n \"popularity\": 7330\n },\n {\n \"tag\": "bechignoned",\n \"popularity\": 7323\n },\n {\n \"tag\": "hologonidium",\n \"popularity\": 7316\n },\n {\n \"tag\": "Pulian",\n \"popularity\": 7309\n },\n {\n \"tag\": "gratulation",\n \"popularity\": 7301\n },\n {\n \"tag\": "Sebright",\n \"popularity\": 7294\n },\n {\n \"tag\": "coinstantaneous emotionally",\n \"popularity\": 7287\n },\n {\n \"tag\": "thoracostracan",\n \"popularity\": 7280\n },\n {\n \"tag\": "saurodont",\n \"popularity\": 7273\n },\n {\n \"tag\": "coseat",\n \"popularity\": 7266\n },\n {\n \"tag\": "irascibility",\n \"popularity\": 7259\n },\n {\n \"tag\": "occlude",\n \"popularity\": 7251\n },\n {\n \"tag\": "metallurgist",\n \"popularity\": 7244\n },\n {\n \"tag\": "extraviolet",\n \"popularity\": 7237\n },\n {\n \"tag\": "clinic",\n \"popularity\": 7230\n },\n {\n \"tag\": "skater",\n \"popularity\": 7223\n },\n {\n \"tag\": "linguistic",\n \"popularity\": 7216\n },\n {\n \"tag\": "attacheship",\n \"popularity\": 7209\n },\n {\n \"tag\": "Rachianectes",\n \"popularity\": 7202\n },\n {\n \"tag\": "foliolose",\n \"popularity\": 7195\n },\n {\n \"tag\": "claudetite",\n \"popularity\": 7188\n },\n {\n \"tag\": "aphidian scratching",\n \"popularity\": 7181\n },\n {\n \"tag\": "Carida",\n \"popularity\": 7174\n },\n {\n \"tag\": "tiepin polymicroscope",\n \"popularity\": 7167\n },\n {\n \"tag\": "telpherage",\n \"popularity\": 7160\n },\n {\n \"tag\": "meek",\n \"popularity\": 7153\n },\n {\n \"tag\": "swiftness",\n \"popularity\": 7146\n },\n {\n \"tag\": "gentes",\n \"popularity\": 7139\n },\n {\n \"tag\": "uncommemorated",\n \"popularity\": 7132\n },\n {\n \"tag\": "Lazarus",\n \"popularity\": 7125\n },\n {\n \"tag\": "redivive",\n \"popularity\": 7119\n },\n {\n \"tag\": "nonfebrile",\n \"popularity\": 7112\n },\n {\n \"tag\": "nymphet",\n \"popularity\": 7105\n },\n {\n \"tag\": "areologically",\n \"popularity\": 7098\n },\n {\n \"tag\": "undonkey",\n \"popularity\": 7091\n },\n {\n \"tag\": "projecting",\n \"popularity\": 7084\n },\n {\n \"tag\": "pinnigrade",\n \"popularity\": 7077\n },\n {\n \"tag\": "butylation",\n \"popularity\": 7071\n },\n {\n \"tag\": "philologistic lenticle",\n \"popularity\": 7064\n },\n {\n \"tag\": "nooky",\n \"popularity\": 7057\n },\n {\n \"tag\": "incestuousness",\n \"popularity\": 7050\n },\n {\n \"tag\": "palingenetically",\n \"popularity\": 7043\n },\n {\n \"tag\": "mitochondria",\n \"popularity\": 7037\n },\n {\n \"tag\": "truthify",\n \"popularity\": 7030\n },\n {\n \"tag\": "titanyl",\n \"popularity\": 7023\n },\n {\n \"tag\": "bestride",\n \"popularity\": 7016\n },\n {\n \"tag\": "chende",\n \"popularity\": 7010\n },\n {\n \"tag\": "Chaucerian monophote",\n \"popularity\": 7003\n },\n {\n \"tag\": "cutback",\n \"popularity\": 6996\n },\n {\n \"tag\": "unpatiently",\n \"popularity\": 6989\n },\n {\n \"tag\": "subvitreous",\n \"popularity\": 6983\n },\n {\n \"tag\": "organizable",\n \"popularity\": 6976\n },\n {\n \"tag\": "anniverse uncomprehensible",\n \"popularity\": 6969\n },\n {\n \"tag\": "hyalescence",\n \"popularity\": 6963\n },\n {\n \"tag\": "amniochorial",\n \"popularity\": 6956\n },\n {\n \"tag\": "Corybantian",\n \"popularity\": 6949\n },\n {\n \"tag\": "genocide Scaphitidae",\n \"popularity\": 6943\n },\n {\n \"tag\": "accordionist",\n \"popularity\": 6936\n },\n {\n \"tag\": "becheck",\n \"popularity\": 6930\n },\n {\n \"tag\": "overproduce",\n \"popularity\": 6923\n },\n {\n \"tag\": "unmaniac frijolillo",\n \"popularity\": 6916\n },\n {\n \"tag\": "multisulcated",\n \"popularity\": 6910\n },\n {\n \"tag\": "wennebergite",\n \"popularity\": 6903\n },\n {\n \"tag\": "tautousious mowth",\n \"popularity\": 6897\n },\n {\n \"tag\": "marigold",\n \"popularity\": 6890\n },\n {\n \"tag\": "affray",\n \"popularity\": 6884\n },\n {\n \"tag\": "nonidolatrous",\n \"popularity\": 6877\n },\n {\n \"tag\": "aphrasia",\n \"popularity\": 6871\n },\n {\n \"tag\": "muddlingly",\n \"popularity\": 6864\n },\n {\n \"tag\": "clear",\n \"popularity\": 6858\n },\n {\n \"tag\": "Clitoria",\n \"popularity\": 6851\n },\n {\n \"tag\": "apportionment underwaist",\n \"popularity\": 6845\n },\n {\n \"tag\": "kodakist",\n \"popularity\": 6838\n },\n {\n \"tag\": "Momotidae",\n \"popularity\": 6832\n },\n {\n \"tag\": "cryptovalency",\n \"popularity\": 6825\n },\n {\n \"tag\": "floe",\n \"popularity\": 6819\n },\n {\n \"tag\": "aphagia",\n \"popularity\": 6812\n },\n {\n \"tag\": "brontograph",\n \"popularity\": 6806\n },\n {\n \"tag\": "tubulous",\n \"popularity\": 6799\n },\n {\n \"tag\": "unhorse",\n \"popularity\": 6793\n },\n {\n \"tag\": "chlordane",\n \"popularity\": 6787\n },\n {\n \"tag\": "colloquy brochan",\n \"popularity\": 6780\n },\n {\n \"tag\": "sloosh",\n \"popularity\": 6774\n },\n {\n \"tag\": "battered",\n \"popularity\": 6767\n },\n {\n \"tag\": "monocularity pluriguttulate",\n \"popularity\": 6761\n },\n {\n \"tag\": "chiastoneury",\n \"popularity\": 6755\n },\n {\n \"tag\": "Sanguinaria",\n \"popularity\": 6748\n },\n {\n \"tag\": "confessionary",\n \"popularity\": 6742\n },\n {\n \"tag\": "enzymic",\n \"popularity\": 6736\n },\n {\n \"tag\": "cord",\n \"popularity\": 6729\n },\n {\n \"tag\": "oviducal",\n \"popularity\": 6723\n },\n {\n \"tag\": "crozzle outsea",\n \"popularity\": 6717\n },\n {\n \"tag\": "balladical",\n \"popularity\": 6710\n },\n {\n \"tag\": "uncollectibleness",\n \"popularity\": 6704\n },\n {\n \"tag\": "predorsal",\n \"popularity\": 6698\n },\n {\n \"tag\": "reauthenticate",\n \"popularity\": 6692\n },\n {\n \"tag\": "ravissant",\n \"popularity\": 6685\n },\n {\n \"tag\": "advantageousness",\n \"popularity\": 6679\n },\n {\n \"tag\": "rung",\n \"popularity\": 6673\n },\n {\n \"tag\": "duncedom",\n \"popularity\": 6667\n },\n {\n \"tag\": "hematolite",\n \"popularity\": 6660\n },\n {\n \"tag\": "thisness",\n \"popularity\": 6654\n },\n {\n \"tag\": "mapau",\n \"popularity\": 6648\n },\n {\n \"tag\": "Hecatic",\n \"popularity\": 6642\n },\n {\n \"tag\": "meningoencephalocele",\n \"popularity\": 6636\n },\n {\n \"tag\": "confection sorra",\n \"popularity\": 6630\n },\n {\n \"tag\": "unsedate",\n \"popularity\": 6623\n },\n {\n \"tag\": "meningocerebritis",\n \"popularity\": 6617\n },\n {\n \"tag\": "biopsychological",\n \"popularity\": 6611\n },\n {\n \"tag\": "clavicithern",\n \"popularity\": 6605\n },\n {\n \"tag\": "resun",\n \"popularity\": 6599\n },\n {\n \"tag\": "bayamo",\n \"popularity\": 6593\n },\n {\n \"tag\": "seeableness",\n \"popularity\": 6587\n },\n {\n \"tag\": "hypsidolichocephalism",\n \"popularity\": 6581\n },\n {\n \"tag\": "salivous",\n \"popularity\": 6574\n },\n {\n \"tag\": "neumatize",\n \"popularity\": 6568\n },\n {\n \"tag\": "stree",\n \"popularity\": 6562\n },\n {\n \"tag\": "markshot",\n \"popularity\": 6556\n },\n {\n \"tag\": "phraseologically",\n \"popularity\": 6550\n },\n {\n \"tag\": "yealing",\n \"popularity\": 6544\n },\n {\n \"tag\": "puggy",\n \"popularity\": 6538\n },\n {\n \"tag\": "sexadecimal",\n \"popularity\": 6532\n },\n {\n \"tag\": "unofficerlike",\n \"popularity\": 6526\n },\n {\n \"tag\": "curiosa",\n \"popularity\": 6520\n },\n {\n \"tag\": "pedomotor",\n \"popularity\": 6514\n },\n {\n \"tag\": "astrally",\n \"popularity\": 6508\n },\n {\n \"tag\": "prosomatic",\n \"popularity\": 6502\n },\n {\n \"tag\": "bulletheaded",\n \"popularity\": 6496\n },\n {\n \"tag\": "fortuned",\n \"popularity\": 6490\n },\n {\n \"tag\": "pixy",\n \"popularity\": 6484\n },\n {\n \"tag\": "protectrix",\n \"popularity\": 6478\n },\n {\n \"tag\": "arthritical",\n \"popularity\": 6472\n },\n {\n \"tag\": "coction",\n \"popularity\": 6466\n },\n {\n \"tag\": "Anthropos",\n \"popularity\": 6460\n },\n {\n \"tag\": "runer",\n \"popularity\": 6454\n },\n {\n \"tag\": "prenotify",\n \"popularity\": 6449\n },\n {\n \"tag\": "microspheric gastroparalysis",\n \"popularity\": 6443\n },\n {\n \"tag\": "Jovicentrical",\n \"popularity\": 6437\n },\n {\n \"tag\": "ceratopsid",\n \"popularity\": 6431\n },\n {\n \"tag\": "Theodoric",\n \"popularity\": 6425\n },\n {\n \"tag\": "Pactolus",\n \"popularity\": 6419\n },\n {\n \"tag\": "spawning",\n \"popularity\": 6413\n },\n {\n \"tag\": "nonconfidential",\n \"popularity\": 6407\n },\n {\n \"tag\": "halotrichite infumate",\n \"popularity\": 6402\n },\n {\n \"tag\": "undiscriminatingly",\n \"popularity\": 6396\n },\n {\n \"tag\": "unexasperated",\n \"popularity\": 6390\n },\n {\n \"tag\": "isoeugenol",\n \"popularity\": 6384\n },\n {\n \"tag\": "pressboard",\n \"popularity\": 6378\n },\n {\n \"tag\": "unshrew",\n \"popularity\": 6372\n },\n {\n \"tag\": "huffingly",\n \"popularity\": 6367\n },\n {\n \"tag\": "wagaun",\n \"popularity\": 6361\n },\n {\n \"tag\": "squirt Philistine",\n \"popularity\": 6355\n },\n {\n \"tag\": "kryptic",\n \"popularity\": 6349\n },\n {\n \"tag\": "paraform",\n \"popularity\": 6344\n },\n {\n \"tag\": "preverify",\n \"popularity\": 6338\n },\n {\n \"tag\": "dalar",\n \"popularity\": 6332\n },\n {\n \"tag\": "interdictor appraisingly",\n \"popularity\": 6326\n },\n {\n \"tag\": "chipped",\n \"popularity\": 6321\n },\n {\n \"tag\": "Pteropoda",\n \"popularity\": 6315\n },\n {\n \"tag\": "Bohairic",\n \"popularity\": 6309\n },\n {\n \"tag\": "felting",\n \"popularity\": 6303\n },\n {\n \"tag\": "compurgatorial",\n \"popularity\": 6298\n },\n {\n \"tag\": "unclead",\n \"popularity\": 6292\n },\n {\n \"tag\": "stockish",\n \"popularity\": 6286\n },\n {\n \"tag\": "mulligatawny",\n \"popularity\": 6281\n },\n {\n \"tag\": "Monotheletism",\n \"popularity\": 6275\n },\n {\n \"tag\": "lutanist",\n \"popularity\": 6269\n },\n {\n \"tag\": "gluttonize",\n \"popularity\": 6264\n },\n {\n \"tag\": "hackneyed",\n \"popularity\": 6258\n },\n {\n \"tag\": "yield",\n \"popularity\": 6253\n },\n {\n \"tag\": "sulphonamido",\n \"popularity\": 6247\n },\n {\n \"tag\": "granulative",\n \"popularity\": 6241\n },\n {\n \"tag\": "swingy",\n \"popularity\": 6236\n },\n {\n \"tag\": "Desmidiales",\n \"popularity\": 6230\n },\n {\n \"tag\": "tootlish",\n \"popularity\": 6224\n },\n {\n \"tag\": "unsatisfiedly",\n \"popularity\": 6219\n },\n {\n \"tag\": "burucha",\n \"popularity\": 6213\n },\n {\n \"tag\": "premeditatingly",\n \"popularity\": 6208\n },\n {\n \"tag\": "cowrie",\n \"popularity\": 6202\n },\n {\n \"tag\": "pleurolysis",\n \"popularity\": 6197\n },\n {\n \"tag\": "nationalist",\n \"popularity\": 6191\n },\n {\n \"tag\": "Pholadacea",\n \"popularity\": 6186\n },\n {\n \"tag\": "anakrousis",\n \"popularity\": 6180\n },\n {\n \"tag\": "proctorial",\n \"popularity\": 6175\n },\n {\n \"tag\": "cavillation",\n \"popularity\": 6169\n },\n {\n \"tag\": "cervicobregmatic",\n \"popularity\": 6163\n },\n {\n \"tag\": "interspecific",\n \"popularity\": 6158\n },\n {\n \"tag\": "Teutonity",\n \"popularity\": 6152\n },\n {\n \"tag\": "snakeholing",\n \"popularity\": 6147\n },\n {\n \"tag\": "balcony",\n \"popularity\": 6142\n },\n {\n \"tag\": "latchless",\n \"popularity\": 6136\n },\n {\n \"tag\": "Mithraea",\n \"popularity\": 6131\n },\n {\n \"tag\": "pseudepigraph",\n \"popularity\": 6125\n },\n {\n \"tag\": "flosser",\n \"popularity\": 6120\n },\n {\n \"tag\": "kotyle",\n \"popularity\": 6114\n },\n {\n \"tag\": "outdo",\n \"popularity\": 6109\n },\n {\n \"tag\": "interclerical",\n \"popularity\": 6103\n },\n {\n \"tag\": "aurar",\n \"popularity\": 6098\n },\n {\n \"tag\": "apophyseal",\n \"popularity\": 6093\n },\n {\n \"tag\": "Miro",\n \"popularity\": 6087\n },\n {\n \"tag\": "Priscillian",\n \"popularity\": 6082\n },\n {\n \"tag\": "alluvia",\n \"popularity\": 6076\n },\n {\n \"tag\": "exordize",\n \"popularity\": 6071\n },\n {\n \"tag\": "breakage",\n \"popularity\": 6066\n },\n {\n \"tag\": "unclosable",\n \"popularity\": 6060\n },\n {\n \"tag\": "monocondylous",\n \"popularity\": 6055\n },\n {\n \"tag\": "dyarchy",\n \"popularity\": 6050\n },\n {\n \"tag\": "subchelate",\n \"popularity\": 6044\n },\n {\n \"tag\": "hearsay",\n \"popularity\": 6039\n },\n {\n \"tag\": "prestigiously",\n \"popularity\": 6034\n },\n {\n \"tag\": "unimuscular",\n \"popularity\": 6028\n },\n {\n \"tag\": "lingwort",\n \"popularity\": 6023\n },\n {\n \"tag\": "jealous",\n \"popularity\": 6018\n },\n {\n \"tag\": "artilleryman",\n \"popularity\": 6012\n },\n {\n \"tag\": "phantasmagorially",\n \"popularity\": 6007\n },\n {\n \"tag\": "stagnum",\n \"popularity\": 6002\n },\n {\n \"tag\": "organotropism shatteringly",\n \"popularity\": 5997\n },\n {\n \"tag\": "Mytilus Hebraist",\n \"popularity\": 5991\n },\n {\n \"tag\": "returf",\n \"popularity\": 5986\n },\n {\n \"tag\": "townfolk",\n \"popularity\": 5981\n },\n {\n \"tag\": "propitiative",\n \"popularity\": 5976\n },\n {\n \"tag\": "Anita unsullied",\n \"popularity\": 5970\n },\n {\n \"tag\": "bandoleered",\n \"popularity\": 5965\n },\n {\n \"tag\": "cubby",\n \"popularity\": 5960\n },\n {\n \"tag\": "Hexanchus",\n \"popularity\": 5955\n },\n {\n \"tag\": "circuminsular",\n \"popularity\": 5949\n },\n {\n \"tag\": "chamberletted eumycete",\n \"popularity\": 5944\n },\n {\n \"tag\": "secure",\n \"popularity\": 5939\n },\n {\n \"tag\": "Edwardean",\n \"popularity\": 5934\n },\n {\n \"tag\": "strenth",\n \"popularity\": 5929\n },\n {\n \"tag\": "exhaustless",\n \"popularity\": 5923\n },\n {\n \"tag\": "electioneerer",\n \"popularity\": 5918\n },\n {\n \"tag\": "estoile",\n \"popularity\": 5913\n },\n {\n \"tag\": "redden",\n \"popularity\": 5908\n },\n {\n \"tag\": "solicitee",\n \"popularity\": 5903\n },\n {\n \"tag\": "nonpatented",\n \"popularity\": 5898\n },\n {\n \"tag\": "lemming",\n \"popularity\": 5893\n },\n {\n \"tag\": "marled subalate",\n \"popularity\": 5887\n },\n {\n \"tag\": "premial horizonward",\n \"popularity\": 5882\n },\n {\n \"tag\": "nonrefueling",\n \"popularity\": 5877\n },\n {\n \"tag\": "rupturewort",\n \"popularity\": 5872\n },\n {\n \"tag\": "unfed",\n \"popularity\": 5867\n },\n {\n \"tag\": "empanelment",\n \"popularity\": 5862\n },\n {\n \"tag\": "isoosmosis",\n \"popularity\": 5857\n },\n {\n \"tag\": "jipijapa",\n \"popularity\": 5852\n },\n {\n \"tag\": "Fiji",\n \"popularity\": 5847\n },\n {\n \"tag\": "interferant",\n \"popularity\": 5842\n },\n {\n \"tag\": "reconstitution",\n \"popularity\": 5837\n },\n {\n \"tag\": "dockyardman",\n \"popularity\": 5832\n },\n {\n \"tag\": "dolichopodous",\n \"popularity\": 5826\n },\n {\n \"tag\": "whiteworm",\n \"popularity\": 5821\n },\n {\n \"tag\": "atheistically",\n \"popularity\": 5816\n },\n {\n \"tag\": "nonconcern",\n \"popularity\": 5811\n },\n {\n \"tag\": "scarabaeidoid",\n \"popularity\": 5806\n },\n {\n \"tag\": "triumviri",\n \"popularity\": 5801\n },\n {\n \"tag\": "rakit",\n \"popularity\": 5796\n },\n {\n \"tag\": "leecheater",\n \"popularity\": 5791\n },\n {\n \"tag\": "Arthrostraca",\n \"popularity\": 5786\n },\n {\n \"tag\": "upknit",\n \"popularity\": 5781\n },\n {\n \"tag\": "tymbalon",\n \"popularity\": 5776\n },\n {\n \"tag\": "inventurous",\n \"popularity\": 5771\n },\n {\n \"tag\": "perradiate",\n \"popularity\": 5766\n },\n {\n \"tag\": "seer",\n \"popularity\": 5762\n },\n {\n \"tag\": "Auricularia",\n \"popularity\": 5757\n },\n {\n \"tag\": "wettish exclusivity",\n \"popularity\": 5752\n },\n {\n \"tag\": "arteriosympathectomy",\n \"popularity\": 5747\n },\n {\n \"tag\": "tunlike",\n \"popularity\": 5742\n },\n {\n \"tag\": "cephalocercal",\n \"popularity\": 5737\n },\n {\n \"tag\": "meaninglessness",\n \"popularity\": 5732\n },\n {\n \"tag\": "fountful",\n \"popularity\": 5727\n },\n {\n \"tag\": "appraisement",\n \"popularity\": 5722\n },\n {\n \"tag\": "geniculated",\n \"popularity\": 5717\n },\n {\n \"tag\": "rotator",\n \"popularity\": 5712\n },\n {\n \"tag\": "foremarch biography",\n \"popularity\": 5707\n },\n {\n \"tag\": "arid",\n \"popularity\": 5703\n },\n {\n \"tag\": "inapprehensible",\n \"popularity\": 5698\n },\n {\n \"tag\": "chlorosulphonic",\n \"popularity\": 5693\n },\n {\n \"tag\": "braguette",\n \"popularity\": 5688\n },\n {\n \"tag\": "panophthalmitis",\n \"popularity\": 5683\n },\n {\n \"tag\": "pro objurgatorily",\n \"popularity\": 5678\n },\n {\n \"tag\": "zooplasty",\n \"popularity\": 5673\n },\n {\n \"tag\": "Terebratulidae",\n \"popularity\": 5669\n },\n {\n \"tag\": "Mahran",\n \"popularity\": 5664\n },\n {\n \"tag\": "anthologize merocele",\n \"popularity\": 5659\n },\n {\n \"tag\": "firecracker chiropractic",\n \"popularity\": 5654\n },\n {\n \"tag\": "tenorist",\n \"popularity\": 5649\n },\n {\n \"tag\": "amphitene",\n \"popularity\": 5645\n },\n {\n \"tag\": "silverbush toadstone",\n \"popularity\": 5640\n },\n {\n \"tag\": "entozoological",\n \"popularity\": 5635\n },\n {\n \"tag\": "trustlessness",\n \"popularity\": 5630\n },\n {\n \"tag\": "reassay",\n \"popularity\": 5625\n },\n {\n \"tag\": "chrysalides",\n \"popularity\": 5621\n },\n {\n \"tag\": "truncation",\n \"popularity\": 5616\n },\n {\n \"tag\": "unwavered mausoleal",\n \"popularity\": 5611\n },\n {\n \"tag\": "unserrated",\n \"popularity\": 5606\n },\n {\n \"tag\": "frampler",\n \"popularity\": 5602\n },\n {\n \"tag\": "celestial",\n \"popularity\": 5597\n },\n {\n \"tag\": "depreter",\n \"popularity\": 5592\n },\n {\n \"tag\": "retaliate",\n \"popularity\": 5588\n },\n {\n \"tag\": "decempunctate",\n \"popularity\": 5583\n },\n {\n \"tag\": "submitter",\n \"popularity\": 5578\n },\n {\n \"tag\": "phenothiazine",\n \"popularity\": 5573\n },\n {\n \"tag\": "hobbledehoyish",\n \"popularity\": 5569\n },\n {\n \"tag\": "erraticness",\n \"popularity\": 5564\n },\n {\n \"tag\": "ovariodysneuria",\n \"popularity\": 5559\n },\n {\n \"tag\": "puja",\n \"popularity\": 5555\n },\n {\n \"tag\": "cesspool",\n \"popularity\": 5550\n },\n {\n \"tag\": "sonation",\n \"popularity\": 5545\n },\n {\n \"tag\": "moggan",\n \"popularity\": 5541\n },\n {\n \"tag\": "overjutting",\n \"popularity\": 5536\n },\n {\n \"tag\": "cohobate",\n \"popularity\": 5531\n },\n {\n \"tag\": "Distoma",\n \"popularity\": 5527\n },\n {\n \"tag\": "Plectognathi",\n \"popularity\": 5522\n },\n {\n \"tag\": "dumple caliphate",\n \"popularity\": 5517\n },\n {\n \"tag\": "shiko",\n \"popularity\": 5513\n },\n {\n \"tag\": "downness",\n \"popularity\": 5508\n },\n {\n \"tag\": "whippletree",\n \"popularity\": 5504\n },\n {\n \"tag\": "nymphaeum",\n \"popularity\": 5499\n },\n {\n \"tag\": "there trest",\n \"popularity\": 5494\n },\n {\n \"tag\": "psychrometer",\n \"popularity\": 5490\n },\n {\n \"tag\": "pyelograph",\n \"popularity\": 5485\n },\n {\n \"tag\": "unsalvable",\n \"popularity\": 5481\n },\n {\n \"tag\": "bescreen",\n \"popularity\": 5476\n },\n {\n \"tag\": "cushy",\n \"popularity\": 5471\n },\n {\n \"tag\": "plicatolobate",\n \"popularity\": 5467\n },\n {\n \"tag\": "lakie",\n \"popularity\": 5462\n },\n {\n \"tag\": "anthropodeoxycholic",\n \"popularity\": 5458\n },\n {\n \"tag\": "resatisfaction",\n \"popularity\": 5453\n },\n {\n \"tag\": "unravelment unaccidental",\n \"popularity\": 5449\n },\n {\n \"tag\": "telewriter monogeneous",\n \"popularity\": 5444\n },\n {\n \"tag\": "unsabred",\n \"popularity\": 5440\n },\n {\n \"tag\": "startlingly",\n \"popularity\": 5435\n },\n {\n \"tag\": "Aralia",\n \"popularity\": 5431\n },\n {\n \"tag\": "alamonti",\n \"popularity\": 5426\n },\n {\n \"tag\": "Franklinization",\n \"popularity\": 5422\n },\n {\n \"tag\": "parliament",\n \"popularity\": 5417\n },\n {\n \"tag\": "schoolkeeper",\n \"popularity\": 5413\n },\n {\n \"tag\": "nonsociety",\n \"popularity\": 5408\n },\n {\n \"tag\": "parenthetic",\n \"popularity\": 5404\n },\n {\n \"tag\": "stog",\n \"popularity\": 5399\n },\n {\n \"tag\": "Pristipomidae",\n \"popularity\": 5395\n },\n {\n \"tag\": "exocarp",\n \"popularity\": 5390\n },\n {\n \"tag\": "monaxonial",\n \"popularity\": 5386\n },\n {\n \"tag\": "tramroad",\n \"popularity\": 5381\n },\n {\n \"tag\": "hookah",\n \"popularity\": 5377\n },\n {\n \"tag\": "saccharonic",\n \"popularity\": 5372\n },\n {\n \"tag\": "perimetrium",\n \"popularity\": 5368\n },\n {\n \"tag\": "libelluloid",\n \"popularity\": 5364\n },\n {\n \"tag\": "overrunningly",\n \"popularity\": 5359\n },\n {\n \"tag\": "untwister",\n \"popularity\": 5355\n },\n {\n \"tag\": "ninnyhammer",\n \"popularity\": 5350\n },\n {\n \"tag\": "metranate",\n \"popularity\": 5346\n },\n {\n \"tag\": "sarcoblast",\n \"popularity\": 5341\n },\n {\n \"tag\": "porkish",\n \"popularity\": 5337\n },\n {\n \"tag\": "chauvinistic",\n \"popularity\": 5333\n },\n {\n \"tag\": "sexagesimal",\n \"popularity\": 5328\n },\n {\n \"tag\": "hematogenic",\n \"popularity\": 5324\n },\n {\n \"tag\": "selfpreservatory",\n \"popularity\": 5320\n },\n {\n \"tag\": "myelauxe",\n \"popularity\": 5315\n },\n {\n \"tag\": "triply",\n \"popularity\": 5311\n },\n {\n \"tag\": "metaphysicous",\n \"popularity\": 5306\n },\n {\n \"tag\": "vitrinoid",\n \"popularity\": 5302\n },\n {\n \"tag\": "glabellae",\n \"popularity\": 5298\n },\n {\n \"tag\": "moonlighter",\n \"popularity\": 5293\n },\n {\n \"tag\": "monotheistically epexegetical",\n \"popularity\": 5289\n },\n {\n \"tag\": "pseudolateral",\n \"popularity\": 5285\n },\n {\n \"tag\": "heptamethylene",\n \"popularity\": 5280\n },\n {\n \"tag\": "salvadora",\n \"popularity\": 5276\n },\n {\n \"tag\": "unjovial diphenylthiourea",\n \"popularity\": 5272\n },\n {\n \"tag\": "thievishness",\n \"popularity\": 5268\n },\n {\n \"tag\": "unridable",\n \"popularity\": 5263\n },\n {\n \"tag\": "underhandedly",\n \"popularity\": 5259\n },\n {\n \"tag\": "fungiform",\n \"popularity\": 5255\n },\n {\n \"tag\": "scruffle",\n \"popularity\": 5250\n },\n {\n \"tag\": "preindisposition",\n \"popularity\": 5246\n },\n {\n \"tag\": "Amadis",\n \"popularity\": 5242\n },\n {\n \"tag\": "Culex",\n \"popularity\": 5238\n },\n {\n \"tag\": "churning",\n \"popularity\": 5233\n },\n {\n \"tag\": "imperite",\n \"popularity\": 5229\n },\n {\n \"tag\": "levorotation",\n \"popularity\": 5225\n },\n {\n \"tag\": "barbate",\n \"popularity\": 5221\n },\n {\n \"tag\": "knotwort",\n \"popularity\": 5216\n },\n {\n \"tag\": "gypsiferous",\n \"popularity\": 5212\n },\n {\n \"tag\": "tourmalinic",\n \"popularity\": 5208\n },\n {\n \"tag\": "helleboric",\n \"popularity\": 5204\n },\n {\n \"tag\": "pneumograph",\n \"popularity\": 5199\n },\n {\n \"tag\": "Peltigeraceae",\n \"popularity\": 5195\n },\n {\n \"tag\": "busine",\n \"popularity\": 5191\n },\n {\n \"tag\": "Ailuridae",\n \"popularity\": 5187\n },\n {\n \"tag\": "azotate",\n \"popularity\": 5183\n },\n {\n \"tag\": "unlikable",\n \"popularity\": 5178\n },\n {\n \"tag\": "sloyd",\n \"popularity\": 5174\n },\n {\n \"tag\": "biblioclasm",\n \"popularity\": 5170\n },\n {\n \"tag\": "Seres",\n \"popularity\": 5166\n },\n {\n \"tag\": "unaccurateness",\n \"popularity\": 5162\n },\n {\n \"tag\": "scrollwise",\n \"popularity\": 5157\n },\n {\n \"tag\": "flandowser",\n \"popularity\": 5153\n },\n {\n \"tag\": "unblackened",\n \"popularity\": 5149\n },\n {\n \"tag\": "schistosternia",\n \"popularity\": 5145\n },\n {\n \"tag\": "fuse",\n \"popularity\": 5141\n },\n {\n \"tag\": "narthecal",\n \"popularity\": 5137\n },\n {\n \"tag\": "Cueva",\n \"popularity\": 5133\n },\n {\n \"tag\": "appositeness",\n \"popularity\": 5128\n },\n {\n \"tag\": "proindustrial",\n \"popularity\": 5124\n },\n {\n \"tag\": "dermatorrhoea",\n \"popularity\": 5120\n },\n {\n \"tag\": "oxyurous tendential",\n \"popularity\": 5116\n },\n {\n \"tag\": "isopurpurin",\n \"popularity\": 5112\n },\n {\n \"tag\": "impose",\n \"popularity\": 5108\n },\n {\n \"tag\": "wordsmanship",\n \"popularity\": 5104\n },\n {\n \"tag\": "saturator",\n \"popularity\": 5100\n },\n {\n \"tag\": "Nordicity",\n \"popularity\": 5096\n },\n {\n \"tag\": "interaccuse",\n \"popularity\": 5092\n },\n {\n \"tag\": "acridinic",\n \"popularity\": 5087\n },\n {\n \"tag\": "scholion",\n \"popularity\": 5083\n },\n {\n \"tag\": "pseudoaconitine",\n \"popularity\": 5079\n },\n {\n \"tag\": "doctorial",\n \"popularity\": 5075\n },\n {\n \"tag\": "Etchimin",\n \"popularity\": 5071\n },\n {\n \"tag\": "oliviform",\n \"popularity\": 5067\n },\n {\n \"tag\": "Pele",\n \"popularity\": 5063\n },\n {\n \"tag\": "Chiromantis Progymnasium",\n \"popularity\": 5059\n },\n {\n \"tag\": "toxosis",\n \"popularity\": 5055\n },\n {\n \"tag\": "spadilla",\n \"popularity\": 5051\n },\n {\n \"tag\": "Actinopterygii",\n \"popularity\": 5047\n },\n {\n \"tag\": "untiring",\n \"popularity\": 5043\n },\n {\n \"tag\": "butyral",\n \"popularity\": 5039\n },\n {\n \"tag\": "Gymnoderinae",\n \"popularity\": 5035\n },\n {\n \"tag\": "testudo",\n \"popularity\": 5031\n },\n {\n \"tag\": "frigorify",\n \"popularity\": 5027\n },\n {\n \"tag\": "aliency",\n \"popularity\": 5023\n },\n {\n \"tag\": "jargon",\n \"popularity\": 5019\n },\n {\n \"tag\": "counterservice",\n \"popularity\": 5015\n },\n {\n \"tag\": "isostrychnine",\n \"popularity\": 5011\n },\n {\n \"tag\": "tellership",\n \"popularity\": 5007\n },\n {\n \"tag\": "miscegenetic",\n \"popularity\": 5003\n },\n {\n \"tag\": "sorcer",\n \"popularity\": 4999\n },\n {\n \"tag\": "tilewright",\n \"popularity\": 4995\n },\n {\n \"tag\": "cyanoplastid",\n \"popularity\": 4991\n },\n {\n \"tag\": "fluxionally",\n \"popularity\": 4987\n },\n {\n \"tag\": "proudhearted",\n \"popularity\": 4983\n },\n {\n \"tag\": "blithely",\n \"popularity\": 4979\n },\n {\n \"tag\": "jestproof",\n \"popularity\": 4975\n },\n {\n \"tag\": "jestwise",\n \"popularity\": 4971\n },\n {\n \"tag\": "nonassimilable",\n \"popularity\": 4967\n },\n {\n \"tag\": "compurgation",\n \"popularity\": 4964\n },\n {\n \"tag\": "unhate",\n \"popularity\": 4960\n },\n {\n \"tag\": "haplodonty",\n \"popularity\": 4956\n },\n {\n \"tag\": "cardholder",\n \"popularity\": 4952\n },\n {\n \"tag\": "rainlight megohmmeter overstout",\n \"popularity\": 4948\n },\n {\n \"tag\": "itchless",\n \"popularity\": 4944\n },\n {\n \"tag\": "begiggle",\n \"popularity\": 4940\n },\n {\n \"tag\": "chromatosphere",\n \"popularity\": 4936\n },\n {\n \"tag\": "typicality",\n \"popularity\": 4932\n },\n {\n \"tag\": "overgrown",\n \"popularity\": 4928\n },\n {\n \"tag\": "envolume",\n \"popularity\": 4925\n },\n {\n \"tag\": "pachycholia",\n \"popularity\": 4921\n },\n {\n \"tag\": "passageable",\n \"popularity\": 4917\n },\n {\n \"tag\": "pathopoiesis",\n \"popularity\": 4913\n },\n {\n \"tag\": "overbreak",\n \"popularity\": 4909\n },\n {\n \"tag\": "satyric",\n \"popularity\": 4905\n },\n {\n \"tag\": "unaudited",\n \"popularity\": 4901\n },\n {\n \"tag\": "whimble",\n \"popularity\": 4898\n },\n {\n \"tag\": "pressureless",\n \"popularity\": 4894\n },\n {\n \"tag\": "Selene",\n \"popularity\": 4890\n },\n {\n \"tag\": "slithery",\n \"popularity\": 4886\n },\n {\n \"tag\": "nondisfigurement",\n \"popularity\": 4882\n },\n {\n \"tag\": "overdelicious",\n \"popularity\": 4878\n },\n {\n \"tag\": "Perca",\n \"popularity\": 4875\n },\n {\n \"tag\": "Palladium",\n \"popularity\": 4871\n },\n {\n \"tag\": "insagacity",\n \"popularity\": 4867\n },\n {\n \"tag\": "peristoma",\n \"popularity\": 4863\n },\n {\n \"tag\": "uncreativeness",\n \"popularity\": 4859\n },\n {\n \"tag\": "incomparability surfboarding",\n \"popularity\": 4856\n },\n {\n \"tag\": "bacillar",\n \"popularity\": 4852\n },\n {\n \"tag\": "ulcerative",\n \"popularity\": 4848\n },\n {\n \"tag\": "stychomythia",\n \"popularity\": 4844\n },\n {\n \"tag\": "sesma somatics nonentry",\n \"popularity\": 4840\n },\n {\n \"tag\": "unsepulchred",\n \"popularity\": 4837\n },\n {\n \"tag\": "cephalanthium",\n \"popularity\": 4833\n },\n {\n \"tag\": "Asiaticization",\n \"popularity\": 4829\n },\n {\n \"tag\": "killeen",\n \"popularity\": 4825\n },\n {\n \"tag\": "Pseudococcus",\n \"popularity\": 4822\n },\n {\n \"tag\": "untractable",\n \"popularity\": 4818\n },\n {\n \"tag\": "apolegamic",\n \"popularity\": 4814\n },\n {\n \"tag\": "hyperpnea",\n \"popularity\": 4810\n },\n {\n \"tag\": "martyrolatry",\n \"popularity\": 4807\n },\n {\n \"tag\": "Sarmatic",\n \"popularity\": 4803\n },\n {\n \"tag\": "nonsurface",\n \"popularity\": 4799\n },\n {\n \"tag\": "adjoined",\n \"popularity\": 4796\n },\n {\n \"tag\": "vasiform",\n \"popularity\": 4792\n },\n {\n \"tag\": "tastelessness",\n \"popularity\": 4788\n },\n {\n \"tag\": "rumbo",\n \"popularity\": 4784\n },\n {\n \"tag\": "subdititious",\n \"popularity\": 4781\n },\n {\n \"tag\": "reparticipation",\n \"popularity\": 4777\n },\n {\n \"tag\": "Yorkshireism",\n \"popularity\": 4773\n },\n {\n \"tag\": "outcrow",\n \"popularity\": 4770\n },\n {\n \"tag\": "casserole",\n \"popularity\": 4766\n },\n {\n \"tag\": "semideltaic",\n \"popularity\": 4762\n },\n {\n \"tag\": "freemason",\n \"popularity\": 4759\n },\n {\n \"tag\": "catkin",\n \"popularity\": 4755\n },\n {\n \"tag\": "conscient",\n \"popularity\": 4751\n },\n {\n \"tag\": "reliably",\n \"popularity\": 4748\n },\n {\n \"tag\": "Telembi",\n \"popularity\": 4744\n },\n {\n \"tag\": "hide",\n \"popularity\": 4740\n },\n {\n \"tag\": "social",\n \"popularity\": 4737\n },\n {\n \"tag\": "ichneutic",\n \"popularity\": 4733\n },\n {\n \"tag\": "polypotome blouse pentagrammatic",\n \"popularity\": 4729\n },\n {\n \"tag\": "airdrome pesthole",\n \"popularity\": 4726\n },\n {\n \"tag\": "unportended",\n \"popularity\": 4722\n },\n {\n \"tag\": "sheerly",\n \"popularity\": 4719\n },\n {\n \"tag\": "acardiac",\n \"popularity\": 4715\n },\n {\n \"tag\": "fetor",\n \"popularity\": 4711\n },\n {\n \"tag\": "storax",\n \"popularity\": 4708\n },\n {\n \"tag\": "syndactylic",\n \"popularity\": 4704\n },\n {\n \"tag\": "otiatrics",\n \"popularity\": 4700\n },\n {\n \"tag\": "range",\n \"popularity\": 4697\n },\n {\n \"tag\": "branchway",\n \"popularity\": 4693\n },\n {\n \"tag\": "beatific",\n \"popularity\": 4690\n },\n {\n \"tag\": "Rugosa",\n \"popularity\": 4686\n },\n {\n \"tag\": "rafty",\n \"popularity\": 4682\n },\n {\n \"tag\": "gapy",\n \"popularity\": 4679\n },\n {\n \"tag\": "heterocercal",\n \"popularity\": 4675\n },\n {\n \"tag\": "actinopterygious",\n \"popularity\": 4672\n },\n {\n \"tag\": "glauconite",\n \"popularity\": 4668\n },\n {\n \"tag\": "limbless priest",\n \"popularity\": 4665\n },\n {\n \"tag\": "chrysene",\n \"popularity\": 4661\n },\n {\n \"tag\": "isentropic",\n \"popularity\": 4658\n },\n {\n \"tag\": "lairdess",\n \"popularity\": 4654\n },\n {\n \"tag\": "butterhead choliambic",\n \"popularity\": 4650\n },\n {\n \"tag\": "hexaseme",\n \"popularity\": 4647\n },\n {\n \"tag\": "treeify",\n \"popularity\": 4643\n },\n {\n \"tag\": "coronetted fructify",\n \"popularity\": 4640\n },\n {\n \"tag\": "admiralty",\n \"popularity\": 4636\n },\n {\n \"tag\": "Flosculariidae",\n \"popularity\": 4633\n },\n {\n \"tag\": "limaceous",\n \"popularity\": 4629\n },\n {\n \"tag\": "subterconscious",\n \"popularity\": 4626\n },\n {\n \"tag\": "stayless",\n \"popularity\": 4622\n },\n {\n \"tag\": "psha",\n \"popularity\": 4619\n },\n {\n \"tag\": "Mediterraneanize",\n \"popularity\": 4615\n },\n {\n \"tag\": "impenetrably",\n \"popularity\": 4612\n },\n {\n \"tag\": "Myrmeleonidae",\n \"popularity\": 4608\n },\n {\n \"tag\": "germander",\n \"popularity\": 4605\n },\n {\n \"tag\": "Buri",\n \"popularity\": 4601\n },\n {\n \"tag\": "papyrotamia",\n \"popularity\": 4598\n },\n {\n \"tag\": "Toxylon",\n \"popularity\": 4594\n },\n {\n \"tag\": "batatilla",\n \"popularity\": 4591\n },\n {\n \"tag\": "fabella assumer",\n \"popularity\": 4587\n },\n {\n \"tag\": "macromethod",\n \"popularity\": 4584\n },\n {\n \"tag\": "Blechnum",\n \"popularity\": 4580\n },\n {\n \"tag\": "pantography",\n \"popularity\": 4577\n },\n {\n \"tag\": "seminovel",\n \"popularity\": 4574\n },\n {\n \"tag\": "disembarrassment",\n \"popularity\": 4570\n },\n {\n \"tag\": "bushmaking",\n \"popularity\": 4567\n },\n {\n \"tag\": "neurosis",\n \"popularity\": 4563\n },\n {\n \"tag\": "Animalia",\n \"popularity\": 4560\n },\n {\n \"tag\": "Bernice",\n \"popularity\": 4556\n },\n {\n \"tag\": "wisen",\n \"popularity\": 4553\n },\n {\n \"tag\": "subhymenium",\n \"popularity\": 4549\n },\n {\n \"tag\": "esophagomycosis",\n \"popularity\": 4546\n },\n {\n \"tag\": "wireworks",\n \"popularity\": 4543\n },\n {\n \"tag\": "Sabellidae",\n \"popularity\": 4539\n },\n {\n \"tag\": "fustianish",\n \"popularity\": 4536\n },\n {\n \"tag\": "professively",\n \"popularity\": 4532\n },\n {\n \"tag\": "overcorruptly",\n \"popularity\": 4529\n },\n {\n \"tag\": "overcreep",\n \"popularity\": 4526\n },\n {\n \"tag\": "Castilloa",\n \"popularity\": 4522\n },\n {\n \"tag\": "forelady Georgie",\n \"popularity\": 4519\n },\n {\n \"tag\": "outsider",\n \"popularity\": 4515\n },\n {\n \"tag\": "Enukki",\n \"popularity\": 4512\n },\n {\n \"tag\": "gypsy",\n \"popularity\": 4509\n },\n {\n \"tag\": "Passamaquoddy",\n \"popularity\": 4505\n },\n {\n \"tag\": "reposit",\n \"popularity\": 4502\n },\n {\n \"tag\": "overtenderness",\n \"popularity\": 4499\n },\n {\n \"tag\": "keratome",\n \"popularity\": 4495\n },\n {\n \"tag\": "interclavicular hypermonosyllable Susanna",\n \"popularity\": 4492\n },\n {\n \"tag\": "mispropose",\n \"popularity\": 4489\n },\n {\n \"tag\": "Membranipora",\n \"popularity\": 4485\n },\n {\n \"tag\": "lampad",\n \"popularity\": 4482\n },\n {\n \"tag\": "header",\n \"popularity\": 4479\n },\n {\n \"tag\": "triseriate",\n \"popularity\": 4475\n },\n {\n \"tag\": "distrainment",\n \"popularity\": 4472\n },\n {\n \"tag\": "staphyloplastic",\n \"popularity\": 4469\n },\n {\n \"tag\": "outscour",\n \"popularity\": 4465\n },\n {\n \"tag\": "tallowmaking",\n \"popularity\": 4462\n },\n {\n \"tag\": "plugger",\n \"popularity\": 4459\n },\n {\n \"tag\": "fashionize",\n \"popularity\": 4455\n },\n {\n \"tag\": "puzzle",\n \"popularity\": 4452\n },\n {\n \"tag\": "imbrue",\n \"popularity\": 4449\n },\n {\n \"tag\": "osteoblast",\n \"popularity\": 4445\n },\n {\n \"tag\": "Hydrocores",\n \"popularity\": 4442\n },\n {\n \"tag\": "Lutra",\n \"popularity\": 4439\n },\n {\n \"tag\": "upridge scarfy",\n \"popularity\": 4435\n },\n {\n \"tag\": "ancon taffle",\n \"popularity\": 4432\n },\n {\n \"tag\": "impest",\n \"popularity\": 4429\n },\n {\n \"tag\": "uncollatedness",\n \"popularity\": 4426\n },\n {\n \"tag\": "hypersensitize",\n \"popularity\": 4422\n },\n {\n \"tag\": "autographically",\n \"popularity\": 4419\n },\n {\n \"tag\": "louther",\n \"popularity\": 4416\n },\n {\n \"tag\": "Ollie",\n \"popularity\": 4413\n },\n {\n \"tag\": "recompensate",\n \"popularity\": 4409\n },\n {\n \"tag\": "Shan",\n \"popularity\": 4406\n },\n {\n \"tag\": "brachycnemic",\n \"popularity\": 4403\n },\n {\n \"tag\": "Carinatae",\n \"popularity\": 4399\n },\n {\n \"tag\": "geotherm",\n \"popularity\": 4396\n },\n {\n \"tag\": "sawback",\n \"popularity\": 4393\n },\n {\n \"tag\": "Novatianist",\n \"popularity\": 4390\n },\n {\n \"tag\": "reapproach",\n \"popularity\": 4387\n },\n {\n \"tag\": "myelopoietic",\n \"popularity\": 4383\n },\n {\n \"tag\": "cyanin",\n \"popularity\": 4380\n },\n {\n \"tag\": "unsmutted",\n \"popularity\": 4377\n },\n {\n \"tag\": "nonpapist",\n \"popularity\": 4374\n },\n {\n \"tag\": "transbaikalian",\n \"popularity\": 4370\n },\n {\n \"tag\": "connately",\n \"popularity\": 4367\n },\n {\n \"tag\": "tenderize iterance",\n \"popularity\": 4364\n },\n {\n \"tag\": "hydrostatical",\n \"popularity\": 4361\n },\n {\n \"tag\": "unflag",\n \"popularity\": 4358\n },\n {\n \"tag\": "translate",\n \"popularity\": 4354\n },\n {\n \"tag\": "Scorzonera",\n \"popularity\": 4351\n },\n {\n \"tag\": "uncomforted",\n \"popularity\": 4348\n },\n {\n \"tag\": "risser varied",\n \"popularity\": 4345\n },\n {\n \"tag\": "plumbate",\n \"popularity\": 4342\n },\n {\n \"tag\": "Usneaceae",\n \"popularity\": 4338\n },\n {\n \"tag\": "fohat",\n \"popularity\": 4335\n },\n {\n \"tag\": "slagging",\n \"popularity\": 4332\n },\n {\n \"tag\": "superserious",\n \"popularity\": 4329\n },\n {\n \"tag\": "theocracy",\n \"popularity\": 4326\n },\n {\n \"tag\": "valonia",\n \"popularity\": 4323\n },\n {\n \"tag\": "Sapindales",\n \"popularity\": 4319\n },\n {\n \"tag\": "palaeozoologist",\n \"popularity\": 4316\n },\n {\n \"tag\": "yalb",\n \"popularity\": 4313\n },\n {\n \"tag\": "unviewed",\n \"popularity\": 4310\n },\n {\n \"tag\": "polyarteritis",\n \"popularity\": 4307\n },\n {\n \"tag\": "vectorial",\n \"popularity\": 4304\n },\n {\n \"tag\": "skimpingly",\n \"popularity\": 4301\n },\n {\n \"tag\": "athort",\n \"popularity\": 4297\n },\n {\n \"tag\": "tribofluorescence",\n \"popularity\": 4294\n },\n {\n \"tag\": "benzonitrol",\n \"popularity\": 4291\n },\n {\n \"tag\": "swiller subobtuse subjacency",\n \"popularity\": 4288\n },\n {\n \"tag\": "uncompassed",\n \"popularity\": 4285\n },\n {\n \"tag\": "cacochymia",\n \"popularity\": 4282\n },\n {\n \"tag\": "commensalist butadiene",\n \"popularity\": 4279\n },\n {\n \"tag\": "culpable",\n \"popularity\": 4276\n },\n {\n \"tag\": "contributive",\n \"popularity\": 4273\n },\n {\n \"tag\": "attemperately",\n \"popularity\": 4269\n },\n {\n \"tag\": "spelt",\n \"popularity\": 4266\n },\n {\n \"tag\": "exoneration",\n \"popularity\": 4263\n },\n {\n \"tag\": "antivivisectionist",\n \"popularity\": 4260\n },\n {\n \"tag\": "granitification",\n \"popularity\": 4257\n },\n {\n \"tag\": "palladize",\n \"popularity\": 4254\n },\n {\n \"tag\": "marksmanship",\n \"popularity\": 4251\n },\n {\n \"tag\": "bullydom",\n \"popularity\": 4248\n },\n {\n \"tag\": "spirality",\n \"popularity\": 4245\n },\n {\n \"tag\": "caliginous",\n \"popularity\": 4242\n },\n {\n \"tag\": "reportedly",\n \"popularity\": 4239\n },\n {\n \"tag\": "polyad",\n \"popularity\": 4236\n },\n {\n \"tag\": "arthroempyesis",\n \"popularity\": 4233\n },\n {\n \"tag\": "semibay facultatively",\n \"popularity\": 4229\n },\n {\n \"tag\": "metastatically",\n \"popularity\": 4226\n },\n {\n \"tag\": "prophetically",\n \"popularity\": 4223\n },\n {\n \"tag\": "Linguatula elapid",\n \"popularity\": 4220\n },\n {\n \"tag\": "pyknatom",\n \"popularity\": 4217\n },\n {\n \"tag\": "centimeter",\n \"popularity\": 4214\n },\n {\n \"tag\": "mensurate",\n \"popularity\": 4211\n },\n {\n \"tag\": "migraine",\n \"popularity\": 4208\n },\n {\n \"tag\": "pentagamist",\n \"popularity\": 4205\n },\n {\n \"tag\": "querken",\n \"popularity\": 4202\n },\n {\n \"tag\": "ambulance",\n \"popularity\": 4199\n },\n {\n \"tag\": "Stokavian",\n \"popularity\": 4196\n },\n {\n \"tag\": "malvasian",\n \"popularity\": 4193\n },\n {\n \"tag\": "uncouthsome",\n \"popularity\": 4190\n },\n {\n \"tag\": "readable",\n \"popularity\": 4187\n },\n {\n \"tag\": "enlodge",\n \"popularity\": 4184\n },\n {\n \"tag\": "plasterwise Appendiculariidae perspectograph",\n \"popularity\": 4181\n },\n {\n \"tag\": "inkweed",\n \"popularity\": 4178\n },\n {\n \"tag\": "streep",\n \"popularity\": 4175\n },\n {\n \"tag\": "diadelphian cultured",\n \"popularity\": 4172\n },\n {\n \"tag\": "hymenopterous",\n \"popularity\": 4169\n },\n {\n \"tag\": "unexorableness",\n \"popularity\": 4166\n },\n {\n \"tag\": "cascaron",\n \"popularity\": 4163\n },\n {\n \"tag\": "undaintiness",\n \"popularity\": 4160\n },\n {\n \"tag\": "Curtana",\n \"popularity\": 4157\n },\n {\n \"tag\": "scurvied",\n \"popularity\": 4154\n },\n {\n \"tag\": "molluscoidal",\n \"popularity\": 4151\n },\n {\n \"tag\": "yurt",\n \"popularity\": 4148\n },\n {\n \"tag\": "deciduitis",\n \"popularity\": 4145\n },\n {\n \"tag\": "creephole",\n \"popularity\": 4142\n },\n {\n \"tag\": "quatrefeuille",\n \"popularity\": 4139\n },\n {\n \"tag\": "bicapitate adenomatome",\n \"popularity\": 4136\n },\n {\n \"tag\": "damassin",\n \"popularity\": 4134\n },\n {\n \"tag\": "planching",\n \"popularity\": 4131\n },\n {\n \"tag\": "dashedly inferential",\n \"popularity\": 4128\n },\n {\n \"tag\": "lobe",\n \"popularity\": 4125\n },\n {\n \"tag\": "Hyrachyus",\n \"popularity\": 4122\n },\n {\n \"tag\": "knab",\n \"popularity\": 4119\n },\n {\n \"tag\": "discohexaster",\n \"popularity\": 4116\n },\n {\n \"tag\": "malign",\n \"popularity\": 4113\n },\n {\n \"tag\": "pedagoguism",\n \"popularity\": 4110\n },\n {\n \"tag\": "shrubbery",\n \"popularity\": 4107\n },\n {\n \"tag\": "undershrub",\n \"popularity\": 4104\n },\n {\n \"tag\": "bureaucrat",\n \"popularity\": 4101\n },\n {\n \"tag\": "pantaleon",\n \"popularity\": 4098\n },\n {\n \"tag\": "mesoventral",\n \"popularity\": 4096\n }]'; + +var log2 = Math.log(2); +var tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } }); + +function makeTagCloud(tagInfo) +{ + var output = '<div class="tagCloud" style="width: 100%">'; + + tagInfo.sort(function(a, b) { if (a.tag < b.tag) { return -1; } else if (a.tag == b.tag) { return 0; } else return 1; }); + + for (var i = 0; i < tagInfo.length; i++) { + var tag = tagInfo[i].tag; + + var validates = true; + for (var j = 0; j < tag.length; j++) { + var ch = tag.charCodeAt(j); + if (ch < 0x20 || ch >= 0x7f) { + validates = false; + break; + } + } + + if (!validates) + continue; + + var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase(); + var popularity = tagInfo[i].popularity; + var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)'; + output += ' <a href="' + url + '" style="font-size: ' + popularity + 'px; color: ' + color + '">' + tag + '</a> \n'; + } + + output += '</div>'; + output.replace(" ", " "); + + return output; +} + +var tagcloud = makeTagCloud(tagInfo); +tagInfo = null; + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/string-unpack-code.html b/build/pgo/js-input/sunspider/string-unpack-code.html new file mode 100644 index 0000000000..ba80c99ea1 --- /dev/null +++ b/build/pgo/js-input/sunspider/string-unpack-code.html @@ -0,0 +1,117 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider string-unpack-code</title> + +</head> + +<body> +<h3>string-unpack-code</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +// This test case unpacks the compressed code for the MochiKit, +// jQuery, Dojo and Prototype JavaScript libraries. + +/*** + MochiKit.MochiKit 1.3.1 : PACKED VERSION + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + See <http://mochikit.com/> for documentation, downloads, license, etc. + + (c) 2005 Bob Ippolito. All rights Reserved. +***/ + +for (var i = 0; i < 2; i++) { + +var decompressedMochiKit = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(H(1q)!="L"){1q.2X("B.J")}if(H(B)=="L"){B={}}if(H(B.J)=="L"){B.J={}}B.J.1Y="1.3.1";B.J.1r="B.J";B.J.2l=G(7V,vR){if(7V===O){7V={}}R(u i=1;i<M.K;i++){u o=M[i];if(H(o)!="L"&&o!==O){R(u k in o){7V[k]=o[k]}}}F 7V};B.J.2l(B.J,{1K:G(){F"["+D.1r+" "+D.1Y+"]"},1l:G(){F D.1K()},4f:G(n){if(M.K===0){n=1}F G(){F n++}},4L:G(mw){u me=M.2U;if(M.K==1){me.1U=mw;F Y me()}},bg:G(vQ){u X=[];u m=B.J;u aw=m.1R(O,M);1M(aw.K){u o=aw.2P();if(o&&H(o)=="3n"&&H(o.K)=="2y"){R(u i=o.K-1;i>=0;i--){aw.e9(o[i])}}N{X.1c(o)}}F X},1R:G(7U,1i,av){if(!av){av=0}if(1i){u l=1i.K;if(H(l)!="2y"){if(H(B.15)!="L"){1i=B.15.2G(1i);l=1i.K}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(!7U){7U=[]}R(u i=av;i<l;i++){7U.1c(1i[i])}}F 7U},8Z:G(5g,1i){if(5g===O){5g={}}R(u i=1;i<M.K;i++){u o=M[i];if(H(o)!="L"&&o!==O){R(u k in o){u v=o[k];if(H(5g[k])=="3n"&&H(v)=="3n"){M.2U(5g[k],v)}N{5g[k]=v}}}}F 5g},lO:G(6c,1i){if(6c===O){6c={}}R(u i=1;i<M.K;i++){u o=M[i];R(u k in o){if(!(k in 6c)){6c[k]=o[k]}}}F 6c},lN:G(1i){u fj=[];R(u mv in 1i){fj.1c(mv)}F fj},lM:G(1i){u fh=[];u e;R(u fi in 1i){u v;1f{v=1i[fi]}1e(e){2V}fh.1c([fi,v])}F fh},jq:G(fg,ff,fe){fe.1U=Y B.J.5a(fg.1r+"."+ff);fg[ff]=fe},4i:{7L:G(a){F!!a},vP:G(a){F!a},eE:G(a){F a},2E:G(a){F~a},vO:G(a){F-a},vN:G(a,b){F a+b},vM:G(a,b){F a-b},4u:G(a,b){F a/b},vL:G(a,b){F a%b},vK:G(a,b){F a*b},3W:G(a,b){F a&b},or:G(a,b){F a|b},vJ:G(a,b){F a^b},vI:G(a,b){F a<<b},vH:G(a,b){F a>>b},vG:G(a,b){F a>>>b},eq:G(a,b){F a==b},ne:G(a,b){F a!=b},gt:G(a,b){F a>b},ge:G(a,b){F a>=b},lt:G(a,b){F a<b},le:G(a,b){F a<=b},vF:G(a,b){F B.J.2f(a,b)===0},vE:G(a,b){F B.J.2f(a,b)!==0},vD:G(a,b){F B.J.2f(a,b)==1},vC:G(a,b){F B.J.2f(a,b)!=-1},vB:G(a,b){F B.J.2f(a,b)==-1},vA:G(a,b){F B.J.2f(a,b)!=1},vz:G(a,b){F a&&b},vy:G(a,b){F a||b},vx:G(a,b){F b in a}},24:G(mu){F G(){F D[mu].1w(D,M)}},lL:G(mt){F G(a9){F a9[mt]}},66:G(){u fd={};R(u i=0;i<M.K;i++){u 6b=M[i];fd[6b]=6b}F G(){R(u i=0;i<M.K;i++){if(!(H(M[i])in fd)){F 1m}}F 1h}},lJ:G(){R(u i=0;i<M.K;i++){if(M[i]!==O){F 1m}}F 1h},lK:G(){R(u i=0;i<M.K;i++){u o=M[i];if(!(H(o)=="L"||o===O)){F 1m}}F 1h},lI:G(1i){F!B.J.7e.1w(D,M)},7e:G(1i){R(u i=0;i<M.K;i++){u o=M[i];if(!(o&&o.K)){F 1m}}F 1h},3A:G(){R(u i=0;i<M.K;i++){u o=M[i];u 6b=H(o);if((6b!="3n"&&!(6b=="G"&&H(o.vw)=="G"))||o===O||H(o.K)!="2y"){F 1m}}F 1h},eN:G(){R(u i=0;i<M.K;i++){u o=M[i];if(H(o)!="3n"||o===O||H(o.9P)!="G"){F 1m}}F 1h},lH:G(fn){if(fn===O){F B.J.1R(O,M,1)}u fc=[];R(u i=1;i<M.K;i++){fc.1c(fn(M[i]))}F fc},2r:G(fn,1g){u m=B.J;u 6a=B.15;u fb=m.3A;if(M.K<=2){if(!fb(1g)){if(6a){1g=6a.2G(1g);if(fn===O){F 1g}}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(fn===O){F m.1R(O,1g)}u 69=[];R(u i=0;i<1g.K;i++){69.1c(fn(1g[i]))}F 69}N{if(fn===O){fn=7o}u 7T=O;R(i=1;i<M.K;i++){if(!fb(M[i])){if(6a){F 6a.2G(6a.4c.1w(O,M))}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}u l=M[i].K;if(7T===O||7T>l){7T=l}}69=[];R(i=0;i<7T;i++){u fa=[];R(u j=1;j<M.K;j++){fa.1c(M[j][i])}69.1c(fn.1w(D,fa))}F 69}},lG:G(fn){u f9=[];if(fn===O){fn=B.J.4i.7L}R(u i=1;i<M.K;i++){u o=M[i];if(fn(o)){f9.1c(o)}}F f9},47:G(fn,1g,7S){u aq=[];u m=B.J;if(!m.3A(1g)){if(B.15){1g=B.15.2G(1g)}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(fn===O){fn=m.4i.7L}if(H(7o.1U.47)=="G"){F 7o.1U.47.cz(1g,fn,7S)}N{if(H(7S)=="L"||7S===O){R(u i=0;i<1g.K;i++){u o=1g[i];if(fn(o)){aq.1c(o)}}}N{R(i=0;i<1g.K;i++){o=1g[i];if(fn.cz(7S,o)){aq.1c(o)}}}}F aq},mq:G(7R){F G(){hd(M.K){3j 0:F 7R();3j 1:F 7R(M[0]);3j 2:F 7R(M[0],M[1]);3j 3:F 7R(M[0],M[1],M[2])}u f8=[];R(u i=0;i<M.K;i++){f8.1c("M["+i+"]")}F dB("(1A("+f8.2b(",")+"))")}},lv:G(mr,ms){u m=B.J;F m.1O.1w(D,m.1R([ms,mr],M,2))},1O:G(3c,4o){if(H(3c)=="1n"){3c=4o[3c]}u ao=3c.f5;u 5f=3c.am;u f6=3c.f7;u m=B.J;if(H(3c)=="G"&&H(3c.1w)=="L"){3c=m.mq(3c)}if(H(ao)!="G"){ao=3c}if(H(4o)!="L"){f6=4o}if(H(5f)=="L"){5f=[]}N{5f=5f.9T()}m.1R(5f,M,2);u 7Q=G(){u ap=M;u me=M.2U;if(me.am.K>0){ap=m.2o(me.am,ap)}u 4o=me.f7;if(!4o){4o=D}F me.f5.1w(4o,ap)};7Q.f7=f6;7Q.f5=ao;7Q.am=5f;F 7Q},lF:G(7P){u mp=B.J.1O;R(u k in 7P){u f4=7P[k];if(H(f4)=="G"){7P[k]=mp(f4,7P)}}},5u:G(mo,mn,ml,mk){B.J.ae.5M(mo,mn,ml,mk)},mj:{"5L":1h,"1n":1h,"2y":1h},2f:G(a,b){if(a==b){F 0}u f3=(H(a)=="L"||a===O);u f2=(H(b)=="L"||b===O);if(f3&&f2){F 0}N{if(f3){F-1}N{if(f2){F 1}}}u m=B.J;u f1=m.mj;if(!(H(a)in f1&&H(b)in f1)){1f{F m.ae.3C(a,b)}1e(e){if(e!=m.4d){14 e}}}if(a<b){F-1}N{if(a>b){F 1}}u f0=m.U;14 Y 3p(f0(a)+" 3W "+f0(b)+" 9v 2E be vv")},eM:G(a,b){F B.J.2f(a.9P(),b.9P())},eL:G(a,b){u mi=B.J.2f;u 7O=a.K;u al=0;if(7O>b.K){al=1;7O=b.K}N{if(7O<b.K){al=-1}}R(u i=0;i<7O;i++){u 4j=mi(a[i],b[i]);if(4j){F 4j}}F al},7M:G(mh,mg,mf,md){B.J.ad.5M(mh,mg,mf,md)},U:G(o){if(H(o)=="L"){F"L"}N{if(o===O){F"O"}}1f{if(H(o.1K)=="G"){F o.1K()}N{if(H(o.U)=="G"&&o.U!=M.2U){F o.U()}}F B.J.ad.3C(o)}1e(e){if(H(o.1r)=="1n"&&(o.1l==cZ.1U.1l||o.1l==vu.1U.1l)){F o.1r}}1f{u eZ=(o+"")}1e(e){F"["+H(o)+"]"}if(H(o)=="G"){o=eZ.23(/^\\s+/,"");u 5n=o.2A("{");if(5n!=-1){o=o.3H(0,5n)+"{...}"}}F eZ},eK:G(o){u m=B.J;F"["+m.2r(m.U,o).2b(", ")+"]"},ac:G(o){F("\\""+o.23(/(["\\\\])/g,"\\\\$1")+"\\"").23(/[\\f]/g,"\\\\f").23(/[\\b]/g,"\\\\b").23(/[\\n]/g,"\\\\n").23(/[\\t]/g,"\\\\t").23(/[\\r]/g,"\\\\r")},eJ:G(o){F o+""},ly:G(mc,mb,ma,m9){B.J.ab.5M(mc,mb,ma,m9)},lx:G(){F dB("("+M[0]+")")},lz:G(o){u 5e=H(o);if(5e=="L"){F"L"}N{if(5e=="2y"||5e=="5L"){F o+""}N{if(o===O){F"O"}}}u m=B.J;u eY=m.ac;if(5e=="1n"){F eY(o)}u me=M.2U;u 3S;if(H(o.m8)=="G"){3S=o.m8();if(o!==3S){F me(3S)}}if(H(o.m7)=="G"){3S=o.m7();if(o!==3S){F me(3S)}}if(5e!="G"&&H(o.K)=="2y"){u X=[];R(u i=0;i<o.K;i++){u 2i=me(o[i]);if(H(2i)!="1n"){2i="L"}X.1c(2i)}F"["+X.2b(", ")+"]"}1f{3S=m.ab.3C(o);F me(3S)}1e(e){if(e!=m.4d){14 e}}if(5e=="G"){F O}X=[];R(u k in o){u ak;if(H(k)=="2y"){ak="\\""+k+"\\""}N{if(H(k)=="1n"){ak=eY(k)}N{2V}}2i=me(o[k]);if(H(2i)!="1n"){2V}X.1c(ak+":"+2i)}F"{"+X.2b(", ")+"}"},lE:G(a,b){F(B.J.2f(a,b)===0)},lD:G(eX,4n){if(eX.K!=4n.K){F 1m}F(B.J.2f(eX,4n)===0)},2o:G(){u eW=[];u m6=B.J.1R;R(u i=0;i<M.K;i++){m6(eW,M[i])}F eW},eR:G(2h){u m=B.J;u eU=m.2f;if(M.K==1){F G(a,b){F eU(a[2h],b[2h])}}u eV=m.1R(O,M);F G(a,b){u aj=0;R(u i=0;(aj===0)&&(i<eV.K);i++){u 2h=eV[i];aj=eU(a[2h],b[2h])}F aj}},lC:G(2h){u m5=B.J.eR.1w(D,M);F G(a,b){F m5(b,a)}},2z:G(m4){u m=B.J;F m.1O.1w(D,m.1R([m4,L],M,1))},67:G(m0,1g){if(1g.K===0){F O}u ai=1g[0];u m3=B.J.2f;R(u i=1;i<1g.K;i++){u o=1g[i];if(m3(o,ai)==m0){ai=o}}F ai},lB:G(){F B.J.67(1,M)},lA:G(){F B.J.67(-1,M)},bi:G(1g,lY,lZ,3B){if(H(3B)=="L"||3B===O){3B=1g.K}R(u i=(lZ||0);i<3B;i++){if(1g[i]===lY){F i}}F-1},eO:G(1g,lW,lX,3B){if(H(3B)=="L"||3B===O){3B=1g.K}u 4j=B.J.2f;R(u i=(lX||0);i<3B;i++){if(4j(1g[i],lW)===0){F i}}F-1},d4:G(1j,lV){u ah=[1j];u lU=B.J.1R;1M(ah.K){u X=lV(ah.2P());if(X){lU(ah,X)}}},3f:G(ag){u 2w=ag.1r;if(H(2w)=="L"){2w=""}N{2w=2w+"."}R(u 1b in ag){u o=ag[1b];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+1b}1e(e){}}}},dw:G(3s,68){if(H(B.S)!="L"&&M.K==1&&(H(3s)=="1n"||(H(3s.3T)!="L"&&3s.3T>0))){u kv=B.S.d5(3s);3s=kv[0];68=kv[1]}N{if(M.K==1){u o=3s;3s=[];68=[];R(u k in o){u v=o[k];if(H(v)!="G"){3s.1c(k);68.1c(v)}}}}u W=[];u lT=28.2a(3s.K,68.K);u eT=B.J.af;R(u i=0;i<lT;i++){v=68[i];if(H(v)!="L"&&v!==O){W.1c(eT(3s[i])+"="+eT(v))}}F W.2b("&")},lw:G(lS,lQ){u 7N=lS.23(/\\+/g,"%20").2R("&");u o={};u 5d;if(H(lR)!="L"){5d=lR}N{5d=vt}if(lQ){R(u i=0;i<7N.K;i++){u 2n=7N[i].2R("=");u 1b=5d(2n[0]);u 4n=o[1b];if(!(4n 2C 7o)){4n=[];o[1b]=4n}4n.1c(5d(2n[1]))}}N{R(i=0;i<7N.K;i++){2n=7N[i].2R("=");o[5d(2n[0])]=5d(2n[1])}}F o}});B.J.4a=G(){D.4m=[]};B.J.4a.1U={5M:G(1b,eS,3y,lP){if(lP){D.4m.e9([1b,eS,3y])}N{D.4m.1c([1b,eS,3y])}},3C:G(){R(u i=0;i<D.4m.K;i++){u 2n=D.4m[i];if(2n[1].1w(D,M)){F 2n[2].1w(D,M)}}14 B.J.4d},vs:G(1b){R(u i=0;i<D.4m.K;i++){u 2n=D.4m[i];if(2n[0]==1b){D.4m.4y(i,1);F 1h}}F 1m}};B.J.1z=["4f","4L","1R","2l","8Z","lO","lN","lM","5a","4i","24","lL","66","lo","ln","lK","lJ","lI","7e","3A","eN","lH","2r","lG","47","1O","lF","4d","4a","5u","2f","7M","U","lE","lD","2o","eR","lC","2z","lm","67","lp","eI","lB","lA","d4","ll","af","dw","lz","ly","lx","lw","eO","bi","bg","lv"];B.J.1W=["3f","ae","ad","ab","eM","eL","eK","ac","eJ"];B.J.2Y=G(lu,eP){if(H(B.eQ)=="L"){B.eQ=(B.3d||(H(1x)=="L"&&H(1q)=="L"))}if(!B.eQ){F}u 1p=eP.2k[":1p"];R(u i=0;i<1p.K;i++){lu[1p[i]]=eP[1p[i]]}};B.J.2d=G(){u m=D;m.vr=m.24;m.vq=m.eO;if(H(ls)!="L"){m.af=G(lr){F ls(lr).23(/\\\'/g,"%27")}}N{m.af=G(lq){F vp(lq).23(/\\+/g,"%2B").23(/\\"/g,"%22").W.23(/\\\'/g,"%27")}}m.5a=G(1b){D.43=1b;D.1b=1b};m.5a.1U=Y 2x();m.2l(m.5a.1U,{U:G(){if(D.43&&D.43!=D.1b){F D.1b+"("+m.U(D.43)+")"}N{F D.1b+"()"}},1l:m.24("U")});m.4d=Y m.5a("B.J.4d");m.lp=m.2z(m.67,1);m.eI=m.2z(m.67,-1);m.lo=m.66("G");m.ln=m.66("L");m.lm=m.2z(m.2l,O);m.ll=m.2z(m.2r,O);m.ae=Y m.4a();m.5u("vo",m.eN,m.eM);m.5u("ej",m.3A,m.eL);m.ad=Y m.4a();m.7M("ej",m.3A,m.eK);m.7M("1n",m.66("1n"),m.ac);m.7M("vn",m.66("2y","5L"),m.eJ);m.ab=Y m.4a();u 1p=m.2o(m.1z,m.1W);m.2k={":3e":m.2o(m.1W),":1p":1p};m.3f(D)};B.J.2d();if(!B.3d){2f=B.J.2f}B.J.2Y(D,B.J);if(H(1q)!="L"){1q.2X("B.15");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.15 3F on B.J!"}if(H(B.15)=="L"){B.15={}}B.15.1r="B.15";B.15.1Y="1.3.1";B.J.2l(B.15,{1K:G(){F"["+D.1r+" "+D.1Y+"]"},1l:G(){F D.1K()},9W:G(1b,lk,lj,lh){B.15.9Y.5M(1b,lk,lj,lh)},1Q:G(3R,lg){u I=B.15;if(M.K==2){F I.9Z(G(a){F a!=lg},3R)}if(H(3R.1a)=="G"){F 3R}N{if(H(3R.1Q)=="G"){F 3R.1Q()}}1f{F I.9Y.3C(3R)}1e(e){u m=B.J;if(e==m.4d){e=Y 3p(H(3R)+": "+m.U(3R)+" is 2E vm")}14 e}},eu:G(n){if(!n){n=0}u m=B.J;F{U:G(){F"eu("+n+")"},1l:m.24("U"),1a:m.4f(n)}},et:G(p){u I=B.15;u m=B.J;u 1g=[];u lf=I.1Q(p);F{U:G(){F"et(...)"},1l:m.24("U"),1a:G(){1f{u W=lf.1a();1g.1c(W);F W}1e(e){if(e!=I.25){14 e}if(1g.K===0){D.1a=G(){14 I.25}}N{u i=-1;D.1a=G(){i=(i+1)%1g.K;F 1g[i]}}F D.1a()}}}},7b:G(Q,n){u m=B.J;if(H(n)=="L"){F{U:G(){F"7b("+m.U(Q)+")"},1l:m.24("U"),1a:G(){F Q}}}F{U:G(){F"7b("+m.U(Q)+", "+n+")"},1l:m.24("U"),1a:G(){if(n<=0){14 B.15.25}n-=1;F Q}}},1a:G(ld){F ld.1a()},es:G(p,q){u m=B.J;u 1a=B.15.1a;u lc=m.2r(1Q,M);F{U:G(){F"es(...)"},1l:m.24("U"),1a:G(){F m.2r(1a,lc)}}},a1:G(3b,1V){u m=B.J;1V=B.15.1Q(1V);if(3b===O){3b=m.4i.7L}F{U:G(){F"a1(...)"},1l:m.24("U"),1a:G(){1M(1h){u W=1V.1a();if(3b(W)){F W}}F L}}},a0:G(3b,1V){u m=B.J;1V=B.15.1Q(1V);if(3b===O){3b=m.4i.7L}F{U:G(){F"a0(...)"},1l:m.24("U"),1a:G(){1M(1h){u W=1V.1a();if(!3b(W)){F W}}F L}}},er:G(1V){u I=B.15;u m=B.J;1V=I.1Q(1V);u 5c=0;u 2J=0;u 3a=1;u i=-1;if(M.K==2){2J=M[1]}N{if(M.K==3){5c=M[1];2J=M[2]}N{5c=M[1];2J=M[2];3a=M[3]}}F{U:G(){F"er("+["...",5c,2J,3a].2b(", ")+")"},1l:m.24("U"),1a:G(){u W;1M(i<5c){W=1V.1a();i++}if(5c>=2J){14 I.25}5c+=3a;F W}}},4c:G(aa,p,q){u m=B.J;u I=B.15;u lb=m.2r(I.1Q,m.1R(O,M,1));u 2r=m.2r;u 1a=I.1a;F{U:G(){F"4c(...)"},1l:m.24("U"),1a:G(){F aa.1w(D,2r(1a,lb))}}},ep:G(aa,1V,I){1V=B.15.1Q(1V);u m=B.J;F{U:G(){F"ep(...)"},1l:m.24("U"),1a:G(){F aa.1w(I,1V.1a())}}},55:G(p,q){u I=B.15;u m=B.J;if(M.K==1){F I.1Q(M[0])}u 64=m.2r(I.1Q,M);F{U:G(){F"55(...)"},1l:m.24("U"),1a:G(){1M(64.K>1){1f{F 64[0].1a()}1e(e){if(e!=I.25){14 e}64.2P()}}if(64.K==1){u a9=64.2P();D.1a=m.1O("1a",a9);F D.1a()}14 I.25}}},9Z:G(3b,1V){u I=B.15;1V=I.1Q(1V);F{U:G(){F"9Z(...)"},1l:B.J.24("U"),1a:G(){u W=1V.1a();if(!3b(W)){D.1a=G(){14 I.25};D.1a()}F W}}},eo:G(3b,1V){1V=B.15.1Q(1V);u m=B.J;u 1O=m.1O;F{"U":G(){F"eo(...)"},"1l":m.24("U"),"1a":G(){1M(1h){u W=1V.1a();if(!3b(W)){2K}}D.1a=1O("1a",1V);F W}}},a7:G(63,2u,la){2u.62[63]=-1;u m=B.J;u l9=m.eI;F{U:G(){F"en("+63+", ...)"},1l:m.24("U"),1a:G(){u W;u i=2u.62[63];if(i==2u.29){W=la.1a();2u.a8.1c(W);2u.29+=1;2u.62[63]+=1}N{W=2u.a8[i-2u.2a];2u.62[63]+=1;if(i==2u.2a&&l9(2u.62)!=2u.2a){2u.2a+=1;2u.a8.2P()}}F W}}},en:G(a6,n){u W=[];u 2u={"62":[],"a8":[],"29":-1,"2a":-1};if(M.K==1){n=2}u I=B.15;a6=I.1Q(a6);u a7=I.a7;R(u i=0;i<n;i++){W.1c(a7(i,2u,a6))}F W},2G:G(4l){u m=B.J;if(H(4l.9T)=="G"){F 4l.9T()}N{if(m.3A(4l)){F m.2o(4l)}}u I=B.15;4l=I.1Q(4l);u W=[];1f{1M(1h){W.1c(4l.1a())}}1e(e){if(e!=I.25){14 e}F W}F L},7H:G(fn,7K,l8){u i=0;u x=l8;u I=B.15;7K=I.1Q(7K);if(M.K<3){1f{x=7K.1a()}1e(e){if(e==I.25){e=Y 3p("7H() of vl vk vj no vi 3m")}14 e}i++}1f{1M(1h){x=fn(x,7K.1a())}}1e(e){if(e!=I.25){14 e}}F x},7I:G(){u 4k=0;u 2J=0;u 3a=1;if(M.K==1){2J=M[0]}N{if(M.K==2){4k=M[0];2J=M[1]}N{if(M.K==3){4k=M[0];2J=M[1];3a=M[2]}N{14 Y 3p("7I() vh 1, 2, or 3 M!")}}}if(3a===0){14 Y 3p("7I() 3a 5p 2E be 0")}F{1a:G(){if((3a>0&&4k>=2J)||(3a<0&&4k<=2J)){14 B.15.25}u W=4k;4k+=3a;F W},U:G(){F"7I("+[4k,2J,3a].2b(", ")+")"},1l:B.J.24("U")}},l0:G(a5,l7){u x=l7||0;u I=B.15;a5=I.1Q(a5);1f{1M(1h){x+=a5.1a()}}1e(e){if(e!=I.25){14 e}}F x},em:G(a4){u I=B.15;a4=I.1Q(a4);1f{1M(1h){a4.1a()}}1e(e){if(e!=I.25){14 e}}},9a:G(7J,1A,I){u m=B.J;if(M.K>2){1A=m.1O(1A,I)}if(m.3A(7J)){1f{R(u i=0;i<7J.K;i++){1A(7J[i])}}1e(e){if(e!=B.15.25){14 e}}}N{I=B.15;I.em(I.4c(1A,7J))}},kZ:G(l6,1A){u I=B.15;1f{I.a0(1A,l6).1a();F 1m}1e(e){if(e!=I.25){14 e}F 1h}},kY:G(l5,4j){u W=B.15.2G(l5);if(M.K==1){4j=B.J.2f}W.iz(4j);F W},kX:G(l4){u W=B.15.2G(l4);W.vg();F W},kW:G(l3,1A){u I=B.15;1f{I.a1(1A,l3).1a();F 1h}1e(e){if(e!=I.25){14 e}F 1m}},kV:G(1g,5b){if(B.J.3A(5b)){R(u i=0;i<5b.K;i++){1g.1c(5b[i])}}N{u I=B.15;5b=I.1Q(5b);1f{1M(1h){1g.1c(5b.1a())}}1e(e){if(e!=I.25){14 e}}}F 1g},ek:G(a3,eH){u m=B.J;u I=B.15;if(M.K<2){eH=m.4i.eE}a3=I.1Q(a3);u pk=L;u k=L;u v;G eF(){v=a3.1a();k=eH(v)}G l2(){u 7j=v;v=L;F 7j}u eG=1h;F{U:G(){F"ek(...)"},1a:G(){1M(k==pk){eF();if(eG){eG=1m;2K}}pk=k;F[k,{1a:G(){if(v==L){eF()}if(k!=pk){14 I.25}F l2()}}]}}},kU:G(a2,eD){u m=B.J;u I=B.15;if(M.K<2){eD=m.4i.eE}a2=I.1Q(a2);u ey=[];u eA=1h;u ez;1M(1h){1f{u eB=a2.1a();u 2h=eD(eB)}1e(e){if(e==I.25){2K}14 e}if(eA||2h!=ez){u eC=[];ey.1c([2h,eC])}eC.1c(eB);eA=1m;ez=2h}F ey},9X:G(ex){u i=0;F{U:G(){F"9X(...)"},1l:B.J.24("U"),1a:G(){if(i>=ex.K){14 B.15.25}F ex[i++]}}},eh:G(ew){F(ew&&H(ew.ei)=="G")},9V:G(l1){F{U:G(){F"9V(...)"},1l:B.J.24("U"),1a:G(){u W=l1.ei();if(W===O||W===L){14 B.15.25}F W}}}});B.15.1W=["9Y","9X","eh","9V",];B.15.1z=["25","9W","1Q","eu","et","7b","1a","es","a1","a0","er","4c","ep","55","9Z","eo","en","2G","7H","7I","l0","em","9a","kZ","kY","kX","kW","kV","ek","kU"];B.15.2d=G(){u m=B.J;D.25=Y m.5a("25");D.9Y=Y m.4a();D.9W("ej",m.3A,D.9X);D.9W("ei",D.eh,D.9V);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.15.2d();if(!B.3d){7H=B.15.7H}B.J.2Y(D,B.15);if(H(1q)!="L"){1q.2X("B.1H");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1H 3F on B.J!"}if(H(B.1H)=="L"){B.1H={}}B.1H.1r="B.1H";B.1H.1Y="1.3.1";B.1H.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1H.1l=G(){F D.1K()};B.1H.1z=["5C","49","7A","kR","2L","5Z","kG","ch","kE","kC"];B.1H.1W=["ef","e8","e7"];B.1H.49=G(1P,kT,3z){D.1P=1P;D.3N=kT;D.3z=3z;D.vf=Y 3Q()};B.1H.49.1U={U:G(){u m=B.J;F"49("+m.2r(m.U,[D.1P,D.3N,D.3z]).2b(", ")+")"},1l:B.J.24("U")};B.J.2l(B.1H,{ef:G(7F){u I=B.1H;if(H(7F)=="1n"){7F=I.5C[7F]}F G(1t){u 7G=1t.3N;if(H(7G)=="1n"){7G=I.5C[7G]}F 7G>=7F}},e8:G(){u kS=B.1H.49;R(u i=0;i<M.K;i++){if(!(M[i]2C kS)){F 1m}}F 1h},e7:G(a,b){F B.J.2f([a.3N,a.3z],[b.3N,b.3z])},kR:G(1t){cq("1P: "+1t.1P+"\\ve: "+1t.3N+"\\vd: "+1t.3z.2b(" "))}});B.1H.7A=G(7E){D.4f=0;if(H(7E)=="L"||7E===O){7E=-1}D.ec=7E;D.4h=[];D.7C={};D.e5=1m};B.1H.7A.1U={vc:G(){D.4h.4y(0,D.4h.K)},kK:G(1t){if(H(2O)!="L"&&2O.eg&&2O.eg.5Z){2O.eg.5Z(1t)}N{if(H(7h)!="L"&&7h.kQ){7h.kQ(1t)}N{if(H(5X)=="G"){5X(1t)}}}},kL:G(1t){R(u k in D.7C){u 2n=D.7C[k];if(2n.kO!=k||(2n[0]&&!2n[0](1t))){2V}2n[1](1t)}},hE:G(ee,7D,kP){if(H(7D)=="1n"){7D=B.1H.ef(7D)}u ed=[7D,kP];ed.kO=ee;D.7C[ee]=ed},c9:G(kN){gi D.7C[kN]},kH:G(kM,vb){u 1t=Y B.1H.49(D.4f,kM,B.J.1R(O,M,1));D.4h.1c(1t);D.kL(1t);if(D.e5){D.kK(1t.3N+": "+1t.3z.2b(" "))}D.4f+=1;1M(D.ec>=0&&D.4h.K>D.ec){D.4h.2P()}},c8:G(9U){u ea=0;if(!(H(9U)=="L"||9U===O)){ea=28.29(0,D.4h.K-9U)}F D.4h.9T(ea)},kJ:G(7B){if(H(7B)=="L"||7B===O){7B=30}u 9S=D.c8(7B);if(9S.K){u 1g=2r(G(m){F"\\n ["+m.1P+"] "+m.3N+": "+m.3z.2b(" ")},9S);1g.e9("va "+9S.K+" v9:");F 1g.2b("")}F""},v8:G(kI){if(H(B.1I)=="L"){cq(D.kJ())}N{B.1I.bY(kI||1m)}}};B.1H.2d=G(){D.5C={8M:40,8L:50,8K:30,8J:20,8I:10};u m=B.J;m.5u("49",D.e8,D.e7);u 61=m.2z;u e6=D.7A;u 60=e6.1U.kH;m.2l(D.7A.1U,{kF:61(60,"8I"),5Z:61(60,"8J"),dE:61(60,"8M"),kD:61(60,"8L"),kB:61(60,"8K")});u I=D;u 5Y=G(1b){F G(){I.2L[1b].1w(I.2L,M)}};D.5Z=5Y("5Z");D.kG=5Y("dE");D.ch=5Y("kF");D.kE=5Y("kD");D.kC=5Y("kB");D.2L=Y e6();D.2L.e5=1h;D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};if(H(5X)=="L"&&H(2v)!="L"&&2v.kA&&H(kz)!="L"){5X=G(){5X.3G=M;u ev=2v.kA("v7");ev.v6("5X",1m,1h);kz(ev)}}B.1H.2d();B.J.2Y(D,B.1H);if(H(1q)!="L"){1q.2X("B.1D")}if(H(B)=="L"){B={}}if(H(B.1D)=="L"){B.1D={}}B.1D.1r="B.1D";B.1D.1Y="1.3.1";B.1D.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1D.1l=G(){F D.1K()};B.1D.ks=G(1y){1y=1y+"";if(H(1y)!="1n"||1y.K===0){F O}u 7z=1y.2R("-");if(7z.K===0){F O}F Y 3Q(7z[0],7z[1]-1,7z[2])};B.1D.ky=/(\\d{4,})(?:-(\\d{1,2})(?:-(\\d{1,2})(?:[T ](\\d{1,2}):(\\d{1,2})(?::(\\d{1,2})(?:\\.(\\d+))?)?(?:(Z)|([+-])(\\d{1,2})(?::(\\d{1,2}))?)?)?)?)?/;B.1D.kr=G(1y){1y=1y+"";if(H(1y)!="1n"||1y.K===0){F O}u X=1y.3C(B.1D.ky);if(H(X)=="L"||X===O){F O}u 5W,7y,7x,9R,2a,9Q,7w;5W=3w(X[1],10);if(H(X[2])=="L"||X[2]===""){F Y 3Q(5W)}7y=3w(X[2],10)-1;7x=3w(X[3],10);if(H(X[4])=="L"||X[4]===""){F Y 3Q(5W,7y,7x)}9R=3w(X[4],10);2a=3w(X[5],10);9Q=(H(X[6])!="L"&&X[6]!=="")?3w(X[6],10):0;if(H(X[7])!="L"&&X[7]!==""){7w=28.ha(c5*4M("0."+X[7]))}N{7w=0}if((H(X[8])=="L"||X[8]==="")&&(H(X[9])=="L"||X[9]==="")){F Y 3Q(5W,7y,7x,9R,2a,9Q,7w)}u 58;if(H(X[9])!="L"&&X[9]!==""){58=3w(X[10],10)*v5;if(H(X[11])!="L"&&X[11]!==""){58+=3w(X[11],10)*kw}if(X[9]=="-"){58=-58}}N{58=0}F Y 3Q(3Q.v4(5W,7y,7x,9R,2a,9Q,7w)-58)};B.1D.dY=G(2g,kx){if(H(2g)=="L"||2g===O){F O}u hh=2g.v3();u mm=2g.v2();u ss=2g.v1();u 1g=[((kx&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];F 1g.2b(":")};B.1D.kq=G(2g,7v){if(H(2g)=="L"||2g===O){F O}u ku=7v?"T":" ";u kt=7v?"Z":"";if(7v){2g=Y 3Q(2g.9P()+(2g.v0()*kw))}F B.1D.dX(2g)+ku+B.1D.dY(2g,7v)+kt};B.1D.dX=G(2g){if(H(2g)=="L"||2g===O){F O}u e4=B.1D.e3;F[2g.dZ(),e4(2g.e1()+1),e4(2g.e0())].2b("-")};B.1D.kp=G(d){d=d+"";if(H(d)!="1n"||d.K===0){F O}u a=d.2R("/");F Y 3Q(a[2],a[0]-1,a[1])};B.1D.e3=G(n){F(n>9)?n:"0"+n};B.1D.ko=G(d){if(H(d)=="L"||d===O){F O}u e2=B.1D.e3;F[e2(d.e1()+1),e2(d.e0()),d.dZ()].2b("/")};B.1D.kn=G(d){if(H(d)=="L"||d===O){F O}F[d.e1()+1,d.e0(),d.dZ()].2b("/")};B.1D.1z=["ks","kr","dY","kq","dX","kp","ko","kn"];B.1D.1W=[];B.1D.2k={":3e":B.1D.1z,":1p":B.1D.1z};B.1D.2d=G(){u 2w=D.1r+".";R(u k in D){u o=D[k];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+k}1e(e){}}}};B.1D.2d();if(H(B.J)!="L"){B.J.2Y(D,B.1D)}N{(G(km,dW){if((H(1x)=="L"&&H(1q)=="L")||(H(B.3d)=="5L"&&B.3d)){u 1p=dW.2k[":1p"];R(u i=0;i<1p.K;i++){km[1p[i]]=dW[1p[i]]}}})(D,B.1D)}if(H(1q)!="L"){1q.2X("B.1s")}if(H(B)=="L"){B={}}if(H(B.1s)=="L"){B.1s={}}B.1s.1r="B.1s";B.1s.1Y="1.3.1";B.1s.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1s.1l=G(){F D.1K()};B.1s.ke=G(kl,kk,kj,ki,kh,dV,kg,9N,kf){F G(1P){1P=4M(1P);if(H(1P)=="L"||1P===O||k8(1P)){F kl}u 9L=kk;u 9K=kj;if(1P<0){1P=-1P}N{9L=9L.23(/-/,"")}u me=M.2U;u 9M=B.1s.dJ(ki);if(kh){1P=1P*3k;9K=9M.9y+9K}1P=B.1s.dK(1P,dV);u 9O=1P.2R(/\\./);u 3r=9O[0];u 3P=(9O.K==1)?"":9O[1];u X="";1M(3r.K<kg){3r="0"+3r}if(9N){1M(3r.K>9N){u i=3r.K-9N;X=9M.9A+3r.2W(i,3r.K)+X;3r=3r.2W(0,i)}}X=3r+X;if(dV>0){1M(3P.K<kf){3P=3P+"0"}X=X+9M.9z+3P}F 9L+X+9K}};B.1s.k5=G(9J,9H,9G){if(H(9H)=="L"){9H=""}u 3q=9J.3C(/((?:[0#]+,)?[0#]+)(?:\\.([0#]+))?(%)?/);if(!3q){14 3p("uZ uY")}u 7u=9J.3H(0,3q.c6);u kd=9J.3H(3q.c6+3q[0].K);if(7u.uX(/-/)==-1){7u=7u+"-"}u 9I=3q[1];u 3P=(H(3q[2])=="1n"&&3q[2]!="")?3q[2]:"";u kc=(H(3q[3])=="1n"&&3q[3]!="");u dU=9I.2R(/,/);u 9F;if(H(9G)=="L"){9G="dG"}if(dU.K==1){9F=O}N{9F=dU[1].K}u ka=9I.K-9I.23(/0/g,"").K;u k9=3P.K-3P.23(/0/g,"").K;u kb=3P.K;u W=B.1s.ke(9H,7u,kd,9G,kc,kb,ka,9F,k9);u m=B.J;if(m){u fn=M.2U;u 3G=m.2o(M);W.U=G(){F[I.1r,"(",2r(m.U,3G).2b(", "),")"].2b("")}}F W};B.1s.dJ=G(4g){if(H(4g)=="L"||4g===O){4g="dG"}if(H(4g)=="1n"){u W=B.1s.5V[4g];if(H(W)=="1n"){W=M.2U(W);B.1s.5V[4g]=W}F W}N{F 4g}};B.1s.k4=G(dT,9E){if(9E){u X=dT/9E;if(!k8(X)){F B.1s.9B(dT/9E)}}F"0"};B.1s.9B=G(dS){u dR=(dS<0?"-":"");u s=28.8B(28.uW(dS)*3k).1l();if(s=="0"){F s}if(s.K<3){1M(s.3Z(s.K-1)=="0"){s=s.2W(0,s.K-1)}F dR+"0."+s}u 5E=dR+s.2W(0,s.K-2);u 7t=s.2W(s.K-2,s.K);if(7t=="uV"){F 5E}N{if(7t.3Z(1)=="0"){F 5E+"."+7t.3Z(0)}N{F 5E+"."+7t}}};B.1s.dI=G(1y,dQ){1y=1y+"";if(H(1y)!="1n"){F O}if(!dQ){F 1y.23(/^\\s+/,"")}N{F 1y.23(Y 8V("^["+dQ+"]+"),"")}};B.1s.dH=G(1y,dP){1y=1y+"";if(H(1y)!="1n"){F O}if(!dP){F 1y.23(/\\s+$/,"")}N{F 1y.23(Y 8V("["+dP+"]+$"),"")}};B.1s.k2=G(1y,dO){u I=B.1s;F I.dH(I.dI(1y,dO),dO)};B.1s.dL=G(9D,9C){9D=28.8B(9D*28.dN(10,9C));u X=(9D*28.dN(10,-9C)).6I(9C);if(X.3Z(0)=="."){X="0"+X}F X};B.1s.dK=G(k7,dM){F B.1s.dL(k7+0.5*28.dN(10,-dM),dM)};B.1s.k3=G(k6){F B.1s.9B(3k*k6)+"%"};B.1s.1z=["dL","dK","k5","dJ","k4","9B","k3","dI","dH","k2"];B.1s.5V={k1:{9A:",",9z:".",9y:"%"},uU:{9A:".",9z:",",9y:"%"},uT:{9A:" ",9z:",",9y:"%"},"dG":"k1"};B.1s.1W=[];B.1s.2k={":1p":B.1s.1z,":3e":B.1s.1z};B.1s.2d=G(){u 2w=D.1r+".";u k,v,o;R(k in D.5V){o=D.5V[k];if(H(o)=="3n"){o.U=G(){F D.1r};o.1r=2w+"5V."+k}}R(k in D){o=D[k];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+k}1e(e){}}}};B.1s.2d();if(H(B.J)!="L"){B.J.2Y(D,B.1s)}N{(G(k0,dF){if((H(1x)=="L"&&H(1q)=="L")||(H(B.3d)=="5L"&&B.3d)){u 1p=dF.2k[":1p"];R(u i=0;i<1p.K;i++){k0[1p[i]]=dF[1p[i]]}}})(D,B.1s)}if(H(1q)!="L"){1q.2X("B.1k");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1k 3F on B.J!"}if(H(B.1k)=="L"){B.1k={}}B.1k.1r="B.1k";B.1k.1Y="1.3.1";B.1k.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1k.1l=G(){F D.1K()};B.1k.2t=G(jZ){D.55=[];D.id=D.7n();D.2H=-1;D.54=0;D.53=[O,O];D.7m=jZ;D.7l=1m;D.7r=1m};B.1k.2t.1U={U:G(){u 7s;if(D.2H==-1){7s="uS"}N{if(D.2H===0){7s="uR"}N{7s="dE"}}F"2t("+D.id+", "+7s+")"},1l:B.J.24("U"),7n:B.J.4f(),jY:G(){u I=B.1k;if(D.2H==-1){if(D.7m){D.7m(D)}N{D.7l=1h}if(D.2H==-1){D.52(Y I.di(D))}}N{if((D.2H===0)&&(D.53[0]2C I.2t)){D.53[0].jY()}}},jQ:G(){D.54++},jX:G(){D.54--;if((D.54===0)&&(D.2H>=0)){D.9u()}},jR:G(X){D.9x(X);D.jX()},9x:G(X){D.2H=((X 2C 2x)?1:0);D.53[D.2H]=X;D.9u()},dD:G(){if(D.2H!=-1){if(!D.7l){14 Y B.1k.dj(D)}D.7l=1m;F}},3o:G(X){D.dD();if(X 2C B.1k.2t){14 Y 2x("2t jW 9v aB be 7r if jV jU jT jS of a 3o")}D.9x(X)},52:G(X){D.dD();u I=B.1k;if(X 2C I.2t){14 Y 2x("2t jW 9v aB be 7r if jV jU jT jS of a 3o")}if(!(X 2C 2x)){X=Y I.9p(X)}D.9x(X)},jP:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(fn,fn)},5Q:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(fn,O)},jA:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(O,fn)},9w:G(cb,eb){if(D.7r){14 Y 2x("uQ uP 9v 2E be re-uO")}D.55.1c([cb,eb]);if(D.2H>=0){D.9u()}F D},9u:G(){u dC=D.55;u 56=D.2H;u X=D.53[56];u I=D;u cb=O;1M(dC.K>0&&D.54===0){u 2n=dC.2P();u f=2n[56];if(f===O){2V}1f{X=f(X);56=((X 2C 2x)?1:0);if(X 2C B.1k.2t){cb=G(X){I.jR(X)};D.jQ()}}1e(3O){56=1;if(!(3O 2C 2x)){3O=Y B.1k.9p(3O)}X=3O}}D.2H=56;D.53[56]=X;if(cb&&D.54){X.jP(cb);X.7r=1h}}};B.J.2l(B.1k,{dk:G(){F dB("("+M[0].jN+")")},dp:G(uN){u d=Y B.1k.2t();d.3o.1w(d,M);F d},9q:G(uM){u d=Y B.1k.2t();d.52.1w(d,M);F d},do:G(){u I=M.2U;if(!I.7q){u dy=[G(){F Y 7q()},G(){F Y dA("jO.dz")},G(){F Y dA("uL.dz")},G(){F Y dA("jO.dz.4.0")},G(){14 Y B.1k.dh("uK uJ 2E uI 7q")}];R(u i=0;i<dy.K;i++){u 1A=dy[i];1f{I.7q=1A;F 1A()}1e(e){}}}F I.7q()},dx:G(){},jK:G(d){if(D.uH==4){1f{D.5T=O}1e(e){1f{D.5T=B.1k.dx}1e(e){}}u 5U=O;1f{5U=D.jm;if(!5U&&B.J.7e(D.jN)){5U=jM}}1e(e){}if(5U==hQ||5U==jM){d.3o(D)}N{u 3O=Y B.1k.dg(D,"uG uF");if(3O.2y){d.52(3O)}N{d.52(3O)}}}},jL:G(2s){1f{2s.5T=O}1e(e){1f{2s.5T=B.1k.dx}1e(e){}}2s.uE()},dl:G(2s,7p){if(H(7p)=="L"||7p===O){7p=""}u m=B.J;u I=B.1k;u d=Y I.2t(m.2z(I.jL,2s));1f{2s.5T=m.1O(I.jK,2s,d);2s.uD(7p)}1e(e){1f{2s.5T=O}1e(uC){}d.52(e)}F d},dn:G(5F){u I=B.1k;u 2s=I.do();if(M.K>1){u m=B.J;u qs=m.dw.1w(O,m.1R(O,M,1));if(qs){5F+="?"+qs}}2s.cp("uB",5F,1h);F I.dl(2s)},jv:G(5F){u I=B.1k;u d=I.dn.1w(I,M);d=d.5Q(I.dk);F d},dm:G(jJ,dv){u d=Y B.1k.2t();u m=B.J;if(H(dv)!="L"){d.5Q(G(){F dv})}u jI=uA(m.1O("3o",d),28.8B(jJ*c5));d.7m=G(){1f{uz(jI)}1e(e){}};F d},ju:G(jH,1A){u m=B.J;u jG=m.2z.1w(m,m.1R(O,M,1));F B.1k.dm(jH).5Q(G(X){F jG()})}});B.1k.5O=G(){D.5S=[];D.4e=1m;D.id=D.7n()};B.1k.5O.1U={bX:B.1k.5O,uy:G(){d=Y B.1k.2t();if(D.4e){D.5S.1c(d)}N{D.4e=1h;d.3o(D)}F d},jF:G(){if(!D.4e){14 3p("ux to jF an jE 5O")}D.4e=1m;if(D.5S.K>0){D.4e=1h;D.5S.2P().3o(D)}},7n:B.J.4f(),U:G(){u 9t;if(D.4e){9t="4e, "+D.5S.K+" 5S"}N{9t="jE"}F"5O("+D.id+", "+9t+")"},1l:B.J.24("U")};B.1k.7i=G(2G,du,jC,jB,jD){D.2G=2G;D.9r=Y 7o(D.2G.K);D.55=[];D.id=D.7n();D.2H=-1;D.54=0;D.53=[O,O];D.7m=jD;D.7l=1m;if(D.2G.K===0&&!du){D.3o(D.9r)}D.dr=0;D.jz=du;D.jy=jC;D.jx=jB;u 9s=0;B.J.2r(B.J.1O(G(d){d.5Q(B.J.1O(D.dt,D),9s,1h);d.jA(B.J.1O(D.dt,D),9s,1m);9s+=1},D),D.2G)};B.J.2l(B.1k.7i.1U,B.1k.2t.1U);B.J.2l(B.1k.7i.1U,{dt:G(ds,7k,5R){D.9r[ds]=[7k,5R];D.dr+=1;if(D.2H!==0){if(7k&&D.jz){D.3o([ds,5R])}N{if(!7k&&D.jy){D.52(5R)}N{if(D.dr==D.2G.K){D.3o(D.9r)}}}}if(!7k&&D.jx){5R=O}F 5R}});B.1k.jt=G(jw){u d=Y B.1k.7i(jw,1m,1h,1m);d.5Q(G(dq){u 7j=[];R(u i=0;i<dq.K;i++){7j.1c(dq[i][1])}F 7j});F d};B.1k.jr=G(1A){u I=B.1k;u 5P;1f{u r=1A.1w(O,B.J.1R([],M,1));if(r 2C I.2t){5P=r}N{if(r 2C 2x){5P=I.9q(r)}N{5P=I.dp(r)}}}1e(e){5P=I.9q(e)}F 5P};B.1k.1z=["dj","di","dh","9p","dg","2t","dp","9q","do","dn","jv","dm","ju","dl","5O","7i","jt","jr"];B.1k.1W=["dk"];B.1k.2d=G(){u m=B.J;u ne=m.2z(m.jq,D);ne("dj",G(jp){D.jo=jp});ne("di",G(jn){D.jo=jn});ne("dh",G(1t){D.43=1t});ne("9p",G(1t){D.43=1t});ne("dg",G(2s,1t){D.2s=2s;D.43=1t;1f{D.2y=2s.jm}1e(e){}});D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.1k.2d();B.J.2Y(D,B.1k);if(H(1q)!="L"){1q.2X("B.S");1q.2M("B.15")}if(H(1x)!="L"){1x.26("B.15",[])}1f{if(H(B.15)=="L"){14""}}1e(e){14"B.S 3F on B.15!"}if(H(B.S)=="L"){B.S={}}B.S.1r="B.S";B.S.1Y="1.3.1";B.S.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.S.1l=G(){F D.1K()};B.S.1z=["d5","cr","b9","95","94","j3","9k","cX","cw","iT","iV","4X","9j","iQ","hS","cs","ia","i9","i8","i7","i6","i5","i4","hV","i3","i2","i1","cu","hW","ct","i0","hZ","hY","hX","P","io","il","ik","ij","cm","ih","ii","ig","ie","ic","cv","8d","A","6m","ib","1E","$","4q","aH","cO","cN","iM","5G","iK","9d","9e","iH","iD","9c","iB","cG","97","hU","hT","iw","jh","jb","j6","j5","jk","jl"];B.S.1W=["9b"];B.S.5N=G(w,h){D.w=w;D.h=h};B.S.5N.1U.U=G(){u U=B.J.U;F"{w: "+U(D.w)+", h: "+U(D.h)+"}"};B.S.5t=G(x,y){D.x=x;D.y=y};B.S.5t.1U.U=G(){u U=B.J.U;F"{x: "+U(D.x)+", y: "+U(D.y)+"}"};B.S.5t.1U.1l=G(){F D.U()};B.J.2l(B.S,{jl:G(Q,o){Q=B.S.1E(Q);B.S.4X(Q,{"1T":{"9o":o,"-hL-9o":o,"-uw-9o":o,"47":" uv(9o="+(o*3k)+")"}})},jk:G(){u d=Y B.S.5N();u w=B.S.3X;u b=B.S.1Z.5s;if(w.jj){d.w=w.jj;d.h=w.uu}N{if(b.dd.9n){d.w=b.dd.9n;d.h=b.dd.ji}N{if(b&&b.9n){d.w=b.9n;d.h=b.ji}}}F d},jh:G(Q){u I=B.S;if(H(Q.w)=="2y"||H(Q.h)=="2y"){F Y I.5N(Q.w||0,Q.h||0)}Q=I.1E(Q);if(!Q){F L}if(I.4q(Q,"3u")!="98"){F Y I.5N(Q.jg||0,Q.ci||0)}u s=Q.1T;u je=s.dc;u jf=s.6P;s.dc="fR";s.6P="j8";s.3u="";u jd=Q.jg;u jc=Q.ci;s.3u="98";s.6P=jf;s.dc=je;F Y I.5N(jd,jc)},jb:G(Q,4Z){u I=B.S;Q=I.1E(Q);if(!Q){F L}u c=Y I.5t(0,0);if(Q.x&&Q.y){c.x+=Q.x||0;c.y+=Q.y||0;F c}N{if(Q.3t===O||I.4q(Q,"3u")=="98"){F L}}u 51=O;u 2j=O;u d=B.S.1Z;u de=d.7Z;u b=d.5s;if(Q.ja){51=Q.ja();c.x+=51.2I+(de.6y||b.6y)-(de.8q||b.8q);c.y+=51.3D+(de.4C||b.4C)-(de.8p||b.8p)}N{if(d.j9){51=d.j9(Q);c.x+=51.x;c.y+=51.y}N{if(Q.8g){c.x+=Q.db;c.y+=Q.da;2j=Q.8g;if(2j!=Q){1M(2j){c.x+=2j.db;c.y+=2j.da;2j=2j.8g}}u ua=ut.us.8G();if((H(7h)!="L"&&4M(7h.ur())<9)||(ua.2A("uq")!=-1&&I.4q(Q,"6P")=="j8")){c.x-=b.db;c.y-=b.da}}}}if(H(4Z)!="L"){4Z=M.2U(4Z);if(4Z){c.x-=(4Z.x||0);c.y-=(4Z.y||0)}}if(Q.3t){2j=Q.3t}N{2j=O}1M(2j&&2j.j7!="uo"&&2j.j7!="co"){c.x-=2j.6y;c.y-=2j.4C;if(2j.3t){2j=2j.3t}N{2j=O}}F c},j6:G(Q,d9,7g){Q=B.S.1E(Q);if(H(7g)=="L"){7g="px"}B.S.4X(Q,{"1T":{"5A":d9.w+7g,"3V":d9.h+7g}})},j5:G(Q,d8,7f){Q=B.S.1E(Q);if(H(7f)=="L"){7f="px"}B.S.4X(Q,{"1T":{"2I":d8.x+7f,"3D":d8.y+7f}})},cr:G(){F B.S.3X},b9:G(){F B.S.1Z},95:G(2m,1A){u I=B.S;u d6=I.1Z;u d7=I.un;u W;1f{I.3X=2m;I.1Z=2m.2v;W=1A()}1e(e){I.3X=d7;I.1Z=d6;14 e}I.3X=d7;I.1Z=d6;F W},d5:G(Q){u 7d=[];u 7c=[];u m=B.J;u I=B.S;if(H(Q)=="L"||Q===O){Q=I.1Z}N{Q=I.1E(Q)}m.d4(Q,G(Q){u 1b=Q.1b;if(m.7e(1b)){u 4Y=Q.cD;if(4Y=="cv"&&(Q.1J=="um"||Q.1J=="uk")&&!Q.ip){F O}if(4Y=="ct"){if(Q.j4>=0){u 9m=Q.1S[Q.j4];7d.1c(1b);7c.1c((9m.3m)?9m.3m:9m.7X);F O}7d.1c(1b);7c.1c("");F O}if(4Y=="cu"||4Y=="P"||4Y=="8d"||4Y=="6m"){F Q.5h}7d.1c(1b);7c.1c(Q.3m||"");F O}F Q.5h});F[7d,7c]},94:G(1N,1A){u I=B.S;u d3=I.1Z;u W;1f{I.1Z=1N;W=1A()}1e(e){I.1Z=d3;14 e}I.1Z=d3;F W},j3:G(1b,j2,3y,j1){B.S.9b.5M(1b,j2,3y,j1)},9k:G(1j,7a){u im=B.15;u I=B.S;u 1Q=im.1Q;u iY=im.7b;u 4c=im.4c;u iX=I.9b;u iZ=I.9k;u iW=B.J.4d;1M(1h){if(H(1j)=="L"||1j===O){F O}if(H(1j.3T)!="L"&&1j.3T>0){F 1j}if(H(1j)=="2y"||H(1j)=="5L"){1j=1j.1l()}if(H(1j)=="1n"){F I.1Z.4S(1j)}if(H(1j.j0)=="G"){1j=1j.j0(7a);2V}if(H(1j)=="G"){1j=1j(7a);2V}u 9l=O;1f{9l=1Q(1j)}1e(e){}if(9l){F 4c(iZ,9l,iY(7a))}1f{1j=iX.3C(1j,7a);2V}1e(e){if(e!=iW){14 e}}F I.1Z.4S(1j.1l())}F L},iV:G(1j,79,iU){u o={};o[79]=iU;1f{F B.S.4X(1j,o)}1e(e){}F O},iT:G(1j,79){u I=B.S;u d2=I.4U.99[79];1j=I.1E(1j);1f{if(d2){F 1j[d2]}F 1j.fm(79)}1e(e){}F O},4X:G(1j,5K){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j)}if(5K){u d0=B.J.8Z;if(I.4U.6X){R(u k in 5K){u v=5K[k];if(H(v)=="3n"&&H(Q[k])=="3n"){d0(Q[k],v)}N{if(k.2W(0,2)=="on"){if(H(v)=="1n"){v=Y cZ(v)}Q[k]=v}N{Q.4p(k,v)}}}}N{u iS=I.4U.99;R(k in 5K){v=5K[k];u d1=iS[k];if(k=="1T"&&H(v)=="1n"){Q.1T.3x=v}N{if(H(d1)=="1n"){Q[d1]=v}N{if(H(Q[k])=="3n"&&H(v)=="3n"){d0(Q[k],v)}N{if(k.2W(0,2)=="on"){if(H(v)=="1n"){v=Y cZ(v)}Q[k]=v}N{Q.4p(k,v)}}}}}}}F Q},9j:G(1j){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j)}u 78=[I.9k(B.J.1R(O,M,1),Q)];u iR=B.J.2o;1M(78.K){u n=78.2P();if(H(n)=="L"||n===O){}N{if(H(n.3T)=="2y"){Q.2c(n)}N{78=iR(n,78)}}}F Q},iQ:G(1j){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j);M[0]=Q}u cY;1M((cY=Q.6n)){Q.6S(cY)}if(M.K<2){F Q}N{F I.9j.1w(D,M)}},cX:G(1b,4b){u Q;u I=B.S;u m=B.J;if(H(4b)=="1n"||H(4b)=="2y"){u 3G=m.1R([1b,O],M,1);F M.2U.1w(D,3G)}if(H(1b)=="1n"){if(4b&&"1b"in 4b&&!I.4U.6X){1b=("<"+1b+" 1b=\\""+I.9c(4b.1b)+"\\">")}Q=I.1Z.2S(1b)}N{Q=1b}if(4b){I.4X(Q,4b)}if(M.K<=2){F Q}N{u 3G=m.1R([Q],M,2);F I.9j.1w(D,3G)}},cw:G(){u m=B.J;F m.2z.1w(D,m.1R([B.S.cX],M))},cs:G(5J,1d){u I=B.S;5J=I.1E(5J);u cW=5J.3t;if(1d){1d=I.1E(1d);cW.uj(1d,5J)}N{cW.6S(5J)}F 1d},1E:G(id){u I=B.S;if(M.K==1){F((H(id)=="1n")?I.1Z.hN(id):id)}N{F B.J.2r(I.1E,M)}},4q:G(iP,cV,cU){if(M.K==2){cU=cV}u I=B.S;u el=I.1E(iP);u 77=I.1Z;if(!el||el==77){F L}if(el.iO){F el.iO[cV]}if(H(77.5k)=="L"){F L}if(77.5k===O){F L}u 9i=77.5k.g4(el,O);if(H(9i)=="L"||9i===O){F L}F 9i.6q(cU)},aH:G(76,9g,4W){u I=B.S;if(H(76)=="L"||76===O){76="*"}if(H(4W)=="L"||4W===O){4W=I.1Z}4W=I.1E(4W);u 9h=(4W.fr(76)||I.1Z.1p);if(H(9g)=="L"||9g===O){F B.J.1R(O,9h)}u cR=[];R(u i=0;i<9h.K;i++){u cS=9h[i];u cT=cS.3M.2R(" ");R(u j=0;j<cT.K;j++){if(cT[j]==9g){cR.1c(cS);2K}}}F cR},iN:G(5I,9f){u W=G(){u cQ=M.2U.5H;R(u i=0;i<cQ.K;i++){if(cQ[i].1w(D,M)===1m){2K}}if(9f){1f{D[5I]=O}1e(e){}}};W.5H=[];F W},cO:G(cP,5I,1A,9f){u I=B.S;u 4V=cP[5I];u 75=4V;if(!(H(4V)=="G"&&H(4V.5H)=="3n"&&4V.5H!==O)){75=I.iN(5I,9f);if(H(4V)=="G"){75.5H.1c(4V)}cP[5I]=75}75.5H.1c(1A)},cN:G(1A){u I=B.S;I.cO(I.3X,"gh",1A,1h)},iM:G(74){u I=B.S;I.cN(G(){74=I.1E(74);if(74){74.ui()}})},5G:G(iL,cM){u I=B.S;u 1i=I.1E(iL);if(I.4U.6X){1i.4p("iq",cM)}N{1i.4p("3M",cM)}},iK:G(cL){u I=B.S;R(u i=1;i<M.K;i++){u 1i=I.1E(M[i]);if(!I.9d(1i,cL)){I.9e(1i,cL)}}},9d:G(iJ,73){u I=B.S;u 1i=I.1E(iJ);u 2F=1i.3M;if(2F.K===0){I.5G(1i,73);F 1h}if(2F==73){F 1m}u cK=1i.3M.2R(" ");R(u i=0;i<cK.K;i++){if(cK[i]==73){F 1m}}I.5G(1i,2F+" "+73);F 1h},9e:G(iI,cJ){u I=B.S;u 1i=I.1E(iI);u 2F=1i.3M;if(2F.K===0){F 1m}if(2F==cJ){I.5G(1i,"");F 1h}u 72=1i.3M.2R(" ");R(u i=0;i<72.K;i++){if(72[i]==cJ){72.4y(i,1);I.5G(1i,72.2b(" "));F 1h}}F 1m},iH:G(iG,iF,iE){u 1i=B.S.1E(iG);u X=B.S.9e(1i,iF);if(X){B.S.9d(1i,iE)}F X},iD:G(iC,uh){u 1i=B.S.1E(iC);u cI=1i.3M.2R(" ");R(u i=1;i<M.K;i++){u cH=1m;R(u j=0;j<cI.K;j++){if(cI[j]==M[i]){cH=1h;2K}}if(!cH){F 1m}}F 1h},9c:G(s){F s.23(/&/g,"&ug;").23(/"/g,"&uf;").23(/</g,"<").23(/>/g,">")},iB:G(2q){F B.S.cG(2q).2b("")},cG:G(2q,1g){if(H(1g)=="L"||1g===O){1g=[]}u 70=[2q];u I=B.S;u cB=I.9c;u iA=I.4U;1M(70.K){2q=70.hP();if(H(2q)=="1n"){1g.1c(2q)}N{if(2q.3T==1){1g.1c("<"+2q.cD.8G());u 71=[];u cF=iA(2q);R(u i=0;i<cF.K;i++){u a=cF[i];71.1c([" ",a.1b,"=\\"",cB(a.3m),"\\""])}71.iz();R(i=0;i<71.K;i++){u cE=71[i];R(u j=0;j<cE.K;j++){1g.1c(cE[j])}}if(2q.ue()){1g.1c(">");70.1c("</"+2q.cD.8G()+">");u cC=2q.5h;R(i=cC.K-1;i>=0;i--){70.1c(cC[i])}}N{1g.1c("/>")}}N{if(2q.3T==3){1g.1c(cB(2q.iv))}}}}F 1g},97:G(ix,cA){u m=B.J;u iy=m.1R(O,M,1);B.15.9a(m.47(O,m.2r(B.S.1E,iy)),G(cA){cA.1T.3u=ix})},iw:G(1j,iu){u W=[];(G(1j){u cn=1j.5h;if(cn){R(u i=0;i<cn.K;i++){M.2U.cz(D,cn[i])}}u cy=1j.iv;if(H(cy)=="1n"){W.1c(cy)}})(B.S.1E(1j));if(iu){F W}N{F W.2b("")}},2d:G(2m){u m=B.J;D.1Z=2v;D.3X=2m;D.9b=Y m.4a();u 6Z=D.1Z.2S("cj");u 2T;if(6Z&&6Z.6Y&&6Z.6Y.K>0){u it=m.47;2T=G(1j){F it(2T.ir,1j.6Y)};2T.cx={};B.15.9a(6Z.6Y,G(a){2T.cx[a.1b]=a.3m});2T.ir=G(a){F(2T.cx[a.1b]!=a.3m)};2T.6X=1m;2T.99={"iq":"3M","ip":"ud","uc":"ub","R":"u9"}}N{2T=G(1j){F 1j.6Y};2T.6X=1h;2T.99={}}D.4U=2T;u 1C=D.cw;D.io=1C("ul");D.il=1C("ol");D.ik=1C("li");D.ij=1C("td");D.cm=1C("tr");D.ii=1C("u8");D.ih=1C("u7");D.ig=1C("u6");D.ie=1C("u5");D.ic=1C("th");D.cv=1C("ck");D.8d=1C("cj");D.A=1C("a");D.6m=1C("4u");D.ib=1C("u4");D.ia=1C("2e");D.i9=1C("tt");D.i8=1C("4O");D.i7=1C("h1");D.i6=1C("h2");D.i5=1C("h3");D.i4=1C("br");D.i3=1C("hr");D.i2=1C("u3");D.i1=1C("u2");D.cu=1C("u1");D.P=1C("p");D.ct=1C("u0");D.i0=1C("hJ");D.hZ=1C("tZ");D.hY=1C("tY");D.hX=1C("tX");D.hW=1C("tW");D.hV=1C("tV");D.hU=m.2z(D.97,"98");D.hT=m.2z(D.97,"8c");D.hS=D.cs;D.$=D.1E;D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)}});B.S.2d(((H(2O)=="L")?D:2O));if(!B.3d){95=B.S.95;94=B.S.94}B.J.2Y(D,B.S);if(H(1q)!="L"){1q.2X("B.1I");1q.2M("B.1H");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.1H",[]);1x.26("B.J",[])}1f{if(H(B.J)=="L"||H(B.1H)=="L"){14""}}1e(e){14"B.1I 3F on B.J 3W B.1H!"}if(H(B.1I)=="L"){B.1I={}}B.1I.1r="B.1I";B.1I.1Y="1.3.1";B.1I.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1I.1l=G(){F D.1K()};B.1I.bY=G(6W){u m=B.1I;6W=!(!6W);if(m.3l&&m.3l.8Q!=6W){m.3l.hA();m.3l=O}if(!m.3l||m.3l.8P){m.3l=Y m.1I(6W,B.1H.2L)}F m.3l};B.1I.1I=G(4R,6V){if(H(6V)=="L"||6V===O){6V=B.1H.2L}D.2L=6V;u tU=B.J.2l;u c3=B.J.8Z;u 1O=B.J.1O;u hM=B.J.4L;u 2m=2O;u 6U="tT";if(H(B.S)!="L"){2m=B.S.cr()}if(!4R){u 5F=2m.tS.tR.2R("?")[0].23(/[:\\/.><&]/g,"hR");u 1b=6U+"hR"+5F;u 5D=2m.cp("",1b,"tQ,tP,3V=hQ");if(!5D){cq("tO tN to cp tM 2O tL to hP-up tK.");F L}5D.2v.fl("<!tJ co tI \\"-//tH//tG co 4.0 tF//tE\\" "+"\\"fq://fp.tD.fo/cm/tC/tB.tA\\">"+"<hO><5E><8Y>[B.1I]</8Y></5E>"+"<5s></5s></hO>");5D.2v.hG();5D.2v.8Y+=" "+2m.2v.8Y;2m=5D}u 1N=2m.2v;D.1N=1N;u 21=1N.hN(6U);u c4=!!21;if(21&&H(21.5B)!="L"){21.5B.2L=D.2L;21.5B.6K();F 21.5B}if(c4){u cl;1M((cl=21.6n)){21.6S(cl)}}N{21=1N.2S("4u");21.id=6U}21.5B=D;u 8T=1N.2S("ck");u 8S=1N.2S("ck");u 6O=1N.2S("2e");u 6N=1N.2S("2e");u 6M=1N.2S("2e");u 6L=1N.2S("2e");u 3L=1N.2S("4u");u 42=1N.2S("4u");u 8U=6U+"tz";D.8N=hM(D.8N);u 4T=[];u 6R=O;u cf=G(1t){u 6T=1t.3N;if(H(6T)=="2y"){6T=B.1H.5C[6T]}F 6T};u cd=G(1t){F 1t.3z.2b(" ")};u ca=1O(G(1t){u 8W=cf(1t);u 7X=cd(1t);u c=D.8N[8W];u p=1N.2S("cj");p.3M="B-49 B-5C-"+8W;p.1T.3x="ty: 2N; 4F-8X: -hL-4O-3y; 4F-8X: -o-4O-3y; 4F-8X: 4O-3y; 4F-8X: 4O-tx; hK-3y: 2K-hK; 3y-hJ: tw; 3U: "+c;p.2c(1N.4S(8W+": "+7X));42.2c(p);42.2c(1N.2S("br"));if(3L.ci>3L.hI){3L.4C=0}N{3L.4C=3L.hI}},D);u hD=G(1t){4T[4T.K]=1t;ca(1t)};u hF=G(){u cg,ce;1f{cg=Y 8V(8T.3m);ce=Y 8V(8S.3m)}1e(e){ch("2x in 47 tv: "+e.43);F O}F G(1t){F(cg.hH(cf(1t))&&ce.hH(cd(1t)))}};u cc=G(){1M(42.6n){42.6S(42.6n)}};u hB=G(){4T=[];cc()};u bZ=1O(G(){if(D.8P){F}D.8P=1h;if(B.1I.3l==D){B.1I.3l=O}D.2L.c9(8U);21.5B=O;if(4R){21.3t.6S(21)}N{D.2m.hG()}},D);u c7=G(){cc();R(u i=0;i<4T.K;i++){u 1t=4T[i];if(6R===O||6R(1t)){ca(1t)}}};D.6K=G(){6R=hF();c7();D.2L.c9(8U);D.2L.hE(8U,6R,hD)};u c0=1O(G(){4T=D.2L.c8();c7()},D);u c2=1O(G(6Q){6Q=6Q||2O.6D;2h=6Q.6w||6Q.8t;if(2h==13){D.6K()}},D);u 31="3u: 8c; z-c6: c5; 2I: 2N; 6f: 2N; 6P: tu; 5A: 3k%; he-3U: 4F; c1: "+D.8O;if(4R){31+="; 3V: ts; 3E-3D: fO 8a 8y"}N{31+="; 3V: 3k%;"}21.1T.3x=31;if(!c4){1N.5s.2c(21)}31={"3x":"5A: 33%; 3u: 8Q; c1: "+D.8O};c3(8T,{"3m":"8L|8M|8K|8J|8I","hC":c2,"1T":31});21.2c(8T);c3(8S,{"3m":".*","hC":c2,"1T":31});21.2c(8S);31="5A: 8%; 3u:8Q; c1: "+D.8O;6O.2c(1N.4S("tq"));6O.8R=1O("6K",D);6O.1T.3x=31;21.2c(6O);6N.2c(1N.4S("tp"));6N.8R=c0;6N.1T.3x=31;21.2c(6N);6M.2c(1N.4S("tn"));6M.8R=hB;6M.1T.3x=31;21.2c(6M);6L.2c(1N.4S("tm"));6L.8R=bZ;6L.1T.3x=31;21.2c(6L);3L.1T.3x="fS: tk; 5A: 3k%";42.1T.3x="5A: 3k%; 3V: "+(4R?"tj":"3k%");3L.2c(42);21.2c(3L);D.6K();c0();if(4R){D.2m=L}N{D.2m=2m}D.8Q=4R;D.hA=bZ;D.8P=1m;F D};B.1I.1I.1U={"8O":"ti tg,tf-te","8N":{"8M":"1v","8L":"gU","8K":"1F","8J":"8y","8I":"bx"}};B.1I.1W=["1I"];B.1I.1z=["bY"];B.1I.2d=G(){D.2k={":3e":D.1z,":1p":B.J.2o(D.1z,D.1W)};B.J.3f(D);B.1I.3l=O};B.1I.2d();B.J.2Y(D,B.1I);if(H(1q)!="L"){1q.2X("B.V");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.V 3F on B.J"}if(H(B.V)=="L"){B.V={}}B.V.1r="B.V";B.V.1Y="1.3.1";B.V.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.V.1l=G(){F D.1K()};B.V.V=G(1v,hz,1F,6J){if(H(6J)=="L"||6J===O){6J=1}D.1B={r:1v,g:hz,b:1F,a:6J}};B.V.V.1U={bX:B.V.V,tc:G(hy){u 1B=D.1B;u m=B.V;F m.V.3Y(1B.r,1B.g,1B.b,hy)},tb:G(1o){u 1G=D.41();1G.h=1o;u m=B.V;F m.V.4H(1G)},ta:G(hx){u 1G=D.41();1G.s=hx;u m=B.V;F m.V.4H(1G)},t9:G(hw){u 1G=D.41();1G.l=hw;u m=B.V;F m.V.4H(1G)},t8:G(hv){u 1G=D.41();1G.l=28.29(1G.l-hv,0);u m=B.V;F m.V.4H(1G)},t7:G(hu){u 1G=D.41();1G.l=28.2a(1G.l+hu,1);u m=B.V;F m.V.4H(1G)},fJ:G(ht,5z){if(H(5z)=="L"||5z===O){5z=0.5}u sf=1-5z;u s=D.1B;u d=ht.1B;u df=5z;F B.V.V.3Y((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df))},h4:G(hs){u a=D.6r();u b=hs.6r();F B.J.2f([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a])},hq:G(){F D.41().b>0.5},t6:G(){F(!D.hq())},t5:G(){u c=D.41();u 2Z=B.V.6F;u W=D.ho;if(!W){u 5y=(2Z(c.h,bF).6I(0)+","+2Z(c.s,3k).hp(4)+"%"+","+2Z(c.l,3k).hp(4)+"%");u a=c.a;if(a>=1){a=1;W="1G("+5y+")"}N{if(a<=0){a=0}W="t4("+5y+","+a+")"}D.ho=W}F W},hl:G(){u c=D.1B;u 2Z=B.V.6F;u W=D.hn;if(!W){u 5y=(2Z(c.r,3h).6I(0)+","+2Z(c.g,3h).6I(0)+","+2Z(c.b,3h).6I(0));if(c.a!=1){W="t3("+5y+","+c.a+")"}N{W="1B("+5y+")"}D.hn=W}F W},6r:G(){F B.J.4L(D.1B)},t2:G(){u m=B.V;u c=D.1B;u 2Z=B.V.6F;u W=D.hm;if(!W){W=("#"+m.6E(2Z(c.r,3h))+m.6E(2Z(c.g,3h))+m.6E(2Z(c.b,3h)));D.hm=W}F W},t1:G(){u 2Q=D.2Q;u c=D.1B;if(H(2Q)=="L"||2Q===O){2Q=B.V.bA(D.1B);D.2Q=2Q}F B.J.4L(2Q)},41:G(){u 1G=D.1G;u c=D.1B;if(H(1G)=="L"||1G===O){1G=B.V.bC(D.1B);D.1G=1G}F B.J.4L(1G)},1l:G(){F D.hl()},U:G(){u c=D.1B;u hk=[c.r,c.g,c.b,c.a];F D.bX.1r+"("+hk.2b(", ")+")"}};B.J.2l(B.V.V,{3Y:G(1v,bW,1F,8H){u hj=B.V.V;if(M.K==1){u 1B=1v;1v=1B.r;bW=1B.g;1F=1B.b;if(H(1B.a)=="L"){8H=L}N{8H=1B.a}}F Y hj(1v,bW,1F,8H)},4H:G(1o,t0,sZ,sY){u m=B.V;F m.V.3Y(m.bB.1w(m,M))},sX:G(1o,sW,sV,sU){u m=B.V;F m.V.3Y(m.bz.1w(m,M))},hi:G(1b){u 8F=B.V.V;if(1b.3Z(0)=="\\""){1b=1b.3H(1,1b.K-2)}u bV=8F.by[1b.8G()];if(H(bV)=="1n"){F 8F.bT(bV)}N{if(1b=="aP"){F 8F.sT()}}F O},8f:G(4Q){u I=B.V.V;u bU=4Q.3H(0,3);if(bU=="1B"){F I.h9(4Q)}N{if(bU=="1G"){F I.h8(4Q)}N{if(4Q.3Z(0)=="#"){F I.bT(4Q)}}}F I.hi(4Q)},bT:G(4P){if(4P.3Z(0)=="#"){4P=4P.2W(1)}u 8E=[];u i,5x;if(4P.K==3){R(i=0;i<3;i++){5x=4P.3H(i,1);8E.1c(3w(5x+5x,16)/3h)}}N{R(i=0;i<6;i+=2){5x=4P.3H(i,2);8E.1c(3w(5x,16)/3h)}}u bS=B.V.V;F bS.3Y.1w(bS,8E)},bG:G(4O,hf,hg,4N){if(4N.2A(4O)===0){4N=4N.2W(4N.2A("(",3)+1,4N.K-1)}u bR=4N.2R(/\\s*,\\s*/);u bP=[];R(u i=0;i<bR.K;i++){u c=bR[i];u 2i;u bQ=c.2W(c.K-3);if(c.3Z(c.K-1)=="%"){2i=0.bE*4M(c.2W(0,c.K-1))}N{if(bQ=="sS"){2i=4M(c)/bF}N{if(bQ=="sR"){2i=4M(c)/(28.sQ*2)}N{2i=hg[i]*4M(c)}}}bP.1c(2i)}F D[hf].1w(D,bP)},bN:G(Q,sP,sO){u d=B.S;u 2F=B.V.V;R(Q=d.1E(Q);Q;Q=Q.3t){u bO=d.4q.1w(d,M);if(!bO){2V}u 8D=2F.8f(bO);if(!8D){2K}if(8D.6r().a>0){F 8D}}F O},ba:G(Q){u 2F=B.V.V;F 2F.bN(Q,"aZ","he-3U")||2F.sN()},sM:G(Q){u 2F=B.V.V;F 2F.bN(Q,"3U","3U")||2F.sL()},sK:G(){F B.J.4L(B.V.V.by)}});B.J.2l(B.V,{6F:G(v,8C){v*=8C;if(v<0){F 0}N{if(v>8C){F 8C}N{F v}}},hc:G(n1,n2,1o){if(1o>6){1o-=6}N{if(1o<0){1o+=6}}u 2i;if(1o<1){2i=n1+(n2-n1)*1o}N{if(1o<3){2i=n2}N{if(1o<4){2i=n1+(n2-n1)*(4-1o)}N{2i=n1}}}F 2i},bz:G(1o,5w,3i,bM){if(M.K==1){u 2Q=1o;1o=2Q.h;5w=2Q.s;3i=2Q.v;bM=2Q.a}u 1v;u 3K;u 1F;if(5w===0){1v=0;3K=0;1F=0}N{u i=28.8B(1o*6);u f=(1o*6)-i;u p=3i*(1-5w);u q=3i*(1-(5w*f));u t=3i*(1-(5w*(1-f)));hd(i){3j 1:1v=q;3K=3i;1F=p;2K;3j 2:1v=p;3K=3i;1F=t;2K;3j 3:1v=p;3K=q;1F=3i;2K;3j 4:1v=t;3K=p;1F=3i;2K;3j 5:1v=3i;3K=p;1F=q;2K;3j 6:3j 0:1v=3i;3K=t;1F=p;2K}}F{r:1v,g:3K,b:1F,a:bM}},bB:G(1o,5v,3v,bL){if(M.K==1){u 1G=1o;1o=1G.h;5v=1G.s;3v=1G.l;bL=1G.a}u 1v;u 8A;u 1F;if(5v===0){1v=3v;8A=3v;1F=3v}N{u m2;if(3v<=0.5){m2=3v*(1+5v)}N{m2=3v+5v-(3v*5v)}u m1=(2*3v)-m2;u f=B.V.hc;u h6=1o*6;1v=f(m1,m2,h6+2);8A=f(m1,m2,h6);1F=f(m1,m2,h6-2)}F{r:1v,g:8A,b:1F,a:bL}},bA:G(1v,4K,1F,bK){if(M.K==1){u 1B=1v;1v=1B.r;4K=1B.g;1F=1B.b;bK=1B.a}u 29=28.29(28.29(1v,4K),1F);u 2a=28.2a(28.2a(1v,4K),1F);u 1o;u 8z;u hb=29;if(2a==29){1o=0;8z=0}N{u 6H=(29-2a);8z=6H/29;if(1v==29){1o=(4K-1F)/6H}N{if(4K==29){1o=2+((1F-1v)/6H)}N{1o=4+((1v-4K)/6H)}}1o/=6;if(1o<0){1o+=1}if(1o>1){1o-=1}}F{h:1o,s:8z,v:hb,a:bK}},bC:G(1v,4J,1F,bI){if(M.K==1){u 1B=1v;1v=1B.r;4J=1B.g;1F=1B.b;bI=1B.a}u 29=28.29(1v,28.29(4J,1F));u 2a=28.2a(1v,28.2a(4J,1F));u 1o;u 6G;u bJ=(29+2a)/2;u 4I=29-2a;if(4I===0){1o=0;6G=0}N{if(bJ<=0.5){6G=4I/(29+2a)}N{6G=4I/(2-29-2a)}if(1v==29){1o=(4J-1F)/4I}N{if(4J==29){1o=2+((1F-1v)/4I)}N{1o=4+((1v-4J)/4I)}}1o/=6;if(1o<0){1o+=1}if(1o>1){1o-=1}}F{h:1o,s:6G,l:bJ,a:bI}},6E:G(1P){1P=28.ha(1P);u bH=1P.1l(16);if(1P<16){F"0"+bH}F bH},2d:G(){u m=B.J;D.V.h9=m.1O(D.V.bG,D.V,"1B","3Y",[1/3h,1/3h,1/3h,1]);D.V.h8=m.1O(D.V.bG,D.V,"1G","4H",[1/bF,0.bE,0.bE,1]);u 4G=1/3;u bD={8y:[0,0,0],1F:[0,0,1],gY:[0.6,0.4,0.2],gX:[0,1,1],sJ:[4G,4G,4G],gR:[0.5,0.5,0.5],bx:[0,1,0],sI:[2*4G,2*4G,2*4G],gN:[1,0,1],gL:[1,0.5,0],gK:[0.5,0,0.5],1v:[1,0,0],aP:[0,0,0,0],4F:[1,1,1],gI:[1,1,0]};u h7=G(1b,r,g,b,a){u W=D.3Y(r,g,b,a);D[1b]=G(){F W};F W};R(u k in bD){u 1b=k+"V";u h5=m.2o([h7,D.V,1b],bD[k]);D.V[1b]=m.1O.1w(O,h5)}u h0=G(){R(u i=0;i<M.K;i++){if(!(M[i]2C V)){F 1m}}F 1h};u gZ=G(a,b){F a.h4(b)};m.3f(D);m.5u(D.V.1r,h0,gZ);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)}}});B.V.1z=["V"];B.V.1W=["6F","bC","bB","bA","bz","6E"];B.V.2d();B.J.2Y(D,B.V);B.V.V.by={sH:"#sG",sF:"#sE",sD:"#gW",sC:"#sB",sA:"#sz",sy:"#sx",sw:"#sv",8y:"#su",st:"#sr",1F:"#sq",sp:"#so",gY:"#sn",sm:"#sl",sk:"#sj",si:"#sh",sg:"#se",sd:"#sc",sb:"#sa",s9:"#s8",s7:"#s6",gX:"#gW",s5:"#s4",s3:"#s2",s1:"#s0",rZ:"#gV",rY:"#rX",rW:"#gV",rV:"#rU",rT:"#rS",rR:"#rQ",rP:"#rO",rN:"#rM",gU:"#rL",rK:"#rJ",rI:"#rH",rG:"#rF",rE:"#gT",rD:"#gT",rC:"#rB",rA:"#rz",ry:"#rx",rw:"#rv",ru:"#gS",rt:"#gS",rs:"#rr",rq:"#rp",ro:"#rn",rm:"#rl",rk:"#gM",rj:"#ri",rh:"#rg",rf:"#rd",rc:"#rb",gR:"#gQ",bx:"#ra",r9:"#r8",r7:"#gQ",r6:"#r5",r4:"#r3",r2:"#r1",r0:"#qZ",qY:"#qX",qW:"#qV",qU:"#qT",qS:"#qR",qQ:"#qP",qO:"#qN",qM:"#qL",qK:"#qJ",qI:"#qH",qG:"#qF",qE:"#gP",qD:"#qC",qB:"#gP",qA:"#qz",qy:"#qx",qw:"#qv",qu:"#qt",qr:"#gO",qq:"#gO",qp:"#qo",qn:"#qm",ql:"#qk",qj:"#qi",qh:"#qg",gN:"#gM",qf:"#qe",qd:"#qc",qb:"#qa",q9:"#q8",q7:"#q6",q5:"#q4",q3:"#q2",q1:"#q0",pZ:"#pY",pX:"#pW",pV:"#pU",pT:"#pS",pR:"#pQ",pP:"#pO",pN:"#pM",pL:"#pK",pJ:"#pI",pH:"#pG",pF:"#pE",gL:"#pD",pC:"#pB",pA:"#pz",py:"#pw",pv:"#pu",pt:"#ps",pr:"#pq",pp:"#po",pn:"#pm",pl:"#pj",pi:"#ph",pg:"#pf",pe:"#pd",gK:"#pc",1v:"#pb",pa:"#p9",p8:"#p7",p6:"#p5",p4:"#p3",p2:"#p1",p0:"#oZ",oY:"#oX",oW:"#oV",oU:"#oT",oS:"#oR",oQ:"#oP",oO:"#gJ",oN:"#gJ",oM:"#oL",oK:"#oJ",oI:"#oH",oG:"#oF",oE:"#oD",oC:"#oB",oA:"#oz",oy:"#ox",ow:"#ov",ou:"#ot",4F:"#os",oq:"#op",gI:"#oo",om:"#ok"};if(H(1q)!="L"){1q.2X("B.1u");1q.2M("B.J");1q.2M("B.S")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.S",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1u 3F on B.J!"}1f{if(H(B.S)=="L"){14""}}1e(e){14"B.1u 3F on B.S!"}if(H(B.1u)=="L"){B.1u={}}B.1u.1r="B.1u";B.1u.1Y="1.3.1";B.1u.4x=[];B.1u.bq=G(1d,e){D.1L=e||2O.6D;D.gH=1d};B.J.2l(B.1u.bq.1U,{1K:G(){u U=B.J.U;u 1y="{6D(): "+U(D.6D())+", 1d(): "+U(D.1d())+", 1J(): "+U(D.1J())+", 8x(): "+U(D.8x())+", 4E(): "+"{8w: "+U(D.4E().8w)+", 8v: "+U(D.4E().8v)+", 8u: "+U(D.4E().8u)+", 2P: "+U(D.4E().2P)+", bw: "+U(D.4E().bw)+"}";if(D.1J()&&D.1J().2A("2h")===0){1y+=", 2h(): {3J: "+U(D.2h().3J)+", 1n: "+U(D.2h().1n)+"}"}if(D.1J()&&(D.1J().2A("3I")===0||D.1J().2A("gE")!=-1||D.1J()=="gD")){1y+=", 3I(): {4D: "+U(D.3I().4D)+", 6A: "+U(D.3I().6A);if(D.1J()!="gC"){1y+=", 2e: {2I: "+U(D.3I().2e.2I)+", 6v: "+U(D.3I().2e.6v)+", 3g: "+U(D.3I().2e.3g)+"}}"}N{1y+="}"}}if(D.1J()=="gG"||D.1J()=="gF"){1y+=", 6C(): "+U(D.6C())}1y+="}";F 1y},1l:G(){F D.1K()},1d:G(){F D.gH},6D:G(){F D.1L},1J:G(){F D.1L.1J||L},8x:G(){F D.1L.8x||D.1L.oj},6C:G(){if(D.1J()=="gG"){F(D.1L.6C||D.1L.aW)}N{if(D.1J()=="gF"){F(D.1L.6C||D.1L.oi)}}F L},4E:G(){u m={};m.8w=D.1L.oh;m.8v=D.1L.og;m.8u=D.1L.oe||1m;m.2P=D.1L.od;m.bw=m.8w||m.8v||m.2P||m.8u;F m},2h:G(){u k={};if(D.1J()&&D.1J().2A("2h")===0){if(D.1J()=="oc"||D.1J()=="ob"){k.3J=D.1L.8t;k.1n=(B.1u.5r[k.3J]||"oa");F k}N{if(D.1J()=="o9"){k.3J=0;k.1n="";if(H(D.1L.6B)!="L"&&D.1L.6B!==0&&!B.1u.bv[D.1L.6B]){k.3J=D.1L.6B;k.1n=bu.bt(k.3J)}N{if(D.1L.8t&&H(D.1L.6B)=="L"){k.3J=D.1L.8t;k.1n=bu.bt(k.3J)}}F k}}}F L},3I:G(){u m={};u e=D.1L;if(D.1J()&&(D.1J().2A("3I")===0||D.1J().2A("gE")!=-1||D.1J()=="gD")){m.6A=Y B.S.5t(0,0);if(e.6z||e.6x){m.6A.x=(!e.6z||e.6z<0)?0:e.6z;m.6A.y=(!e.6x||e.6x<0)?0:e.6x}m.4D=Y B.S.5t(0,0);if(e.8s||e.8r){m.4D.x=(!e.8s||e.8s<0)?0:e.8s;m.4D.y=(!e.8r||e.8r<0)?0:e.8r}N{u de=B.S.1Z.7Z;u b=B.S.1Z.5s;m.4D.x=e.6z+(de.6y||b.6y)-(de.8q||b.8q);m.4D.y=e.6x+(de.4C||b.4C)-(de.8p||b.8p)}if(D.1J()!="gC"){m.2e={};m.2e.2I=1m;m.2e.3g=1m;m.2e.6v=1m;if(e.6w){m.2e.2I=(e.6w==1);m.2e.6v=(e.6w==2);m.2e.3g=(e.6w==3)}N{m.2e.2I=!!(e.2e&1);m.2e.3g=!!(e.2e&2);m.2e.6v=!!(e.2e&4)}}F m}F L},2J:G(){D.8o();D.8n()},8o:G(){if(D.1L.8o){D.1L.8o()}N{D.1L.o8=1h}},8n:G(){if(D.1L.8n){D.1L.8n()}N{D.1L.o7=1m}}});B.1u.bv={3:"gz",o6:"gA",o5:"gy",o4:"gx",o3:"gw",o2:"gv",o1:"gu",o0:"gs",nZ:"gr",nY:"gq",nX:"gp",nW:"go"};R(i=gB;i<=nV;i++){B.1u.bv[i]="gk"+(i-gB+1)}B.1u.5r={8:"nU",9:"nT",12:"gA",13:"gz",16:"nS",17:"nR",18:"nQ",19:"nP",20:"nO",27:"nN",32:"nM",33:"gy",34:"gx",35:"gw",36:"gv",37:"gu",38:"gs",39:"gr",40:"gq",44:"nL",45:"gp",46:"go",59:"gn",91:"nK",92:"nJ",93:"nI",nH:"nG",nF:"nE",nD:"nC-gm",nB:"nA",nz:"ny",nx:"nw",nv:"nu",nt:"gn",ns:"nr",nq:"np",nn:"nm-gm",nl:"nk",nj:"ni",nh:"ng",nf:"nd",nc:"nb",na:"n9",n8:"n7"};R(u i=48;i<=57;i++){B.1u.5r[i]="gl"+(i-48)}R(i=65;i<=90;i++){B.1u.5r[i]="gl"+bu.bt(i)}R(i=96;i<=n6;i++){B.1u.5r[i]="n5"+(i-96)}R(i=gj;i<=n4;i++){B.1u.5r[i]="gk"+(i-gj+1)}B.J.2l(B.1u,{1K:G(){F"["+D.1r+" "+D.1Y+"]"},1l:G(){F D.1K()},g7:G(){u I=B.1u;u bs=I.4x;R(u i=0;i<bs.K;i++){I.6t(bs[i])}gi I.4x;1f{2O.gh=L}1e(e){}1f{2O.g8=L}1e(e){}},gb:G(1d,1A,1i,gg){u E=B.1u.bq;if(!gg){F B.J.1O(1A,1i)}1i=1i||1d;if(H(1A)=="1n"){F G(gf){1i[1A].1w(1i,[Y E(1d,gf)])}}N{F G(gd){1A.1w(1i,[Y E(1d,gd)])}}},6s:G(1d,2D,5q,4B){1d=B.S.1E(1d);u I=B.1u;if(H(2D)!="1n"){14 Y 2x("\'2D\' 5p be a 1n")}u 1i=O;u 1A=O;if(H(4B)!="L"){1i=5q;1A=4B;if(H(4B)=="1n"){if(H(5q[4B])!="G"){14 Y 2x("\'bp\' 5p be a G on \'gc\'")}}N{if(H(4B)!="G"){14 Y 2x("\'bp\' 5p be a G or 1n")}}}N{if(H(5q)!="G"){14 Y 2x("\'gc\' 5p be a G if \'bp\' is 2E n3")}N{1A=5q}}if(H(1i)=="L"||1i===O){1i=1d}u bm=!!(1d.bo||1d.bn);u 8m=I.gb(1d,1A,1i,bm);if(1d.bo){1d.bo(2D.3H(2),8m,1m)}N{if(1d.bn){1d.bn(2D,8m)}}u bk=[1d,2D,8m,bm,5q,4B];I.4x.1c(bk);F bk},6t:G(6u){if(!6u[3]){F}u 1d=6u[0];u 2D=6u[1];u bj=6u[2];if(1d.ga){1d.ga(2D.3H(2),bj,1m)}N{if(1d.g9){1d.g9(2D,bj)}N{14 Y 2x("\'1d\' 5p be a S n0")}}},8j:G(bh){u I=B.1u;u 5o=I.4x;u m=B.J;if(M.K>1){u 1d=B.S.1E(M[0]);u 2D=M[1];u 1i=M[2];u 1A=M[3];R(u i=5o.K-1;i>=0;i--){u o=5o[i];if(o[0]===1d&&o[1]===2D&&o[4]===1i&&o[5]===1A){I.6t(o);5o.4y(i,1);F 1h}}}N{u 5n=m.bi(5o,bh);if(5n>=0){I.6t(bh);5o.4y(5n,1);F 1h}}F 1m},8i:G(1d,2D){1d=B.S.1E(1d);u m=B.J;u 8l=m.bg(m.1R(O,M,1));u I=B.1u;u bd=I.6t;u 4z=I.4x;if(8l.K===0){R(u i=4z.K-1;i>=0;i--){u 4A=4z[i];if(4A[0]===1d){bd(4A);4z.4y(i,1)}}}N{u bf={};R(u i=0;i<8l.K;i++){bf[8l[i]]=1h}R(u i=4z.K-1;i>=0;i--){u 4A=4z[i];if(4A[0]===1d&&4A[1]in bf){bd(4A);4z.4y(i,1)}}}},8h:G(1d,2D){u bc=B.1u.4x;1d=B.S.1E(1d);u 3G=B.J.1R(O,M,2);u 5m=[];R(u i=0;i<bc.K;i++){u 8k=bc[i];if(8k[0]===1d&&8k[1]===2D){1f{8k[2].1w(1d,3G)}1e(e){5m.1c(e)}}}if(5m.K==1){14 5m[0]}N{if(5m.K>1){u e=Y 2x("mZ bb mY in mX \'2D\', mW bb mV");e.bb=5m;14 e}}}});B.1u.1W=[];B.1u.1z=["6s","8j","8h","8i"];B.1u.2d=G(2m){u m=B.J;D.1Z=2v;D.3X=2m;1f{D.6s(2O,"g8",D.g7)}1e(e){}D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.1u.2d(D);if(!B.3d){6s=B.1u.6s;8j=B.1u.8j;8i=B.1u.8i;8h=B.1u.8h}B.J.2Y(D,B.1u);if(H(1q)!="L"){1q.2X("B.1X");1q.2M("B.J");1q.2M("B.S");1q.2M("B.V")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.S",[]);1x.26("B.V",[])}1f{if(H(B.J)=="L"||H(B.S)=="L"||H(B.V)=="L"){14""}}1e(e){14"B.1X 3F on B.J, B.S 3W B.V!"}if(H(B.1X)=="L"){B.1X={}}B.1X.1r="B.1X";B.1X.1Y="1.3.1";B.1X.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1X.1l=G(){F D.1K()};B.1X.aI=G(e,g6){e=B.S.1E(e);D.fN(g6);if(D.1S.fL){e=D.g5(e)}u 4w=D.1S.3U;u C=B.V.V;if(D.1S.3U=="aW"){4w=C.ba(e)}N{if(!(4w 2C C)){4w=C.8f(4w)}}D.82=(4w.6r().a<=0);u 5l=D.1S.aV;if(D.1S.aV=="fM"){5l=C.ba(e.8g)}N{if(!(5l 2C C)){5l=C.8f(5l)}}D.g3(e,4w,5l)};B.1X.aI.1U={g5:G(e){u mU=e.3t;u 1N=B.S.b9();if(H(1N.5k)=="L"||1N.5k===O){F e}u 4v=1N.5k.g4(e,O);if(H(4v)=="L"||4v===O){F e}u b8=B.S.6m({"1T":{3u:"8c",mT:4v.6q("6p-3D"),85:4v.6q("6p-3g"),mS:4v.6q("6p-6f"),86:4v.6q("6p-2I"),6p:"2N"}});b8.6o=e.6o;e.6o="";e.2c(b8);F e},g3:G(e,b7,8e){if(D.1S.3E){D.g2(e,8e)}if(D.fy()){D.fX(e,b7,8e)}if(D.fx()){D.fV(e,b7,8e)}},g2:G(el,g1){u b6="6l 8a "+D.aQ(g1);u g0="3E-2I: "+b6;u fZ="3E-3g: "+b6;u fY="1T=\'"+g0+";"+fZ+"\'";el.6o="<4u "+fY+">"+el.6o+"</4u>"},fX:G(el,fW,b5){u b4=D.b1(b5);R(u i=0;i<D.1S.89;i++){b4.2c(D.b0(fW,b5,i,"3D"))}el.1T.mR=0;el.mQ(b4,el.6n)},fV:G(el,fU,b3){u b2=D.b1(b3);R(u i=(D.1S.89-1);i>=0;i--){b2.2c(D.b0(fU,b3,i,"6f"))}el.1T.mP=0;el.2c(b2)},b1:G(fT){u 2q=B.S;F 2q.6m({1T:{aZ:fT.1l()}})},b0:G(aY,fQ,n,aX){u 6k=B.S.8d();u 2p=6k.1T;2p.aZ=aY.1l();2p.3u="8c";2p.3V="6l";2p.fS="fR";2p.mO="6l";u 8b=D.aQ(aY,fQ);if(D.1S.3E&&n===0){2p.mN="8a";2p.mM="6l";2p.84="2N";2p.83="2N";2p.mL="2N";2p.3V="2N";2p.fP=8b.1l()}N{if(8b){2p.fP=8b.1l();2p.mK="8a";2p.mJ="2N 6l"}}if(!D.1S.4r&&(n==(D.1S.89-1))){2p.3V="fO"}D.fI(6k,n,aX);D.fG(6k,n,aX);F 6k},fN:G(fK){D.1S={6g:"1p",3U:"aW",aV:"fM",5j:1h,3E:1m,4r:1m,fL:1m};B.J.2l(D.1S,fK);D.1S.89=(D.1S.4r?2:4)},aL:G(){u 88=D.1S.6g;if(D.6h(88,"1p","3D")){F""}u aU=(88.2A("tl")!=-1);u aT=(88.2A("tr")!=-1);if(aU&&aT){F""}if(aU){F"2I"}if(aT){F"3g"}F""},aK:G(){u 87=D.1S.6g;if(D.6h(87,"1p","6f")){F""}u aS=(87.2A("bl")!=-1);u aR=(87.2A("br")!=-1);if(aS&&aR){F""}if(aS){F"2I"}if(aR){F"3g"}F""},aQ:G(aN,aO){if(aN=="aP"){F aO}N{if(D.1S.3E){F D.1S.3E}N{if(D.1S.5j){F aO.fJ(aN)}}}F""},fI:G(el,n,fH){u 6j=D.fE(n)+"px";u aM=(fH=="3D"?D.aL():D.aK());u 4t=el.1T;if(aM=="2I"){4t.86=6j;4t.85="2N"}N{if(aM=="3g"){4t.85=6j;4t.86="2N"}N{4t.86=6j;4t.85=6j}}},fG:G(el,n,fF){u 6i=D.fz(n)+"px";u aJ=(fF=="3D"?D.aL():D.aK());u 4s=el.1T;if(aJ=="2I"){4s.84=6i;4s.83="2N"}N{if(aJ=="3g"){4s.83=6i;4s.84="2N"}N{4s.84=6i;4s.83=6i}}},fE:G(n){if(D.82){F 0}u o=D.1S;if(o.4r&&o.5j){u fD=[1,0];F fD[n]}N{if(o.4r){u fC=[2,1];F fC[n]}N{if(o.5j){u fB=[3,2,1,0];F fB[n]}N{u fA=[5,3,2,1];F fA[n]}}}},fz:G(n){u o=D.1S;u 5i;if(o.4r&&(o.5j||D.82)){F 1}N{if(o.4r){5i=[1,0]}N{if(o.5j){5i=[2,1,1,1]}N{if(o.3E){5i=[0,2,0,0]}N{if(D.82){5i=[5,3,2,1]}N{F 0}}}}}F 5i[n]},6h:G(1y){R(u i=1;i<M.K;i++){if(1y.2A(M[i])!=-1){F 1h}}F 1m},fy:G(){F D.6h(D.1S.6g,"1p","3D","tl","tr")},fx:G(){F D.6h(D.1S.6g,"1p","6f","bl","br")},mI:G(el){F(el.5h.K==1&&el.5h[0].3T==3)}};B.1X.aF=G(e,fw){Y B.1X.aI(e,fw)};B.1X.fs=G(fv,fu,ft){u aG=B.S.aH(fv,fu);R(u i=0;i<aG.K;i++){B.1X.aF(aG[i],ft)}};B.1X.V=B.V.V;B.1X.mH=B.S.4q;B.1X.2d=G(){u m=B.J;m.3f(D);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)}};B.1X.1z=["aF","fs"];B.1X.1W=[];B.1X.2d();B.J.2Y(D,B.1X);if(H(B)=="L"){B={}}if(H(B.B)=="L"){B.B={}}B.B.1r="B.B";B.B.1Y="1.3.1";B.B.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.B.1l=G(){F D.1K()};B.B.aA=["J","15","1H","1D","1s","1k","S","1I","V","1u","1X"];if(H(1x)!="L"||H(1q)!="L"){if(H(1q)!="L"){1q.2X("B.B");1q.2M("B.*")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.15",[]);1x.26("B.1H",[]);1x.26("B.1D",[]);1x.26("B.1s",[]);1x.26("B.1k",[]);1x.26("B.S",[]);1x.26("B.1I",[]);1x.26("B.V",[]);1x.26("B.1u",[]);1x.26("B.1X",[])}(G(){u 6e=B.J.1R;u I=B.B;u aE=I.aA;u aD=[];u aC=[];u 81={};u i,k,m,1p;R(i=0;i<aE.K;i++){m=B[aE[i]];6e(aD,m.1z);6e(aC,m.1W);R(k in m.2k){81[k]=6e(81[k],m.2k[k])}1p=m.2k[":1p"];if(!1p){1p=6e(O,m.1z,m.1W)}u j;R(j=0;j<1p.K;j++){k=1p[j];I[k]=m[k]}}I.1z=aD;I.1W=aC;I.2k=81}())}N{if(H(B.3d)=="L"){B.3d=1h}(G(){u 80=2v.fr("7W");u ay="fq://fp.mG.fo/mF/mE/mD.is.aB.mC";u 2w=O;u ax=O;u az={};u i;R(i=0;i<80.K;i++){u 1d=80[i].fm("1d");if(!1d){2V}az[1d]=1h;if(1d.3C(/B.js$/)){2w=1d.2W(0,1d.mB("B.js"));ax=80[i]}}if(2w===O){F}u 6d=B.B.aA;R(u i=0;i<6d.K;i++){if(B[6d[i]]){2V}u 7Y=2w+6d[i]+".js";if(7Y in az){2V}if(2v.7Z&&2v.7Z.mA==ay){u s=2v.mz(ay,"7W");s.4p("id","my"+2w+6d[i]);s.4p("1d",7Y);s.4p("1J","mx/x-fk");ax.3t.2c(s)}N{2v.fl("<7W 1d=\\""+7Y+"\\" 1J=\\"7X/fk\\"></7W>")}}})()}',62,1976,'||||||||||||||||||||||||||||||var|||||||MochiKit||this||return|function|typeof|self|Base|length|undefined|arguments|else|null||elem|for|DOM||repr|Color|rval|res|new||||||throw|Iter|||||next|name|push|src|catch|try|lst|true|obj|node|Async|toString|false|string|hue|all|dojo|NAME|Format|msg|Signal|red|apply|JSAN|str|EXPORT|func|rgb|_425|DateTime|getElement|blue|hsl|Logging|LoggingPane|type|__repr__|_event|while|doc|bind|num|iter|extend|options|style|prototype|seq|EXPORT_OK|Visual|VERSION|_document||_434||replace|forwardCall|StopIteration|use||Math|max|min|join|appendChild|__new__|button|compare|date|key|val|_329|EXPORT_TAGS|update|win|pair|concat|_596|dom|map|req|Deferred|sync|document|base|Error|number|partial|indexOf||instanceof|sig|not|cls|list|fired|left|stop|break|logger|require|0px|window|shift|hsv|split|createElement|_423|callee|continue|substring|provide|_exportSymbols|ccc||_464|||||||||step|pred|_51|__compat__|common|nameFunctions|right|255|_517|case|100|_loggingPane|value|object|callback|TypeError|_251|_246|_113|parentNode|display|_522|parseInt|cssText|wrap|info|isArrayLike|end|match|top|border|depends|args|substr|mouse|code|_519|_443|className|level|err|frac|Date|_135|_85|nodeType|color|height|and|_window|fromRGB|charAt||asHSL|_444|message||||filter||LogMessage|AdapterRegistry|_366|imap|NotFound|locked|counter|_262|_messages|operator|cmp|_165|_161|pairs|arr|_52|setAttribute|computedStyle|compact|_614|_610|div|_576|_572|_observers|splice|_565|_566|_555|scrollTop|page|modifier|white|_541|fromHSL|_539|_535|_528|clone|parseFloat|_505|pre|_499|_497|_427|createTextNode|_446|attributeArray|_388|_379|updateNodeAttributes|_341|_326||box|errback|results|paused|chain|_285||ofs||NamedError|_175|_147|_122|_83|_54|_17|childNodes|_619|blend|defaultView|_574|_569|idx|_562|must|_554|_specialKeys|body|Coordinates|registerComparator|_521|_516|hex|mid|_478|width|loggingPane|LogLevel|nwin|head|url|setElementClass|callStack|path|dest|_359|boolean|register|Dimensions|DeferredLock|_313|addCallback|_310|waiting|onreadystatechange|_290|LOCALE|year|printfire|_214|log|_213|_211|pos|_155|_153||typeMatcher|listMinMax|_114|_40|itr|typ|_19|_634|_625|bottom|corners|_hasString|_612|_608|_595|1px|DIV|firstChild|innerHTML|padding|getPropertyValue|asRGB|connect|_disconnect|_559|middle|which|clientY|scrollLeft|clientX|client|charCode|relatedTarget|event|toColorPart|clampColorComponent|_537|_534|toFixed|_468|buildAndApplyFilter|_442|_441|_440|_439|position|_463|_447|removeChild|_449|uid|_428|_426|compliant|attributes|_422|_409|_412|_400|_395|_390|_389|_377|_375|_363|attr|ctx|repeat|_340|_339|isNotEmpty|_335|_333|opera|DeferredList|ret|_309|silentlyCancelled|canceller|_nextId|Array|_293|XMLHttpRequest|chained|_281|tail|_252|_225|msec|day|month|iso|Logger|_208|listeners|_200|_198|_194|_196|reduce|range|_169|_162|truth|registerRepr|_121|_70|_58|_56|_47|_45|_41|_13|_1|script|text|uri|documentElement|_630|_629|isTransparent|borderRightWidth|borderLeftWidth|marginRight|marginLeft|_602|_599|numSlices|solid|_597|block|SPAN|_579|fromString|offsetParent|signal|disconnectAll|disconnect|_570|_563|_557|preventDefault|stopPropagation|clientTop|clientLeft|pageY|pageX|keyCode|meta|ctrl|alt|target|black|_532|_524|floor|_513|_512|_500|_495|toLowerCase|_487|DEBUG|INFO|WARNING|FATAL|ERROR|colorTable|logFont|closed|inline|onclick|_438|_437|_445|RegExp|_452|space|title|updatetree|||||withDocument|withWindow||setDisplayForElement|none|renames|forEach|domConverters|escapeHTML|addElementClass|removeElementClass|once|_378|_380|_376|appendChildNodes|coerceToDOM|_355|opt|clientWidth|opacity|GenericError|fail|resultList|_307|_301|_fire|can|addCallbacks|_resback|percent|decimal|separator|twoDigitFloat|_274|_273|_264|_257|_250|_249|_254|_248|_243|_242|fmt|_240|_245|getTime|sec|hour|_209|slice|_206|iterateNextIter|registerIteratorFactory|arrayLikeIter|iteratorRegistry|takewhile|ifilterfalse|ifilter|_181|_176|_168|_166|_159|_tee|deque|arg|fun|jsonRegistry|reprString|reprRegistry|comparatorRegistry|urlEncode|_110|_108|cur|_95|_87|_71|im_preargs||_53|_57|_46|present|like|array|Argument|_15|_12|_632|_631|_633|SUBMODULES|only|_628|_627|_626|roundElement|_624|getElementsByTagAndClassName|_RoundCorners|_613|_whichSideBottom|_whichSideTop|_609|_605|_606|transparent|_borderColor|_604|_603|_601|_600|bgColor|fromElement|_594|_592|backgroundColor|_createCornerSlice|_createCorner|_590|_589|_587|_586|_581|_578|_577|currentDocument|fromBackground|errors|_568|_564||sigs|flattenArguments|_561|findIdentical|_560|_558||_556|attachEvent|addEventListener|funcOrStr|Event||_548|fromCharCode|String|_specialMacKeys|any|green|_namedColors|hsvToRGB|rgbToHSV|hslToRGB|rgbToHSL|_542|01|360|_fromColorString|_540|_536|_538|_529|_523|_518|fromComputedStyle|_511|_507|_508|_506|_501|fromHexString|_498|_496|_486|__class__|createLoggingPane|_459|_461|font|_462|_430|_435|1000|index|_460|getMessages|removeListener|_451||_457|_450|infore|_448|_456|logDebug|offsetHeight|span|input|_436|TR||HTML|open|alert|currentWindow|swapDOM|SELECT|FORM|INPUT|createDOMFunc|ignoreAttr|_421|call|_417|_410|_415|nodeName|_414|_413|emitHTML|good|_406|_399|_397|_393|_392|addLoadEvent|addToCallStack|_387|_386|_381|_382|_383|_373|_372|_369|createDOM|_365|Function|_360|_362|_358|_344|nodeWalk|formContents|_337|_338|_334|_332|offsetTop|offsetLeft|visibility|parentElement|||XMLHttpRequestError|BrowserComplianceError|CancelledError|AlreadyCalledError|evalJSONRequest|sendXMLHttpRequest|wait|doSimpleXMLHttpRequest|getXMLHttpRequest|succeed|_312|finishedCount|_308|_cbDeferred|_303|_297|queryString|_nothing|_289|XMLHTTP|ActiveXObject|eval|_284|_check|error|_279|default|rstrip|lstrip|formatLocale|roundToFixed|truncToFixed|_276|pow|_272|_271|_270|sign|_265|_263|tmp|_238|_232|toISODate|toISOTime|getFullYear|getDate|getMonth|_230|_padTwo|_228|useNativeConsole|_212|compareLogMessage|isLogMessage|unshift|_207||maxSize|_202|_199|logLevelAtLeast|console|hasIterateNext|iterateNext|arrayLike|groupby||exhaust|tee|dropwhile|applymap||islice|izip|cycle|count||_189|_188|_183|_185|_184|_186|_187|_182|identity|fetch|_180|_177|listMin|reprNumber|reprArrayLike|compareArrayLike|compareDateLike|isDateLike|findValue|_128|__export__|keyComparator|_124|_118|_93|_94|_90|_88|_84|_77|_68|_67|_66|_65|_60|im_func|_55|im_self|_48|_44|_42|_39|_36|_33|_27|_26|_25|_22|_24|_20|javascript|write|getAttribute||org|www|http|getElementsByTagName|roundClass|_623|_622|_621|_620|_isBottomRounded|_isTopRounded|_borderSize|_618|_617|_616|_615|_marginSize|_611|_setBorder|_607|_setMargin|blendedColor|_598|__unstable__wrapElement|fromParent|_setOptions|2px|borderColor|_593|hidden|overflow|_591|_588|_roundBottomCorners|_585|_roundTopCorners|_584|_583|_582|_580|_renderBorder|_roundCornersImpl|getComputedStyle|_doWrap|_571|_unloadCache|onunload|detachEvent|removeEventListener|_listener|objOrFunc|_552||_551|_549|onload|delete|112|KEY_F|KEY_|MINUS|KEY_SEMICOLON|KEY_DELETE|KEY_INSERT|KEY_ARROW_DOWN|KEY_ARROW_RIGHT|KEY_ARROW_UP||KEY_ARROW_LEFT|KEY_HOME|KEY_END|KEY_PAGE_DOWN|KEY_PAGE_UP|KEY_ENTER|KEY_NUM_PAD_CLEAR|63236|mousemove|contextmenu|click|mouseout|mouseover|_src|yellow|708090|purple|orange|ff00ff|magenta|778899|d3d3d3|808080|gray|696969|2f4f4f|darkred|a9a9a9|00ffff|cyan|brown|_547|_546||||compareRGB|_545||_543|fromHSLString|fromRGBString|round|_533|_hslValue|switch|background|_503|_504||fromName|_488|col|toRGBString|_hexString|_rgbString|_hslString|toPrecision|isLight||_481|_477|_476|_475|_474|_473|_469|_466|closePane|_458|onkeypress|_454|addListener|_455|close|test|scrollHeight|option|word|moz|_431|getElementById|html|pop|200|_|removeElement|showElement|hideElement|CANVAS|STRONG|FIELDSET|LEGEND|OPTGROUP|OPTION|TEXTAREA|LABEL|HR|BR|H3|H2|H1|PRE|TT|BUTTON|IMG|TH||TABLE||TFOOT|THEAD|TBODY|TD|LI|OL|||UL|checked|class|ignoreAttrFilter||_424|_419|nodeValue|scrapeText|_416|_418|sort|_411|toHTML|_404|hasElementClass|_403|_402|_401|swapElementClass|_398|_394|toggleElementClass|_391|focusOnLoad|_newCallStack|currentStyle|_371|replaceChildNodes|_364|_361|getNodeAttribute|_357|setNodeAttribute|_354|_352|_350|_353|toDOM|_346|_345|registerDOMConverter|selectedIndex|setElementPosition|setElementDimensions|tagName|absolute|getBoxObjectFor|getBoundingClientRect|elementPosition|_325|_324|_322|_323|offsetWidth|elementDimensions|clientHeight|innerWidth|getViewportDimensions|setOpacity|status|_317|deferred|_316|_newNamedError|maybeDeferred||gatherResults|callLater|loadJSONDoc|_311|consumeErrors|fireOnOneErrback|fireOnOneCallback|addErrback|_305|_304|_306|unlocked|release|_300|_299|_298|_296|_xhr_onreadystatechange|_xhr_canceller|304|responseText|Msxml2|addBoth|_pause|_continue|result|the|are|they|instances|_unpause|cancel|_280|_278|en_US|strip|percentFormat|twoDigitAverage|numberFormatter|_277|_275|isNaN|_259|_258|_260|_255|_253|_numberFormatter|_241|_239|_237|_236|_235|_234|_233|_231|toAmericanDate|toPaddedAmericanDate|americanDate|toISOTimestamp|isoTimestamp|isoDate|foot|sep||60000|_221|_isoRegexp|dispatchEvent|createEvent|warning|logWarning|fatal|logFatal|debug|logError|baseLog|_210|getMessageText|logToConsole|dispatchListeners|_204|_203|ident|_201|postError|alertListener|_197|_192|groupby_as_array|iextend|some|reversed|sorted|every|sum|_190|eat|_174|_173|_172|_171|_167|_163|_158|_157|_151|_144|_141||_139|_136|_134||_133|_132|zip|merge|isUndefined|isCallable|listMax|_131|_130|encodeURIComponent||_127|method|parseQueryString|evalJSON|registerJSON|serializeJSON|objMin|objMax|reverseKeyComparator|arrayEqual|objEqual|bindMethods|xfilter|xmap|isEmpty|isNull|isUndefinedOrNull|itemgetter|items|keys|setdefault|_126|_120|decodeURIComponent|_119|len|_109|_107|_104|_105|_101|_102|_98|||_100|_97|_96|_91|json|__json__|_82|_81|_80|_79|_76||_75|_74|_73|_69|_primitives|_64|_63||_62|_61|_59|_wrapDumbFunction|_49|_50|_31|_30|_21|_7|application|MochiKit_|createElementNS|namespaceURI|lastIndexOf|xul|there|gatekeeper|keymaster|mozilla|getElementsComputedStyle|_hasSingleTextChild|borderWidth|borderStyle|borderBottomWidth|borderTopWidth|borderTopStyle|fontSize|paddingBottom|insertBefore|paddingTop|marginBottom|marginTop|_575|property|see|handling|thrown|Multiple|element|||given|123|KEY_NUM_PAD_|105|KEY_APOSTROPHE|222|KEY_RIGHT_SQUARE_BRACKET|221|KEY_REVERSE_SOLIDUS|220|KEY_LEFT_SQUARE_BRACKET||219|KEY_GRAVE_ACCENT|192|KEY_SOLIDUS|191|KEY_FULL_STOP|190|KEY_HYPHEN|189||KEY_COMMA|188|KEY_EQUALS_SIGN|187|186|KEY_SCROLL_LOCK|145|KEY_NUM_LOCK|144|KEY_NUM_PAD_SOLIDUS|111|KEY_NUM_PAD_FULL_STOP|110|KEY_NUM_PAD_HYPHEN|109|KEY_NUM_PAD_PLUS_SIGN|107|KEY_NUM_PAD_ASTERISK|106|KEY_SELECT|KEY_WINDOWS_RIGHT|KEY_WINDOWS_LEFT|KEY_PRINT_SCREEN|KEY_SPACEBAR|KEY_ESCAPE|KEY_CAPS_LOCK|KEY_PAUSE|KEY_ALT|KEY_CTRL|KEY_SHIFT|KEY_TAB|KEY_BACKSPACE|63242|63272|63302|63233|63235|63232|63234|63273|63275|63277|63276|63289|returnValue|cancelBubble|keypress|KEY_UNKNOWN|keyup|keydown|shiftKey|metaKey||ctrlKey|altKey|toElement|srcElement|9acd32||yellowgreen||ffff00|f5f5f5|whitesmoke||ffffff|f5deb3|wheat|ee82ee|violet|40e0d0|turquoise|ff6347|tomato|d8bfd8|thistle|008080|teal|d2b48c|tan|4682b4|steelblue|00ff7f|springgreen|fffafa|snow|slategrey|slategray|6a5acd|slateblue|87ceeb|skyblue|c0c0c0|silver|a0522d|sienna|fff5ee|seashell|2e8b57|seagreen|f4a460|sandybrown|fa8072|salmon|8b4513|saddlebrown|4169e1|royalblue|bc8f8f|rosybrown|ff0000|800080|b0e0e6|powderblue|dda0dd|plum|ffc0cb|pink|cd853f||peru|ffdab9|peachpuff|ffefd5|papayawhip|db7093|palevioletred|afeeee|paleturquoise|98fb98|palegreen|eee8aa||palegoldenrod|da70d6|orchid|ff4500|orangered|ffa500|6b8e23|olivedrab|808000|olive|fdf5e6|oldlace|000080|navy|ffdead|navajowhite|ffe4b5|moccasin|ffe4e1|mistyrose|f5fffa|mintcream|191970|midnightblue|c71585|mediumvioletred|48d1cc|mediumturquoise|00fa9a|mediumspringgreen|7b68ee|mediumslateblue|3cb371|mediumseagreen|9370db|mediumpurple|ba55d3|mediumorchid|0000cd|mediumblue|66cdaa|mediumaquamarine|800000|maroon|faf0e6|linen|32cd32|limegreen|00ff00|lime|ffffe0|lightyellow|b0c4de|lightsteelblue|lightslategrey|lightslategray||87cefa|lightskyblue|20b2aa|lightseagreen|ffa07a|lightsalmon|ffb6c1|lightpink|lightgrey|90ee90|lightgreen|lightgray|fafad2|lightgoldenrodyellow|e0ffff|lightcyan|f08080|lightcoral|add8e6|lightblue|fffacd|lemonchiffon|7cfc00|lawngreen|fff0f5|lavenderblush|e6e6fa|lavender|f0e68c|khaki|fffff0|ivory|4b0082|indigo|cd5c5c|indianred|ff69b4|hotpink|f0fff0|honeydew|grey|adff2f|greenyellow|008000|daa520|goldenrod|ffd700||gold|f8f8ff|ghostwhite|dcdcdc|gainsboro|fuchsia|228b22|forestgreen|fffaf0|floralwhite|b22222|firebrick|1e90ff|dodgerblue|dimgrey|dimgray|00bfff|deepskyblue|ff1493|deeppink|9400d3|darkviolet|00ced1|darkturquoise|darkslategrey|darkslategray|483d8b|darkslateblue|8fbc8f|darkseagreen|e9967a|darksalmon|8b0000|9932cc|darkorchid|ff8c00|darkorange|556b2f|darkolivegreen|8b008b|darkmagenta|bdb76b|darkkhaki|darkgrey|006400|darkgreen|darkgray|b8860b|darkgoldenrod|008b8b|darkcyan|00008b|darkblue|dc143c|crimson|fff8dc|cornsilk|6495ed|cornflowerblue|ff7f50|coral|d2691e||chocolate|7fff00|chartreuse|5f9ea0|cadetblue|deb887|burlywood|a52a2a|8a2be2|blueviolet|0000ff|ffebcd||blanchedalmond|000000|ffe4c4|bisque|f5f5dc|beige|f0ffff|azure|7fffd4|aquamarine|aqua|faebd7|antiquewhite|f0f8ff|aliceblue|lightGray|darkGray|namedColors|blackColor|fromText|whiteColor|_510|_509|PI|rad|deg|transparentColor|_494|_493|_492|fromHSV|_491|_490|_489|asHSV|toHexString|rgba|hsla|toHSLString|isDark|lighterColorWithLevel|darkerColorWithLevel|colorWithLightness|colorWithSaturation|colorWithHue|colorWithAlpha||serif|sans|Verdana||8pt|8em|auto||Close|Clear||Load|Filter||10em||fixed|regex|emergency|line|margin|_Listener|dtd|loose|html4|w3|EN|Transitional|DTD|W3C|PUBLIC|DOCTYPE|blocking|due|debugging|able|Not|resizable|dependent|href|location|_MochiKit_LoggingPane|_429|canvas|strong|fieldset|legend|optgroup|select|form|textarea|label|img|table|tfoot|thead|tbody|htmlFor||useMap|usemap|defaultChecked|hasChildNodes|quot|amp|_405|focus|replaceChild|checkbox||radio|_win|BODY||safari|version|userAgent|navigator|innerHeight|alpha|khtml|Tried|acquire|clearTimeout|setTimeout|GET|ignore|send|abort|failed|Request|readyState|support|does|Browser|Microsoft|_288|_287|used|Deferreds|Chained|success|unfired|fr_FR|de_DE|00|abs|search|pattern|Invalid|getTimezoneOffset|getSeconds|getMinutes|getHours|UTC|3600000|initEvent|Events|debuggingBookmarklet|MESSAGES|LAST|_205|clear|ninfo|nlevel|timestamp|reverse|takes|initial|with|sequence|empty|iterable|numbers|dateLike|escape|find|forward|unregister|unescape|Object|compared|item|contains|logor|logand|cle|clt|cge|cgt|cne|ceq|zrshift|rshift|lshift|xor|mul|mod|sub|add|neg|lognot|_9|_2'.split('|'),0,{}) + + +/* + * jQuery 1.2.1 - New Wave Javascript + * + * Copyright (c) 2007 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $ + * $Rev: 3353 $ + */ + +var decompressedJQuery = function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(G(){9(1m E!="W")H w=E;H E=18.15=G(a,b){I 6 7u E?6.5N(a,b):1u E(a,b)};9(1m $!="W")H D=$;18.$=E;H u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;E.1b=E.3A={5N:G(c,a){c=c||U;9(1m c=="1M"){H m=u.2S(c);9(m&&(m[1]||!a)){9(m[1])c=E.4D([m[1]],a);J{H b=U.3S(m[3]);9(b)9(b.22!=m[3])I E().1Y(c);J{6[0]=b;6.K=1;I 6}J c=[]}}J I 1u E(a).1Y(c)}J 9(E.1n(c))I 1u E(U)[E.1b.2d?"2d":"39"](c);I 6.6v(c.1c==1B&&c||(c.4c||c.K&&c!=18&&!c.1y&&c[0]!=W&&c[0].1y)&&E.2h(c)||[c])},4c:"1.2.1",7Y:G(){I 6.K},K:0,21:G(a){I a==W?E.2h(6):6[a]},2o:G(a){H b=E(a);b.4Y=6;I b},6v:G(a){6.K=0;1B.3A.1a.16(6,a);I 6},N:G(a,b){I E.N(6,a,b)},4I:G(a){H b=-1;6.N(G(i){9(6==a)b=i});I b},1x:G(f,d,e){H c=f;9(f.1c==3X)9(d==W)I 6.K&&E[e||"1x"](6[0],f)||W;J{c={};c[f]=d}I 6.N(G(a){L(H b 1i c)E.1x(e?6.R:6,b,E.1e(6,c[b],e,a,b))})},17:G(b,a){I 6.1x(b,a,"3C")},2g:G(e){9(1m e!="5i"&&e!=S)I 6.4n().3g(U.6F(e));H t="";E.N(e||6,G(){E.N(6.3j,G(){9(6.1y!=8)t+=6.1y!=1?6.6x:E.1b.2g([6])})});I t},5m:G(b){9(6[0])E(b,6[0].3H).6u().3d(6[0]).1X(G(){H a=6;1W(a.1w)a=a.1w;I a}).3g(6);I 6},8m:G(a){I 6.N(G(){E(6).6q().5m(a)})},8d:G(a){I 6.N(G(){E(6).5m(a)})},3g:G(){I 6.3z(1q,Q,1,G(a){6.58(a)})},6j:G(){I 6.3z(1q,Q,-1,G(a){6.3d(a,6.1w)})},6g:G(){I 6.3z(1q,P,1,G(a){6.12.3d(a,6)})},50:G(){I 6.3z(1q,P,-1,G(a){6.12.3d(a,6.2q)})},2D:G(){I 6.4Y||E([])},1Y:G(t){H b=E.1X(6,G(a){I E.1Y(t,a)});I 6.2o(/[^+>] [^+>]/.14(t)||t.1g("..")>-1?E.4V(b):b)},6u:G(e){H f=6.1X(G(){I 6.67?E(6.67)[0]:6.4R(Q)});H d=f.1Y("*").4O().N(G(){9(6[F]!=W)6[F]=S});9(e===Q)6.1Y("*").4O().N(G(i){H c=E.M(6,"2P");L(H a 1i c)L(H b 1i c[a])E.1j.1f(d[i],a,c[a][b],c[a][b].M)});I f},1E:G(t){I 6.2o(E.1n(t)&&E.2W(6,G(b,a){I t.16(b,[a])})||E.3m(t,6))},5V:G(t){I 6.2o(t.1c==3X&&E.3m(t,6,Q)||E.2W(6,G(a){I(t.1c==1B||t.4c)?E.2A(a,t)<0:a!=t}))},1f:G(t){I 6.2o(E.1R(6.21(),t.1c==3X?E(t).21():t.K!=W&&(!t.11||E.11(t,"2Y"))?t:[t]))},3t:G(a){I a?E.3m(a,6).K>0:P},7c:G(a){I 6.3t("."+a)},3i:G(b){9(b==W){9(6.K){H c=6[0];9(E.11(c,"24")){H e=c.4Z,a=[],Y=c.Y,2G=c.O=="24-2G";9(e<0)I S;L(H i=2G?e:0,33=2G?e+1:Y.K;i<33;i++){H d=Y[i];9(d.26){H b=E.V.1h&&!d.9V["1Q"].9L?d.2g:d.1Q;9(2G)I b;a.1a(b)}}I a}J I 6[0].1Q.1p(/\\r/g,"")}}J I 6.N(G(){9(b.1c==1B&&/4k|5j/.14(6.O))6.2Q=(E.2A(6.1Q,b)>=0||E.2A(6.2H,b)>=0);J 9(E.11(6,"24")){H a=b.1c==1B?b:[b];E("9h",6).N(G(){6.26=(E.2A(6.1Q,a)>=0||E.2A(6.2g,a)>=0)});9(!a.K)6.4Z=-1}J 6.1Q=b})},4o:G(a){I a==W?(6.K?6[0].3O:S):6.4n().3g(a)},6H:G(a){I 6.50(a).28()},6E:G(i){I 6.2J(i,i+1)},2J:G(){I 6.2o(1B.3A.2J.16(6,1q))},1X:G(b){I 6.2o(E.1X(6,G(a,i){I b.2O(a,i,a)}))},4O:G(){I 6.1f(6.4Y)},3z:G(f,d,g,e){H c=6.K>1,a;I 6.N(G(){9(!a){a=E.4D(f,6.3H);9(g<0)a.8U()}H b=6;9(d&&E.11(6,"1I")&&E.11(a[0],"4m"))b=6.4l("1K")[0]||6.58(U.5B("1K"));E.N(a,G(){H a=c?6.4R(Q):6;9(!5A(0,a))e.2O(b,a)})})}};G 5A(i,b){H a=E.11(b,"1J");9(a){9(b.3k)E.3G({1d:b.3k,3e:P,1V:"1J"});J E.5f(b.2g||b.6s||b.3O||"");9(b.12)b.12.3b(b)}J 9(b.1y==1)E("1J",b).N(5A);I a}E.1k=E.1b.1k=G(){H c=1q[0]||{},a=1,2c=1q.K,5e=P;9(c.1c==8o){5e=c;c=1q[1]||{}}9(2c==1){c=6;a=0}H b;L(;a<2c;a++)9((b=1q[a])!=S)L(H i 1i b){9(c==b[i])6r;9(5e&&1m b[i]==\'5i\'&&c[i])E.1k(c[i],b[i]);J 9(b[i]!=W)c[i]=b[i]}I c};H F="15"+(1u 3D()).3B(),6p=0,5c={};E.1k({8a:G(a){18.$=D;9(a)18.15=w;I E},1n:G(a){I!!a&&1m a!="1M"&&!a.11&&a.1c!=1B&&/G/i.14(a+"")},4a:G(a){I a.2V&&!a.1G||a.37&&a.3H&&!a.3H.1G},5f:G(a){a=E.36(a);9(a){9(18.6l)18.6l(a);J 9(E.V.1N)18.56(a,0);J 3w.2O(18,a)}},11:G(b,a){I b.11&&b.11.27()==a.27()},1L:{},M:G(c,d,b){c=c==18?5c:c;H a=c[F];9(!a)a=c[F]=++6p;9(d&&!E.1L[a])E.1L[a]={};9(b!=W)E.1L[a][d]=b;I d?E.1L[a][d]:a},30:G(c,b){c=c==18?5c:c;H a=c[F];9(b){9(E.1L[a]){2E E.1L[a][b];b="";L(b 1i E.1L[a])1T;9(!b)E.30(c)}}J{2a{2E c[F]}29(e){9(c.53)c.53(F)}2E E.1L[a]}},N:G(a,b,c){9(c){9(a.K==W)L(H i 1i a)b.16(a[i],c);J L(H i=0,48=a.K;i<48;i++)9(b.16(a[i],c)===P)1T}J{9(a.K==W)L(H i 1i a)b.2O(a[i],i,a[i]);J L(H i=0,48=a.K,3i=a[0];i<48&&b.2O(3i,i,3i)!==P;3i=a[++i]){}}I a},1e:G(c,b,d,e,a){9(E.1n(b))b=b.2O(c,[e]);H f=/z-?4I|7T-?7Q|1r|69|7P-?1H/i;I b&&b.1c==4W&&d=="3C"&&!f.14(a)?b+"2T":b},1o:{1f:G(b,c){E.N((c||"").2l(/\\s+/),G(i,a){9(!E.1o.3K(b.1o,a))b.1o+=(b.1o?" ":"")+a})},28:G(b,c){b.1o=c!=W?E.2W(b.1o.2l(/\\s+/),G(a){I!E.1o.3K(c,a)}).66(" "):""},3K:G(t,c){I E.2A(c,(t.1o||t).3s().2l(/\\s+/))>-1}},2k:G(e,o,f){L(H i 1i o){e.R["3r"+i]=e.R[i];e.R[i]=o[i]}f.16(e,[]);L(H i 1i o)e.R[i]=e.R["3r"+i]},17:G(e,p){9(p=="1H"||p=="2N"){H b={},42,41,d=["7J","7I","7G","7F"];E.N(d,G(){b["7C"+6]=0;b["7B"+6+"5Z"]=0});E.2k(e,b,G(){9(E(e).3t(\':3R\')){42=e.7A;41=e.7w}J{e=E(e.4R(Q)).1Y(":4k").5W("2Q").2D().17({4C:"1P",2X:"4F",19:"2Z",7o:"0",1S:"0"}).5R(e.12)[0];H a=E.17(e.12,"2X")||"3V";9(a=="3V")e.12.R.2X="7g";42=e.7e;41=e.7b;9(a=="3V")e.12.R.2X="3V";e.12.3b(e)}});I p=="1H"?42:41}I E.3C(e,p)},3C:G(h,j,i){H g,2w=[],2k=[];G 3n(a){9(!E.V.1N)I P;H b=U.3o.3Z(a,S);I!b||b.4y("3n")==""}9(j=="1r"&&E.V.1h){g=E.1x(h.R,"1r");I g==""?"1":g}9(j.1t(/4u/i))j=y;9(!i&&h.R[j])g=h.R[j];J 9(U.3o&&U.3o.3Z){9(j.1t(/4u/i))j="4u";j=j.1p(/([A-Z])/g,"-$1").2p();H d=U.3o.3Z(h,S);9(d&&!3n(h))g=d.4y(j);J{L(H a=h;a&&3n(a);a=a.12)2w.4w(a);L(a=0;a<2w.K;a++)9(3n(2w[a])){2k[a]=2w[a].R.19;2w[a].R.19="2Z"}g=j=="19"&&2k[2w.K-1]!=S?"2s":U.3o.3Z(h,S).4y(j)||"";L(a=0;a<2k.K;a++)9(2k[a]!=S)2w[a].R.19=2k[a]}9(j=="1r"&&g=="")g="1"}J 9(h.3Q){H f=j.1p(/\\-(\\w)/g,G(m,c){I c.27()});g=h.3Q[j]||h.3Q[f];9(!/^\\d+(2T)?$/i.14(g)&&/^\\d/.14(g)){H k=h.R.1S;H e=h.4v.1S;h.4v.1S=h.3Q.1S;h.R.1S=g||0;g=h.R.71+"2T";h.R.1S=k;h.4v.1S=e}}I g},4D:G(a,e){H r=[];e=e||U;E.N(a,G(i,d){9(!d)I;9(d.1c==4W)d=d.3s();9(1m d=="1M"){d=d.1p(/(<(\\w+)[^>]*?)\\/>/g,G(m,a,b){I b.1t(/^(70|6Z|6Y|9Q|4t|9N|9K|3a|9G|9E)$/i)?m:a+"></"+b+">"});H s=E.36(d).2p(),1s=e.5B("1s"),2x=[];H c=!s.1g("<9y")&&[1,"<24>","</24>"]||!s.1g("<9w")&&[1,"<6T>","</6T>"]||s.1t(/^<(9u|1K|9t|9r|9p)/)&&[1,"<1I>","</1I>"]||!s.1g("<4m")&&[2,"<1I><1K>","</1K></1I>"]||(!s.1g("<9m")||!s.1g("<9k"))&&[3,"<1I><1K><4m>","</4m></1K></1I>"]||!s.1g("<6Y")&&[2,"<1I><1K></1K><6L>","</6L></1I>"]||E.V.1h&&[1,"1s<1s>","</1s>"]||[0,"",""];1s.3O=c[1]+d+c[2];1W(c[0]--)1s=1s.5p;9(E.V.1h){9(!s.1g("<1I")&&s.1g("<1K")<0)2x=1s.1w&&1s.1w.3j;J 9(c[1]=="<1I>"&&s.1g("<1K")<0)2x=1s.3j;L(H n=2x.K-1;n>=0;--n)9(E.11(2x[n],"1K")&&!2x[n].3j.K)2x[n].12.3b(2x[n]);9(/^\\s/.14(d))1s.3d(e.6F(d.1t(/^\\s*/)[0]),1s.1w)}d=E.2h(1s.3j)}9(0===d.K&&(!E.11(d,"2Y")&&!E.11(d,"24")))I;9(d[0]==W||E.11(d,"2Y")||d.Y)r.1a(d);J r=E.1R(r,d)});I r},1x:G(c,d,a){H e=E.4a(c)?{}:E.5o;9(d=="26"&&E.V.1N)c.12.4Z;9(e[d]){9(a!=W)c[e[d]]=a;I c[e[d]]}J 9(E.V.1h&&d=="R")I E.1x(c.R,"9e",a);J 9(a==W&&E.V.1h&&E.11(c,"2Y")&&(d=="9d"||d=="9a"))I c.97(d).6x;J 9(c.37){9(a!=W){9(d=="O"&&E.11(c,"4t")&&c.12)6G"O 94 93\'t 92 91";c.90(d,a)}9(E.V.1h&&/6C|3k/.14(d)&&!E.4a(c))I c.4p(d,2);I c.4p(d)}J{9(d=="1r"&&E.V.1h){9(a!=W){c.69=1;c.1E=(c.1E||"").1p(/6O\\([^)]*\\)/,"")+(3I(a).3s()=="8S"?"":"6O(1r="+a*6A+")")}I c.1E?(3I(c.1E.1t(/1r=([^)]*)/)[1])/6A).3s():""}d=d.1p(/-([a-z])/8Q,G(z,b){I b.27()});9(a!=W)c[d]=a;I c[d]}},36:G(t){I(t||"").1p(/^\\s+|\\s+$/g,"")},2h:G(a){H r=[];9(1m a!="8P")L(H i=0,2c=a.K;i<2c;i++)r.1a(a[i]);J r=a.2J(0);I r},2A:G(b,a){L(H i=0,2c=a.K;i<2c;i++)9(a[i]==b)I i;I-1},1R:G(a,b){9(E.V.1h){L(H i=0;b[i];i++)9(b[i].1y!=8)a.1a(b[i])}J L(H i=0;b[i];i++)a.1a(b[i]);I a},4V:G(b){H r=[],2f={};2a{L(H i=0,6y=b.K;i<6y;i++){H a=E.M(b[i]);9(!2f[a]){2f[a]=Q;r.1a(b[i])}}}29(e){r=b}I r},2W:G(b,a,c){9(1m a=="1M")a=3w("P||G(a,i){I "+a+"}");H d=[];L(H i=0,4g=b.K;i<4g;i++)9(!c&&a(b[i],i)||c&&!a(b[i],i))d.1a(b[i]);I d},1X:G(c,b){9(1m b=="1M")b=3w("P||G(a){I "+b+"}");H d=[];L(H i=0,4g=c.K;i<4g;i++){H a=b(c[i],i);9(a!==S&&a!=W){9(a.1c!=1B)a=[a];d=d.8M(a)}}I d}});H v=8K.8I.2p();E.V={4s:(v.1t(/.+(?:8F|8E|8C|8B)[\\/: ]([\\d.]+)/)||[])[1],1N:/6w/.14(v),34:/34/.14(v),1h:/1h/.14(v)&&!/34/.14(v),35:/35/.14(v)&&!/(8z|6w)/.14(v)};H y=E.V.1h?"4h":"5h";E.1k({5g:!E.V.1h||U.8y=="8x",4h:E.V.1h?"4h":"5h",5o:{"L":"8w","8v":"1o","4u":y,5h:y,4h:y,3O:"3O",1o:"1o",1Q:"1Q",3c:"3c",2Q:"2Q",8u:"8t",26:"26",8s:"8r"}});E.N({1D:"a.12",8q:"15.4e(a,\'12\')",8p:"15.2I(a,2,\'2q\')",8n:"15.2I(a,2,\'4d\')",8l:"15.4e(a,\'2q\')",8k:"15.4e(a,\'4d\')",8j:"15.5d(a.12.1w,a)",8i:"15.5d(a.1w)",6q:"15.11(a,\'8h\')?a.8f||a.8e.U:15.2h(a.3j)"},G(i,n){E.1b[i]=G(a){H b=E.1X(6,n);9(a&&1m a=="1M")b=E.3m(a,b);I 6.2o(E.4V(b))}});E.N({5R:"3g",8c:"6j",3d:"6g",8b:"50",89:"6H"},G(i,n){E.1b[i]=G(){H a=1q;I 6.N(G(){L(H j=0,2c=a.K;j<2c;j++)E(a[j])[n](6)})}});E.N({5W:G(a){E.1x(6,a,"");6.53(a)},88:G(c){E.1o.1f(6,c)},87:G(c){E.1o.28(6,c)},86:G(c){E.1o[E.1o.3K(6,c)?"28":"1f"](6,c)},28:G(a){9(!a||E.1E(a,[6]).r.K){E.30(6);6.12.3b(6)}},4n:G(){E("*",6).N(G(){E.30(6)});1W(6.1w)6.3b(6.1w)}},G(i,n){E.1b[i]=G(){I 6.N(n,1q)}});E.N(["85","5Z"],G(i,a){H n=a.2p();E.1b[n]=G(h){I 6[0]==18?E.V.1N&&3y["84"+a]||E.5g&&38.33(U.2V["5a"+a],U.1G["5a"+a])||U.1G["5a"+a]:6[0]==U?38.33(U.1G["6n"+a],U.1G["6m"+a]):h==W?(6.K?E.17(6[0],n):S):6.17(n,h.1c==3X?h:h+"2T")}});H C=E.V.1N&&3x(E.V.4s)<83?"(?:[\\\\w*57-]|\\\\\\\\.)":"(?:[\\\\w\\82-\\81*57-]|\\\\\\\\.)",6k=1u 47("^>\\\\s*("+C+"+)"),6i=1u 47("^("+C+"+)(#)("+C+"+)"),6h=1u 47("^([#.]?)("+C+"*)");E.1k({55:{"":"m[2]==\'*\'||15.11(a,m[2])","#":"a.4p(\'22\')==m[2]",":":{80:"i<m[3]-0",7Z:"i>m[3]-0",2I:"m[3]-0==i",6E:"m[3]-0==i",3v:"i==0",3u:"i==r.K-1",6f:"i%2==0",6e:"i%2","3v-46":"a.12.4l(\'*\')[0]==a","3u-46":"15.2I(a.12.5p,1,\'4d\')==a","7X-46":"!15.2I(a.12.5p,2,\'4d\')",1D:"a.1w",4n:"!a.1w",7W:"(a.6s||a.7V||15(a).2g()||\'\').1g(m[3])>=0",3R:\'"1P"!=a.O&&15.17(a,"19")!="2s"&&15.17(a,"4C")!="1P"\',1P:\'"1P"==a.O||15.17(a,"19")=="2s"||15.17(a,"4C")=="1P"\',7U:"!a.3c",3c:"a.3c",2Q:"a.2Q",26:"a.26||15.1x(a,\'26\')",2g:"\'2g\'==a.O",4k:"\'4k\'==a.O",5j:"\'5j\'==a.O",54:"\'54\'==a.O",52:"\'52\'==a.O",51:"\'51\'==a.O",6d:"\'6d\'==a.O",6c:"\'6c\'==a.O",2r:\'"2r"==a.O||15.11(a,"2r")\',4t:"/4t|24|6b|2r/i.14(a.11)",3K:"15.1Y(m[3],a).K",7S:"/h\\\\d/i.14(a.11)",7R:"15.2W(15.32,G(1b){I a==1b.T;}).K"}},6a:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1u 47("^([:.#]*)("+C+"+)")],3m:G(a,c,b){H d,2b=[];1W(a&&a!=d){d=a;H f=E.1E(a,c,b);a=f.t.1p(/^\\s*,\\s*/,"");2b=b?c=f.r:E.1R(2b,f.r)}I 2b},1Y:G(t,o){9(1m t!="1M")I[t];9(o&&!o.1y)o=S;o=o||U;H d=[o],2f=[],3u;1W(t&&3u!=t){H r=[];3u=t;t=E.36(t);H l=P;H g=6k;H m=g.2S(t);9(m){H p=m[1].27();L(H i=0;d[i];i++)L(H c=d[i].1w;c;c=c.2q)9(c.1y==1&&(p=="*"||c.11.27()==p.27()))r.1a(c);d=r;t=t.1p(g,"");9(t.1g(" ")==0)6r;l=Q}J{g=/^([>+~])\\s*(\\w*)/i;9((m=g.2S(t))!=S){r=[];H p=m[2],1R={};m=m[1];L(H j=0,31=d.K;j<31;j++){H n=m=="~"||m=="+"?d[j].2q:d[j].1w;L(;n;n=n.2q)9(n.1y==1){H h=E.M(n);9(m=="~"&&1R[h])1T;9(!p||n.11.27()==p.27()){9(m=="~")1R[h]=Q;r.1a(n)}9(m=="+")1T}}d=r;t=E.36(t.1p(g,""));l=Q}}9(t&&!l){9(!t.1g(",")){9(o==d[0])d.44();2f=E.1R(2f,d);r=d=[o];t=" "+t.68(1,t.K)}J{H k=6i;H m=k.2S(t);9(m){m=[0,m[2],m[3],m[1]]}J{k=6h;m=k.2S(t)}m[2]=m[2].1p(/\\\\/g,"");H f=d[d.K-1];9(m[1]=="#"&&f&&f.3S&&!E.4a(f)){H q=f.3S(m[2]);9((E.V.1h||E.V.34)&&q&&1m q.22=="1M"&&q.22!=m[2])q=E(\'[@22="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.11(q,m[3]))?[q]:[]}J{L(H i=0;d[i];i++){H a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];9(a=="*"&&d[i].11.2p()=="5i")a="3a";r=E.1R(r,d[i].4l(a))}9(m[1]==".")r=E.4X(r,m[2]);9(m[1]=="#"){H e=[];L(H i=0;r[i];i++)9(r[i].4p("22")==m[2]){e=[r[i]];1T}r=e}d=r}t=t.1p(k,"")}}9(t){H b=E.1E(t,r);d=r=b.r;t=E.36(b.t)}}9(t)d=[];9(d&&o==d[0])d.44();2f=E.1R(2f,d);I 2f},4X:G(r,m,a){m=" "+m+" ";H c=[];L(H i=0;r[i];i++){H b=(" "+r[i].1o+" ").1g(m)>=0;9(!a&&b||a&&!b)c.1a(r[i])}I c},1E:G(t,r,h){H d;1W(t&&t!=d){d=t;H p=E.6a,m;L(H i=0;p[i];i++){m=p[i].2S(t);9(m){t=t.7O(m[0].K);m[2]=m[2].1p(/\\\\/g,"");1T}}9(!m)1T;9(m[1]==":"&&m[2]=="5V")r=E.1E(m[3],r,Q).r;J 9(m[1]==".")r=E.4X(r,m[2],h);J 9(m[1]=="["){H g=[],O=m[3];L(H i=0,31=r.K;i<31;i++){H a=r[i],z=a[E.5o[m[2]]||m[2]];9(z==S||/6C|3k|26/.14(m[2]))z=E.1x(a,m[2])||\'\';9((O==""&&!!z||O=="="&&z==m[5]||O=="!="&&z!=m[5]||O=="^="&&z&&!z.1g(m[5])||O=="$="&&z.68(z.K-m[5].K)==m[5]||(O=="*="||O=="~=")&&z.1g(m[5])>=0)^h)g.1a(a)}r=g}J 9(m[1]==":"&&m[2]=="2I-46"){H e={},g=[],14=/(\\d*)n\\+?(\\d*)/.2S(m[3]=="6f"&&"2n"||m[3]=="6e"&&"2n+1"||!/\\D/.14(m[3])&&"n+"+m[3]||m[3]),3v=(14[1]||1)-0,d=14[2]-0;L(H i=0,31=r.K;i<31;i++){H j=r[i],12=j.12,22=E.M(12);9(!e[22]){H c=1;L(H n=12.1w;n;n=n.2q)9(n.1y==1)n.4U=c++;e[22]=Q}H b=P;9(3v==1){9(d==0||j.4U==d)b=Q}J 9((j.4U+d)%3v==0)b=Q;9(b^h)g.1a(j)}r=g}J{H f=E.55[m[1]];9(1m f!="1M")f=E.55[m[1]][m[2]];f=3w("P||G(a,i){I "+f+"}");r=E.2W(r,f,h)}}I{r:r,t:t}},4e:G(b,c){H d=[];H a=b[c];1W(a&&a!=U){9(a.1y==1)d.1a(a);a=a[c]}I d},2I:G(a,e,c,b){e=e||1;H d=0;L(;a;a=a[c])9(a.1y==1&&++d==e)1T;I a},5d:G(n,a){H r=[];L(;n;n=n.2q){9(n.1y==1&&(!a||n!=a))r.1a(n)}I r}});E.1j={1f:G(g,e,c,h){9(E.V.1h&&g.4j!=W)g=18;9(!c.2u)c.2u=6.2u++;9(h!=W){H d=c;c=G(){I d.16(6,1q)};c.M=h;c.2u=d.2u}H i=e.2l(".");e=i[0];c.O=i[1];H b=E.M(g,"2P")||E.M(g,"2P",{});H f=E.M(g,"2t",G(){H a;9(1m E=="W"||E.1j.4T)I a;a=E.1j.2t.16(g,1q);I a});H j=b[e];9(!j){j=b[e]={};9(g.4S)g.4S(e,f,P);J g.7N("43"+e,f)}j[c.2u]=c;6.1Z[e]=Q},2u:1,1Z:{},28:G(d,c,b){H e=E.M(d,"2P"),2L,4I;9(1m c=="1M"){H a=c.2l(".");c=a[0]}9(e){9(c&&c.O){b=c.4Q;c=c.O}9(!c){L(c 1i e)6.28(d,c)}J 9(e[c]){9(b)2E e[c][b.2u];J L(b 1i e[c])9(!a[1]||e[c][b].O==a[1])2E e[c][b];L(2L 1i e[c])1T;9(!2L){9(d.4P)d.4P(c,E.M(d,"2t"),P);J d.7M("43"+c,E.M(d,"2t"));2L=S;2E e[c]}}L(2L 1i e)1T;9(!2L){E.30(d,"2P");E.30(d,"2t")}}},1F:G(d,b,e,c,f){b=E.2h(b||[]);9(!e){9(6.1Z[d])E("*").1f([18,U]).1F(d,b)}J{H a,2L,1b=E.1n(e[d]||S),4N=!b[0]||!b[0].2M;9(4N)b.4w(6.4M({O:d,2m:e}));b[0].O=d;9(E.1n(E.M(e,"2t")))a=E.M(e,"2t").16(e,b);9(!1b&&e["43"+d]&&e["43"+d].16(e,b)===P)a=P;9(4N)b.44();9(f&&f.16(e,b)===P)a=P;9(1b&&c!==P&&a!==P&&!(E.11(e,\'a\')&&d=="4L")){6.4T=Q;e[d]()}6.4T=P}I a},2t:G(d){H a;d=E.1j.4M(d||18.1j||{});H b=d.O.2l(".");d.O=b[0];H c=E.M(6,"2P")&&E.M(6,"2P")[d.O],3q=1B.3A.2J.2O(1q,1);3q.4w(d);L(H j 1i c){3q[0].4Q=c[j];3q[0].M=c[j].M;9(!b[1]||c[j].O==b[1]){H e=c[j].16(6,3q);9(a!==P)a=e;9(e===P){d.2M();d.3p()}}}9(E.V.1h)d.2m=d.2M=d.3p=d.4Q=d.M=S;I a},4M:G(c){H a=c;c=E.1k({},a);c.2M=G(){9(a.2M)a.2M();a.7L=P};c.3p=G(){9(a.3p)a.3p();a.7K=Q};9(!c.2m&&c.65)c.2m=c.65;9(E.V.1N&&c.2m.1y==3)c.2m=a.2m.12;9(!c.4K&&c.4J)c.4K=c.4J==c.2m?c.7H:c.4J;9(c.64==S&&c.63!=S){H e=U.2V,b=U.1G;c.64=c.63+(e&&e.2R||b.2R||0);c.7E=c.7D+(e&&e.2B||b.2B||0)}9(!c.3Y&&(c.61||c.60))c.3Y=c.61||c.60;9(!c.5F&&c.5D)c.5F=c.5D;9(!c.3Y&&c.2r)c.3Y=(c.2r&1?1:(c.2r&2?3:(c.2r&4?2:0)));I c}};E.1b.1k({3W:G(c,a,b){I c=="5Y"?6.2G(c,a,b):6.N(G(){E.1j.1f(6,c,b||a,b&&a)})},2G:G(d,b,c){I 6.N(G(){E.1j.1f(6,d,G(a){E(6).5X(a);I(c||b).16(6,1q)},c&&b)})},5X:G(a,b){I 6.N(G(){E.1j.28(6,a,b)})},1F:G(c,a,b){I 6.N(G(){E.1j.1F(c,a,6,Q,b)})},7x:G(c,a,b){9(6[0])I E.1j.1F(c,a,6[0],P,b)},25:G(){H a=1q;I 6.4L(G(e){6.4H=0==6.4H?1:0;e.2M();I a[6.4H].16(6,[e])||P})},7v:G(f,g){G 4G(e){H p=e.4K;1W(p&&p!=6)2a{p=p.12}29(e){p=6};9(p==6)I P;I(e.O=="4x"?f:g).16(6,[e])}I 6.4x(4G).5U(4G)},2d:G(f){5T();9(E.3T)f.16(U,[E]);J E.3l.1a(G(){I f.16(6,[E])});I 6}});E.1k({3T:P,3l:[],2d:G(){9(!E.3T){E.3T=Q;9(E.3l){E.N(E.3l,G(){6.16(U)});E.3l=S}9(E.V.35||E.V.34)U.4P("5S",E.2d,P);9(!18.7t.K)E(18).39(G(){E("#4E").28()})}}});E.N(("7s,7r,39,7q,6n,5Y,4L,7p,"+"7n,7m,7l,4x,5U,7k,24,"+"51,7j,7i,7h,3U").2l(","),G(i,o){E.1b[o]=G(f){I f?6.3W(o,f):6.1F(o)}});H x=P;G 5T(){9(x)I;x=Q;9(E.V.35||E.V.34)U.4S("5S",E.2d,P);J 9(E.V.1h){U.7f("<7d"+"7y 22=4E 7z=Q "+"3k=//:><\\/1J>");H a=U.3S("4E");9(a)a.62=G(){9(6.2C!="1l")I;E.2d()};a=S}J 9(E.V.1N)E.4B=4j(G(){9(U.2C=="5Q"||U.2C=="1l"){4A(E.4B);E.4B=S;E.2d()}},10);E.1j.1f(18,"39",E.2d)}E.1b.1k({39:G(g,d,c){9(E.1n(g))I 6.3W("39",g);H e=g.1g(" ");9(e>=0){H i=g.2J(e,g.K);g=g.2J(0,e)}c=c||G(){};H f="4z";9(d)9(E.1n(d)){c=d;d=S}J{d=E.3a(d);f="5P"}H h=6;E.3G({1d:g,O:f,M:d,1l:G(a,b){9(b=="1C"||b=="5O")h.4o(i?E("<1s/>").3g(a.40.1p(/<1J(.|\\s)*?\\/1J>/g,"")).1Y(i):a.40);56(G(){h.N(c,[a.40,b,a])},13)}});I 6},7a:G(){I E.3a(6.5M())},5M:G(){I 6.1X(G(){I E.11(6,"2Y")?E.2h(6.79):6}).1E(G(){I 6.2H&&!6.3c&&(6.2Q||/24|6b/i.14(6.11)||/2g|1P|52/i.14(6.O))}).1X(G(i,c){H b=E(6).3i();I b==S?S:b.1c==1B?E.1X(b,G(a,i){I{2H:c.2H,1Q:a}}):{2H:c.2H,1Q:b}}).21()}});E.N("5L,5K,6t,5J,5I,5H".2l(","),G(i,o){E.1b[o]=G(f){I 6.3W(o,f)}});H B=(1u 3D).3B();E.1k({21:G(d,b,a,c){9(E.1n(b)){a=b;b=S}I E.3G({O:"4z",1d:d,M:b,1C:a,1V:c})},78:G(b,a){I E.21(b,S,a,"1J")},77:G(c,b,a){I E.21(c,b,a,"45")},76:G(d,b,a,c){9(E.1n(b)){a=b;b={}}I E.3G({O:"5P",1d:d,M:b,1C:a,1V:c})},75:G(a){E.1k(E.59,a)},59:{1Z:Q,O:"4z",2z:0,5G:"74/x-73-2Y-72",6o:Q,3e:Q,M:S},49:{},3G:G(s){H f,2y=/=(\\?|%3F)/g,1v,M;s=E.1k(Q,s,E.1k(Q,{},E.59,s));9(s.M&&s.6o&&1m s.M!="1M")s.M=E.3a(s.M);9(s.1V=="4b"){9(s.O.2p()=="21"){9(!s.1d.1t(2y))s.1d+=(s.1d.1t(/\\?/)?"&":"?")+(s.4b||"5E")+"=?"}J 9(!s.M||!s.M.1t(2y))s.M=(s.M?s.M+"&":"")+(s.4b||"5E")+"=?";s.1V="45"}9(s.1V=="45"&&(s.M&&s.M.1t(2y)||s.1d.1t(2y))){f="4b"+B++;9(s.M)s.M=s.M.1p(2y,"="+f);s.1d=s.1d.1p(2y,"="+f);s.1V="1J";18[f]=G(a){M=a;1C();1l();18[f]=W;2a{2E 18[f]}29(e){}}}9(s.1V=="1J"&&s.1L==S)s.1L=P;9(s.1L===P&&s.O.2p()=="21")s.1d+=(s.1d.1t(/\\?/)?"&":"?")+"57="+(1u 3D()).3B();9(s.M&&s.O.2p()=="21"){s.1d+=(s.1d.1t(/\\?/)?"&":"?")+s.M;s.M=S}9(s.1Z&&!E.5b++)E.1j.1F("5L");9(!s.1d.1g("8g")&&s.1V=="1J"){H h=U.4l("9U")[0];H g=U.5B("1J");g.3k=s.1d;9(!f&&(s.1C||s.1l)){H j=P;g.9R=g.62=G(){9(!j&&(!6.2C||6.2C=="5Q"||6.2C=="1l")){j=Q;1C();1l();h.3b(g)}}}h.58(g);I}H k=P;H i=18.6X?1u 6X("9P.9O"):1u 6W();i.9M(s.O,s.1d,s.3e);9(s.M)i.5C("9J-9I",s.5G);9(s.5y)i.5C("9H-5x-9F",E.49[s.1d]||"9D, 9C 9B 9A 5v:5v:5v 9z");i.5C("X-9x-9v","6W");9(s.6U)s.6U(i);9(s.1Z)E.1j.1F("5H",[i,s]);H c=G(a){9(!k&&i&&(i.2C==4||a=="2z")){k=Q;9(d){4A(d);d=S}1v=a=="2z"&&"2z"||!E.6S(i)&&"3U"||s.5y&&E.6R(i,s.1d)&&"5O"||"1C";9(1v=="1C"){2a{M=E.6Q(i,s.1V)}29(e){1v="5k"}}9(1v=="1C"){H b;2a{b=i.5s("6P-5x")}29(e){}9(s.5y&&b)E.49[s.1d]=b;9(!f)1C()}J E.5r(s,i,1v);1l();9(s.3e)i=S}};9(s.3e){H d=4j(c,13);9(s.2z>0)56(G(){9(i){i.9q();9(!k)c("2z")}},s.2z)}2a{i.9o(s.M)}29(e){E.5r(s,i,S,e)}9(!s.3e)c();I i;G 1C(){9(s.1C)s.1C(M,1v);9(s.1Z)E.1j.1F("5I",[i,s])}G 1l(){9(s.1l)s.1l(i,1v);9(s.1Z)E.1j.1F("6t",[i,s]);9(s.1Z&&!--E.5b)E.1j.1F("5K")}},5r:G(s,a,b,e){9(s.3U)s.3U(a,b,e);9(s.1Z)E.1j.1F("5J",[a,s,e])},5b:0,6S:G(r){2a{I!r.1v&&9n.9l=="54:"||(r.1v>=6N&&r.1v<9j)||r.1v==6M||E.V.1N&&r.1v==W}29(e){}I P},6R:G(a,c){2a{H b=a.5s("6P-5x");I a.1v==6M||b==E.49[c]||E.V.1N&&a.1v==W}29(e){}I P},6Q:G(r,b){H c=r.5s("9i-O");H d=b=="6K"||!b&&c&&c.1g("6K")>=0;H a=d?r.9g:r.40;9(d&&a.2V.37=="5k")6G"5k";9(b=="1J")E.5f(a);9(b=="45")a=3w("("+a+")");I a},3a:G(a){H s=[];9(a.1c==1B||a.4c)E.N(a,G(){s.1a(3f(6.2H)+"="+3f(6.1Q))});J L(H j 1i a)9(a[j]&&a[j].1c==1B)E.N(a[j],G(){s.1a(3f(j)+"="+3f(6))});J s.1a(3f(j)+"="+3f(a[j]));I s.66("&").1p(/%20/g,"+")}});E.1b.1k({1A:G(b,a){I b?6.1U({1H:"1A",2N:"1A",1r:"1A"},b,a):6.1E(":1P").N(G(){6.R.19=6.3h?6.3h:"";9(E.17(6,"19")=="2s")6.R.19="2Z"}).2D()},1z:G(b,a){I b?6.1U({1H:"1z",2N:"1z",1r:"1z"},b,a):6.1E(":3R").N(G(){6.3h=6.3h||E.17(6,"19");9(6.3h=="2s")6.3h="2Z";6.R.19="2s"}).2D()},6J:E.1b.25,25:G(a,b){I E.1n(a)&&E.1n(b)?6.6J(a,b):a?6.1U({1H:"25",2N:"25",1r:"25"},a,b):6.N(G(){E(6)[E(6).3t(":1P")?"1A":"1z"]()})},9c:G(b,a){I 6.1U({1H:"1A"},b,a)},9b:G(b,a){I 6.1U({1H:"1z"},b,a)},99:G(b,a){I 6.1U({1H:"25"},b,a)},98:G(b,a){I 6.1U({1r:"1A"},b,a)},96:G(b,a){I 6.1U({1r:"1z"},b,a)},95:G(c,a,b){I 6.1U({1r:a},c,b)},1U:G(k,i,h,g){H j=E.6D(i,h,g);I 6[j.3L===P?"N":"3L"](G(){j=E.1k({},j);H f=E(6).3t(":1P"),3y=6;L(H p 1i k){9(k[p]=="1z"&&f||k[p]=="1A"&&!f)I E.1n(j.1l)&&j.1l.16(6);9(p=="1H"||p=="2N"){j.19=E.17(6,"19");j.2U=6.R.2U}}9(j.2U!=S)6.R.2U="1P";j.3M=E.1k({},k);E.N(k,G(c,a){H e=1u E.2j(3y,j,c);9(/25|1A|1z/.14(a))e[a=="25"?f?"1A":"1z":a](k);J{H b=a.3s().1t(/^([+-]=)?([\\d+-.]+)(.*)$/),1O=e.2b(Q)||0;9(b){H d=3I(b[2]),2i=b[3]||"2T";9(2i!="2T"){3y.R[c]=(d||1)+2i;1O=((d||1)/e.2b(Q))*1O;3y.R[c]=1O+2i}9(b[1])d=((b[1]=="-="?-1:1)*d)+1O;e.3N(1O,d,2i)}J e.3N(1O,a,"")}});I Q})},3L:G(a,b){9(E.1n(a)){b=a;a="2j"}9(!a||(1m a=="1M"&&!b))I A(6[0],a);I 6.N(G(){9(b.1c==1B)A(6,a,b);J{A(6,a).1a(b);9(A(6,a).K==1)b.16(6)}})},9f:G(){H a=E.32;I 6.N(G(){L(H i=0;i<a.K;i++)9(a[i].T==6)a.6I(i--,1)}).5n()}});H A=G(b,c,a){9(!b)I;H q=E.M(b,c+"3L");9(!q||a)q=E.M(b,c+"3L",a?E.2h(a):[]);I q};E.1b.5n=G(a){a=a||"2j";I 6.N(G(){H q=A(6,a);q.44();9(q.K)q[0].16(6)})};E.1k({6D:G(b,a,c){H d=b&&b.1c==8Z?b:{1l:c||!c&&a||E.1n(b)&&b,2e:b,3J:c&&a||a&&a.1c!=8Y&&a};d.2e=(d.2e&&d.2e.1c==4W?d.2e:{8X:8W,8V:6N}[d.2e])||8T;d.3r=d.1l;d.1l=G(){E(6).5n();9(E.1n(d.3r))d.3r.16(6)};I d},3J:{6B:G(p,n,b,a){I b+a*p},5q:G(p,n,b,a){I((-38.9s(p*38.8R)/2)+0.5)*a+b}},32:[],2j:G(b,c,a){6.Y=c;6.T=b;6.1e=a;9(!c.3P)c.3P={}}});E.2j.3A={4r:G(){9(6.Y.2F)6.Y.2F.16(6.T,[6.2v,6]);(E.2j.2F[6.1e]||E.2j.2F.6z)(6);9(6.1e=="1H"||6.1e=="2N")6.T.R.19="2Z"},2b:G(a){9(6.T[6.1e]!=S&&6.T.R[6.1e]==S)I 6.T[6.1e];H r=3I(E.3C(6.T,6.1e,a));I r&&r>-8O?r:3I(E.17(6.T,6.1e))||0},3N:G(c,b,e){6.5u=(1u 3D()).3B();6.1O=c;6.2D=b;6.2i=e||6.2i||"2T";6.2v=6.1O;6.4q=6.4i=0;6.4r();H f=6;G t(){I f.2F()}t.T=6.T;E.32.1a(t);9(E.32.K==1){H d=4j(G(){H a=E.32;L(H i=0;i<a.K;i++)9(!a[i]())a.6I(i--,1);9(!a.K)4A(d)},13)}},1A:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1A=Q;6.3N(0,6.2b());9(6.1e=="2N"||6.1e=="1H")6.T.R[6.1e]="8N";E(6.T).1A()},1z:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1z=Q;6.3N(6.2b(),0)},2F:G(){H t=(1u 3D()).3B();9(t>6.Y.2e+6.5u){6.2v=6.2D;6.4q=6.4i=1;6.4r();6.Y.3M[6.1e]=Q;H a=Q;L(H i 1i 6.Y.3M)9(6.Y.3M[i]!==Q)a=P;9(a){9(6.Y.19!=S){6.T.R.2U=6.Y.2U;6.T.R.19=6.Y.19;9(E.17(6.T,"19")=="2s")6.T.R.19="2Z"}9(6.Y.1z)6.T.R.19="2s";9(6.Y.1z||6.Y.1A)L(H p 1i 6.Y.3M)E.1x(6.T.R,p,6.Y.3P[p])}9(a&&E.1n(6.Y.1l))6.Y.1l.16(6.T);I P}J{H n=t-6.5u;6.4i=n/6.Y.2e;6.4q=E.3J[6.Y.3J||(E.3J.5q?"5q":"6B")](6.4i,n,0,1,6.Y.2e);6.2v=6.1O+((6.2D-6.1O)*6.4q);6.4r()}I Q}};E.2j.2F={2R:G(a){a.T.2R=a.2v},2B:G(a){a.T.2B=a.2v},1r:G(a){E.1x(a.T.R,"1r",a.2v)},6z:G(a){a.T.R[a.1e]=a.2v+a.2i}};E.1b.6m=G(){H c=0,3E=0,T=6[0],5t;9(T)8L(E.V){H b=E.17(T,"2X")=="4F",1D=T.12,23=T.23,2K=T.3H,4f=1N&&3x(4s)<8J;9(T.6V){5w=T.6V();1f(5w.1S+38.33(2K.2V.2R,2K.1G.2R),5w.3E+38.33(2K.2V.2B,2K.1G.2B));9(1h){H d=E("4o").17("8H");d=(d=="8G"||E.5g&&3x(4s)>=7)&&2||d;1f(-d,-d)}}J{1f(T.5l,T.5z);1W(23){1f(23.5l,23.5z);9(35&&/^t[d|h]$/i.14(1D.37)||!4f)d(23);9(4f&&!b&&E.17(23,"2X")=="4F")b=Q;23=23.23}1W(1D.37&&!/^1G|4o$/i.14(1D.37)){9(!/^8D|1I-9S.*$/i.14(E.17(1D,"19")))1f(-1D.2R,-1D.2B);9(35&&E.17(1D,"2U")!="3R")d(1D);1D=1D.12}9(4f&&b)1f(-2K.1G.5l,-2K.1G.5z)}5t={3E:3E,1S:c}}I 5t;G d(a){1f(E.17(a,"9T"),E.17(a,"8A"))}G 1f(l,t){c+=3x(l)||0;3E+=3x(t)||0}}})();',62,616,'||||||this|||if|||||||||||||||||||||||||||||||||function|var|return|else|length|for|data|each|type|false|true|style|null|elem|document|browser|undefined||options|||nodeName|parentNode||test|jQuery|apply|css|window|display|push|fn|constructor|url|prop|add|indexOf|msie|in|event|extend|complete|typeof|isFunction|className|replace|arguments|opacity|div|match|new|status|firstChild|attr|nodeType|hide|show|Array|success|parent|filter|trigger|body|height|table|script|tbody|cache|string|safari|start|hidden|value|merge|left|break|animate|dataType|while|map|find|global||get|id|offsetParent|select|toggle|selected|toUpperCase|remove|catch|try|cur|al|ready|duration|done|text|makeArray|unit|fx|swap|split|target||pushStack|toLowerCase|nextSibling|button|none|handle|guid|now|stack|tb|jsre|timeout|inArray|scrollTop|readyState|end|delete|step|one|name|nth|slice|doc|ret|preventDefault|width|call|events|checked|scrollLeft|exec|px|overflow|documentElement|grep|position|form|block|removeData|rl|timers|max|opera|mozilla|trim|tagName|Math|load|param|removeChild|disabled|insertBefore|async|encodeURIComponent|append|oldblock|val|childNodes|src|readyList|multiFilter|color|defaultView|stopPropagation|args|old|toString|is|last|first|eval|parseInt|self|domManip|prototype|getTime|curCSS|Date|top||ajax|ownerDocument|parseFloat|easing|has|queue|curAnim|custom|innerHTML|orig|currentStyle|visible|getElementById|isReady|error|static|bind|String|which|getComputedStyle|responseText|oWidth|oHeight|on|shift|json|child|RegExp|ol|lastModified|isXMLDoc|jsonp|jquery|previousSibling|dir|safari2|el|styleFloat|state|setInterval|radio|getElementsByTagName|tr|empty|html|getAttribute|pos|update|version|input|float|runtimeStyle|unshift|mouseover|getPropertyValue|GET|clearInterval|safariTimer|visibility|clean|__ie_init|absolute|handleHover|lastToggle|index|fromElement|relatedTarget|click|fix|evt|andSelf|removeEventListener|handler|cloneNode|addEventListener|triggered|nodeIndex|unique|Number|classFilter|prevObject|selectedIndex|after|submit|password|removeAttribute|file|expr|setTimeout|_|appendChild|ajaxSettings|client|active|win|sibling|deep|globalEval|boxModel|cssFloat|object|checkbox|parsererror|offsetLeft|wrapAll|dequeue|props|lastChild|swing|handleError|getResponseHeader|results|startTime|00|box|Modified|ifModified|offsetTop|evalScript|createElement|setRequestHeader|ctrlKey|callback|metaKey|contentType|ajaxSend|ajaxSuccess|ajaxError|ajaxStop|ajaxStart|serializeArray|init|notmodified|POST|loaded|appendTo|DOMContentLoaded|bindReady|mouseout|not|removeAttr|unbind|unload|Width|keyCode|charCode|onreadystatechange|clientX|pageX|srcElement|join|outerHTML|substr|zoom|parse|textarea|reset|image|odd|even|before|quickClass|quickID|prepend|quickChild|execScript|offset|scroll|processData|uuid|contents|continue|textContent|ajaxComplete|clone|setArray|webkit|nodeValue|fl|_default|100|linear|href|speed|eq|createTextNode|throw|replaceWith|splice|_toggle|xml|colgroup|304|200|alpha|Last|httpData|httpNotModified|httpSuccess|fieldset|beforeSend|getBoundingClientRect|XMLHttpRequest|ActiveXObject|col|br|abbr|pixelLeft|urlencoded|www|application|ajaxSetup|post|getJSON|getScript|elements|serialize|clientWidth|hasClass|scr|clientHeight|write|relative|keyup|keypress|keydown|change|mousemove|mouseup|mousedown|right|dblclick|resize|focus|blur|frames|instanceof|hover|offsetWidth|triggerHandler|ipt|defer|offsetHeight|border|padding|clientY|pageY|Left|Right|toElement|Bottom|Top|cancelBubble|returnValue|detachEvent|attachEvent|substring|line|weight|animated|header|font|enabled|innerText|contains|only|size|gt|lt|uFFFF|u0128|417|inner|Height|toggleClass|removeClass|addClass|replaceAll|noConflict|insertAfter|prependTo|wrap|contentWindow|contentDocument|http|iframe|children|siblings|prevAll|nextAll|wrapInner|prev|Boolean|next|parents|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|compatible|borderTopWidth|ie|ra|inline|it|rv|medium|borderWidth|userAgent|522|navigator|with|concat|1px|10000|array|ig|PI|NaN|400|reverse|fast|600|slow|Function|Object|setAttribute|changed|be|can|property|fadeTo|fadeOut|getAttributeNode|fadeIn|slideToggle|method|slideUp|slideDown|action|cssText|stop|responseXML|option|content|300|th|protocol|td|location|send|cap|abort|colg|cos|tfoot|thead|With|leg|Requested|opt|GMT|1970|Jan|01|Thu|area|Since|hr|If|Type|Content|meta|specified|open|link|XMLHTTP|Microsoft|img|onload|row|borderLeftWidth|head|attributes'.split('|'),0,{}); + +/* + Copyright (c) 2004-2007, The Dojo Foundation + All Rights Reserved. + + Licensed under the Academic Free License version 2.1 or above OR the + modified BSD license. For more information on Dojo licensing, see: + + http://dojotoolkit.org/community/licensing.shtml +*/ + +/* + This is a compiled version of Dojo, built for deployment and not for + development. To get an editable version, please visit: + + http://dojotoolkit.org + + for documentation and information on getting the source. +*/ + +var decompressedDojo = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(V z=="1k"){(B(){if(V D["1o"]=="1k"){D.1o={}}if((!D["1z"])||(!1z["ca"])){D.1z={}}A cn=["rA","rz","1K","ry","rx","9f","rw","rv","ru","rt","rs","rr","rq","ro","rn","rm"];A i=0,24;1s(24=cn[i++]){if(!1z[24]){1z[24]=B(){}}}if(V D["z"]=="1k"){D.z={}}z.1W=D;A d3={im:U,rl:U,rk:"",rj:"",ri:"",rh:K,rg:U};R(A 8z in d3){if(V 1o[8z]=="1k"){1o[8z]=d3[8z]}}A jK=["rf","rd","rc","rb"];A t;1s(t=jK.3a()){z["is"+t]=U}})();z.8h=1o.8h;z.cY={jJ:0,jI:9,jH:0,jG:"",jF:2V("$ra: r9 $".1f(/[0-9]+/)[0]),2i:B(){4G(z.cY){C jJ+"."+jI+"."+jH+jG+" ("+jF+")"}}};z.d1=B(jE,jD,1V){A 2h=1V||z.1W;R(A i=0,p;2h&&(p=jE[i]);i++){2h=(p in 2h?2h[p]:(jD?2h[p]={}:1k))}C 2h};z.88=B(jC,jA,jB){A d2=jC.1A("."),p=d2.8q(),M=z.d1(d2,K,jB);C(M&&p?(M[p]=jA):1k)};z.6q=B(jz,jy,jx){C z.d1(jz.1A("."),jy,jx)};z.r8=B(jw,M){C!!z.6q(jw,U,M)};z["3u"]=B(d0){C z.1W.3u?z.1W.3u(d0):3u(d0)};z.ia=B(jv,cZ,cX){A 8y="r7: "+jv;if(cZ){8y+=" "+cZ}if(cX){8y+=" -- r6 be r5 in cY: "+cX}1z.1K(8y)};z.r4=B(ju,cW){A cV="r3: "+ju+" -- r2 r1 4F r0 qZ qY.";if(cW){cV+=" "+cW}1z.1K(cV)};(B(){A cR={53:{},6p:0,1h:{},8k:{z:{1p:"z",1Z:"."},cU:{1p:"cU",1Z:"../qX/cU"},cT:{1p:"cT",1Z:"cT"}},cN:B(cS){A mp=D.8k;C jp(mp[cS]&&mp[cS].1Z)},jk:B(8x){A mp=D.8k;if(D.cN(8x)){C mp[8x].1Z}C 8x},8v:[],6t:U,56:[],8t:[],8u:U};R(A cQ in cR){z[cQ]=cR[cQ]}})();z.jg=B(8w,cP,cb){A 1g=(((8w.2s(0)=="/"||8w.1f(/^\\w+:/)))?"":D.51)+8w;if(1o.jt&&z.c8){1g+="?"+67(1o.jt).2f(/\\W+/g,"")}1u{C!cP?D.cO(1g,cb):D.jq(1g,cP,cb)}1y(e){1z.1K(e);C U}};z.cO=B(1g,cb){if(D.8v[1g]){C K}A 6u=D.iR(1g,K);if(!6u){C U}D.8v[1g]=K;D.8v.Y(1g);if(cb){6u="("+6u+")"}A jr=z["3u"](6u+"\\r\\n//@ qW="+1g);if(cb){cb(jr)}C K};z.jq=B(1g,jo,cb){A ok=U;1u{ok=D.cO(1g,cb)}1y(e){1z.1K("qV je ",1g," 4G 9f: ",e)}C jp(ok&&D.53[jo])};z.6m=B(){D.8u=K;D.6t=K;A 57=D.56;D.56=[];R(A x=0;x<57.G;x++){57[x]()}D.8u=U;if(z.6t&&z.6p==0&&D.56.G>0){z.8s()}};z.ck=B(){A 57=D.8t;1s(57.G){(57.8q())()}};z.qU=B(M,jn){A d=z;if(P.G==1){d.56.Y(M)}I{if(P.G>1){d.56.Y(B(){M[jn]()})}}if(d.6t&&d.6p==0&&!d.8u){d.8s()}};z.dW=B(M,jm){A d=z;if(P.G==1){d.8t.Y(M)}I{if(P.G>1){d.8t.Y(B(){M[jm]()})}}};z.iM=B(){if(D.6t){C}if(D.6p>0){1z.1K("qT qS in qR!");C}z.8s()};z.8s=B(){if(V 5c=="8b"||(1o["qQ"]&&z.2M)){5c("z.6m();",0)}I{z.6m()}};z.cF=B(jl){A 4v=jl.1A(".");R(A i=4v.G;i>0;i--){A 8r=4v.2w(0,i).22(".");if((i==1)&&!D.cN(8r)){4v[0]="../"+4v[0]}I{A cM=D.jk(8r);if(cM!=8r){4v.3S(0,i,cM);3f}}}C 4v};z.jj=U;z.8m=B(2T,qP,55){55=D.jj||55;A 54=D.53[2T];if(54){C 54}A cL=2T.1A(".");A 3L=D.cF(2T);A jh=((3L[0].2s(0)!="/")&&!3L[0].1f(/^\\w+:/));A ji=3L[3L.G-1];A 3m;if(ji=="*"){2T=cL.2w(0,-1).22(".");3L.8q();3m=3L.22("/")+"/"+(1o["qO"]||"qN")+".js";if(jh&&3m.2s(0)=="/"){3m=3m.2w(1)}}I{3m=3L.22("/")+".js";2T=cL.22(".")}A jf=(!55)?2T:L;A ok=D.jg(3m,jf);if((!ok)&&(!55)){2m S 1O("qM 3O 4E \'"+2T+"\'; 72 qL \'"+3m+"\'")}if((!55)&&(!D["qK"])){54=D.53[2T];if(!54){2m S 1O("qJ \'"+2T+"\' is 3O qI a8 je \'"+3m+"\'")}}C 54};z.8c=z.8m;z.1Q=B(cK){A cJ=cK+"";A 8p=cJ;A 6s=cK.1A(/\\./);if(6s[6s.G-1]=="*"){6s.8q();8p=6s.22(".")}A 8o=z.6q(8p,K);D.53[cJ]=8o;D.53[8p]=8o;C 8o};z.qH=B(8n){A jd=8n["qG"]||[];A cI=jd.3U(8n[z.j4]||8n["aY"]||[]);R(A x=0;x<cI.G;x++){A 8l=cI[x];if(8l.1P==4e){z.8m.14(z,8l)}I{z.8m(8l)}}};z.jb=B(jc,qF){if(jc===K){A cH=[];R(A i=1;i<P.G;i++){cH.Y(P[i])}z.8c.14(z,cH)}};z.qE=z.jb;z.io=B(cG,ja){D.8k[cG]={1p:cG,1Z:ja}};z.qD=B(qC,qB,qA,qz){z.8c("z.j9");z.j9.qy.14(z.qx,P)};(B(){A j7=S 9G("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?$");A j6=S 9G("^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$");z.4r=B(){A n=L;A 1V=P;A 1g=1V[0];R(A i=1;i<1V.G;i++){if(!1V[i]){6c}A 1t=S z.4r(1V[i]+"");A 4u=S z.4r(1g+"");if((1t.28=="")&&(!1t.4t)&&(!1t.3l)&&(!1t.1r)){if(1t.52!=n){4u.52=1t.52}1t=4u}I{if(!1t.4t){1t.4t=4u.4t;if(!1t.3l){1t.3l=4u.3l;if(1t.28.2s(0)!="/"){A j8=4u.28.21(0,4u.28.31("/")+1)+1t.28;A 1X=j8.1A("/");R(A j=0;j<1X.G;j++){if(1X[j]=="."){if(j==1X.G-1){1X[j]=""}I{1X.3S(j,1);j--}}I{if(j>0&&!(j==1&&1X[0]=="")&&1X[j]==".."&&1X[j-1]!=".."){if(j==(1X.G-1)){1X.3S(j,1);1X[j-1]=""}I{1X.3S(j-1,2);j-=2}}}}1t.28=1X.22("/")}}}}1g="";if(1t.4t){1g+=1t.4t+":"}if(1t.3l){1g+="//"+1t.3l}1g+=1t.28;if(1t.1r){1g+="?"+1t.1r}if(1t.52){1g+="#"+1t.52}}D.1g=1g.2i();A r=D.1g.1f(j7);D.4t=r[2]||(r[1]?"":n);D.3l=r[4]||(r[3]?"":n);D.28=r[5];D.1r=r[7]||(r[6]?"":n);D.52=r[9]||(r[8]?"":n);if(D.3l!=n){r=D.3l.1f(j6);D.8X=r[3]||n;D.8W=r[4]||n;D.qw=r[5];D.qv=r[7]||n}};z.4r.1C.2i=B(){C D.1g}})();z.qu=B(j5,2E){A 2B=z.cF(j5).22("/");if(!2B){C L}if(2B.31("/")!=2B.G-1){2B+="/"}A cE=2B.T(":");if(2B.2s(0)!="/"&&(cE==-1||cE>2B.T("/"))){2B=z.51+2B}C S z.4r(2B,2E)};if(V 26!="1k"){z.c8=K;z.j4="qt";(B(){A d=z;if(1q&&1q.4I){A 8j=1q.4I("ak");A j3=/z(\\.qs)?\\.js([\\?\\.]|$)/i;R(A i=0;i<8j.G;i++){A 4X=8j[i].5t("4X");if(!4X){6c}A m=4X.1f(j3);if(m){if(!1o["51"]){1o["51"]=4X.21(0,m.hK)}A cD=8j[i].5t("1o");if(cD){A cC=3u("({ "+cD+" })");R(A x in cC){1o[x]=cC[x]}}3f}}}d.51=1o["51"];A n=cq;A 8i=n.iL;A 4Z=n.qr;A 6r=2k(4Z);d.2M=(8i.T("qq")>=0)?6r:0;d.6B=(4Z.T("qo")>=0)||(4Z.T("j2")>=0)?6r:0;d.3o=(4Z.T("j2")>=0)?6r:0;A j1=8i.T("qn");d.gu=d.7B=((j1>=0)&&(!d.6B))?6r:0;d.j0=0;d.1l=0;d.iV=0;1u{if(d.7B){d.j0=2k(8i.1A("qm/")[1].1A(" ")[0])}if((1q.gx)&&(!d.2M)){d.1l=2k(4Z.1A("qk ")[1].1A(";")[0])}}1y(e){}if(z.1l&&(26.8f.cu==="9q:")){1o.iT=K}d.iX=B(){A 2A;A qj;A cB=d.6q("cz.cy");if(cB){C cB}if(V iZ!="1k"){2A=S iZ()}I{if(d.1l){1u{2A=S 9j("qi.qh")}1y(e){}}I{if(cq.qg["8Z/x-iY"]){2A=1q.a9("8b");2A.cA("Z","8Z/x-iY");2A.cA("3n",0);2A.cA("58",0);2A.1c.gq="7C";1q.5K.4c(2A)}}}if(!2A){C L}z.88("cz.cy.qf",2A);C z.6q("cz.cy")};A iW=d.iX();if(iW){d.iV=K}A cm=1q["aX"];d.qe=(cm=="aW")||(cm=="gr")||(d.1l<6);d.8h=1o.8h||(d.1l?n.qd:n.qc).1M();d.qb=1z.1K;d.cx=["iU.8g","em.8g","iU.8g.4.0"];d.9b=B(){A 4s=L;A cv=L;if(!z.1l||!1o.iT){1u{4s=S qa()}1y(e){}}if(!4s){R(A i=0;i<3;++i){A cw=z.cx[i];1u{4s=S 9j(cw)}1y(e){cv=e}if(4s){z.cx=[cw];3f}}}if(!4s){2m S 1O("8g 3O q9: "+cv)}C 4s};d.8Y=B(iS){A 4Y=iS.3N||0;C((4Y>=q8)&&(4Y<q7))||(4Y==q6)||(4Y==q5)||(!4Y&&(8f.cu=="9q:"||8f.cu=="q4:"))};A cs=1q.4I("q3");A iQ=(cs&&cs.G>0);d.iR=B(1g,iP){A 3K=D.9b();if(!iQ&&z.4r){1g=(S z.4r(26.8f,1g)).2i()}3K.dL("dD",1g,U);1u{3K.dI(L);if(!d.8Y(3K)){A 1G=1O("q2 4F 4E "+1g+" 3N:"+3K.3N);1G.3N=3K.3N;1G.2G=3K.2G;2m 1G}}1y(e){if(iP){C L}2m e}C 3K.2G}})();z.iO=U;z.6o=B(e){z.iO=K;A cr=(e&&e.Z)?e.Z.1M():"4E";if(P.2O.iN||(cr!="q1"&&cr!="4E")){C}P.2O.iN=K;if(V z["8e"]!="1k"){dX(z.8e);63 z.8e}if(z.6p==0){z.iM()}};if(1q.66){if(z.2M||(z.7B&&(1o["q0"]===K))){1q.66("pZ",z.6o,L)}26.66("4E",z.6o,L)}if(/(pY|pX)/i.6Z(cq.iL)){z.8e=dN(B(){if(/6m|iJ/.6Z(1q.6F)){z.6o()}},10)}(B(){A 3g=26;A 8d=B(cp,fp){A iK=3g[cp]||B(){};3g[cp]=B(){fp.14(3g,P);iK.14(3g,P)}};if(z.1l){1q.fJ("<iI"+"iH pW 4X=\\"//:\\" "+"pV=\\"if(D.6F==\'iJ\'){z.6o();}\\">"+"</iI"+"iH>");A co=K;8d("iG",B(){3g.5c(B(){co=U},0)});8d("pU",B(){if(co){z.ck()}});1u{1q.pT.2P("v","pS:pR-pQ-pP:pO");1q.pN().pM("v\\\\:*","pL:2E(#aY#pK)")}1y(e){}}I{8d("iG",B(){z.ck()})}})();z.pJ=B(){};z.1e=26["1q"]||L;z.3E=B(){C z.1e.3E||z.1e.4I("3E")[0]};z.ch=B(iF,iE){z.1W=iF;z.1e=iE};z.cf=B(4q,6n,iD){if((6n)&&((V 4q=="3c")||(4q 1N 67))){4q=6n[4q]}C(6n?4q.14(6n,iD||[]):4q())};z.pI=B(cj,iC,iB,iA){A cg;A iz=z.1W;A iy=z.1e;1u{z.ch(cj,cj.1q);cg=z.cf(iC,iB,iA)}ir{z.ch(iz,iy)}C cg};z.pH=B(ix,iw,iv,iu){A ce;A ip=z.1e;1u{z.1e=ix;ce=z.cf(iw,iv,iu)}ir{z.1e=ip}C ce};if(1o["cd"]){R(A cc in 1o["cd"]){z.io(cc,1o["cd"][cc])}}}if(1o.im){if(!1z.ca){z.8c("z.pG.ca")}}}if(!z.1h["z.X.c9"]){z.1h["z.X.c9"]=K;z.1Q("z.X.c9");z.1R=B(it){C(V it=="3c"||it 1N 67)};z.2l=B(it){C(it&&it 1N 4e||V it=="6a"||((V z["1H"]!="1k")&&(it 1N z.1H)))};if(z.c8&&z.3o){z.1Y=B(it){if((V(it)=="B")&&(it=="[8b 1H]")){C U}C(V it=="B"||it 1N bI)}}I{z.1Y=B(it){C(V it=="B"||it 1N bI)}}z.ib=B(it){if(V it=="1k"){C U}C(it===L||V it=="8b"||z.2l(it)||z.1Y(it))};z.pF=B(it){A d=z;if((!it)||(V it=="1k")){C U}if(d.1R(it)){C U}if(d.1Y(it)){C U}if(d.2l(it)){C K}if((it.5w)&&(it.5w.1M()=="3R")){C U}if(pE(it.G)){C K}C U};z.pD=B(it){if(!it){C U}C!z.1Y(it)&&/\\{\\s*\\[il 5h\\]\\s*\\}/.6Z(67(it))};z.c7=B(M,4W){A 8a={};R(A x in 4W){if((V 8a[x]=="1k")||(8a[x]!=4W[x])){M[x]=4W[x]}}if(z.1l){A p=4W.2i;if((V(p)=="B")&&(p!=M.2i)&&(p!=8a.2i)&&(p!="\\pC 2i() {\\n [il 5h]\\n}\\n")){M.2i=4W.2i}}C M};z.1x=B(M,pB){R(A i=1,l=P.G;i<l;i++){z.c7(M,P[i])}C M};z.4M=B(c6,pA){R(A i=1,l=P.G;i<l;i++){z.c7(c6.1C,P[i])}C c6};z.ig=B(c5,89){A ij=z.4d(P,2);A ik=z.1R(89);C B(){A ih=z.4d(P);A f=(ik?(c5||z.1W)[89]:89);C(f)&&(f.14(c5||D,ij.3U(ih)))}};z.2p=B(2z,3k){if(P.G>2){C z.ig.14(z,P)}if(!3k){3k=2z;2z=L}if(z.1R(3k)){2z=2z||z.1W;if(!2z[3k]){2m(["z.2p: ie[\\"",3k,"\\"] is L (ie=\\"",2z,"\\")"].22(""))}C B(){C 2z[3k].14(2z,P||[])}}I{C(!2z?3k:B(){C 3k.14(2z,P||[])})}};z.6j=B(M,c3){B c4(){};c4.1C=M;A c2=S c4();if(c3){z.1x(c2,c3)}C c2};z.7X=B(pz){A Q=[L];C z.2p.14(z,Q.3U(z.4d(P)))};z.4d=B(M,ic){A Q=[];R(A x=ic||0;x<M.G;x++){Q.Y(M[x])}C Q};z.c1=B(o){if(!o){C o}if(z.2l(o)){A r=[];R(A i=0;i<o.G;++i){r.Y(z.c1(o[i]))}C r}I{if(z.ib(o)){if(o.2t&&o.a7){C o.a7(K)}I{A r=S o.1P();R(A i in o){if(!(i in r)||r[i]!=o[i]){r[i]=z.c1(o[i])}}C r}}}C o};z.7g=B(2H){C 2H.2f(/^\\s\\s*/,"").2f(/\\s\\s*$/,"")}}if(!z.1h["z.X.2r"]){z.1h["z.X.2r"]=K;z.1Q("z.X.2r");z.2r=B(6l,4p,3j){if(z.1Y(3j)||(P.G>3)){z.ia("z.2r: R 9P \'"+6l+"\' py pw B as \'1P\' pv pu of as a pt i3.","","1.0");A c=3j;3j=P[3]||{};3j.1P=c}A dd=P.2O,4V=L;if(z.2l(4p)){4V=4p;4p=4V.3a()}if(4V){R(A i=0,m;i<4V.G;i++){m=4V[i];if(!m){2m("ps #"+i+" 4F pr of "+6l+" is L. pq\'s pp a po pl is 3O 6m.")}4p=dd.6j(4p,m)}}A i9=(3j||0).1P,6k=dd.6j(4p),fn;R(A i in 3j){if(z.1Y(fn=3j[i])&&(!0[i])){fn.i4=i}}z.4M(6k,{4o:6l,bY:i9,bZ:L},3j||0);6k.1C.1P=6k;C z.88(6l,6k)};z.1x(z.2r,{6j:B(c0,i8){A bp=(c0||0).1C,mp=(i8||0).1C;A 2S=z.2r.i7();z.1x(2S,{84:bp,1x:mp});if(c0){2S.1C=z.6j(bp)}z.4M(2S,z.2r.i6,mp||0,{bY:L});2S.1C.1P=2S;2S.1C.4o=(bp||0).4o+"pk"+(mp||0).4o;z.88(2S.1C.4o,2S);C 2S},i7:B(){C B(){D.i5(P)}},i6:{i5:B(86){A c=86.2O,s=c.84,ct=s&&s.1P,m=c.1x,87=m&&m.1P,a=86,ii,fn;if(a[0]){if((fn=a[0]["bZ"])){a=fn.14(D,a)||a}}if(fn=c.1C.bZ){a=fn.14(D,a)||a}if(ct&&ct.14){ct.14(D,a)}if(87&&87.14){87.14(D,a)}if(ii=c.1C.bY){ii.14(D,86)}},bX:B(85){A c=D.1P,p,m;1s(c){p=c.84;m=c.1x;if(m==85||(m 1N 85.1P)){C p}if(m&&(m=m.bX(85))){C m}c=p&&p.1P}},6h:B(83,82,bW,6i){A p=bW,c,m,f;do{c=p.1P;m=c.1x;if(m&&(m=D.6h(83,82,m,6i))){C m}if((f=p[83])&&(6i==(f==82))){C p}p=c.84}1s(p);C!6i&&(p=D.bX(bW))&&D.6h(83,82,p,6i)},bU:B(2R,4U,bV){A a=P;if(!z.1R(a[0])){bV=4U;4U=2R;2R=4U.2O.i4}A c=4U.2O,p=D.1P.1C,a=bV||4U,fn,mp;if(D[2R]!=c||p[2R]==c){mp=D.6h(2R,c,p,K);if(!mp){2m(D.4o+": 1p i3 (\\""+2R+"\\") 4F bU pj 1f 2O (2r.js)")}p=D.6h(2R,c,mp,U)}fn=p&&p[2R];if(!fn){1z.1K(mp.4o+": no bU \\""+2R+"\\" ph pg (2r.js)");C}C fn.14(D,a)}}})}if(!z.1h["z.X.2c"]){z.1h["z.X.2c"]=K;z.1Q("z.X.2c");z.3i={i2:B(){C B(){A ap=4e.1C,c=P.2O,ls=c.2b,t=c.5V;A r=t&&t.14(D,P);R(A i in ls){if(!(i in ap)){ls[i].14(D,P)}}C r}},2P:B(6g,bT,i1){6g=6g||z.1W;A f=6g[bT];if(!f||!f.2b){A d=z.3i.i2();d.5V=f;d.2b=[];f=6g[bT]=d}C f.2b.Y(i1)},3J:B(i0,hZ,bS){A f=(i0||z.1W)[hZ];if(f&&f.2b&&bS--){63 f.2b[bS]}}};z.2c=B(M,pd,pc,pa,p9){A a=P,F=[],i=0;F.Y(z.1R(a[0])?L:a[i++],a[i++]);A a1=a[i+1];F.Y(z.1R(a1)||z.1Y(a1)?a[i++]:L,a[i++]);R(A l=a.G;i<l;i++){F.Y(a[i])}C z.by.14(D,F)};z.by=B(M,bR,hY,hX){A l=z.3i,h=l.2P(M,bR,z.2p(hY,hX));C[M,bR,h,l]};z.p8=B(6f){if(6f&&6f[0]!==1k){z.bv.14(D,6f);63 6f[0]}};z.bv=B(M,hV,hU,hW){hW.3J(M,hV,hU)};z.80={};z.p7=B(bQ,hT,hS){C[bQ,z.3i.2P(z.80,bQ,z.2p(hT,hS))]};z.p6=B(81){if(81){z.3i.3J(z.80,81[0],81[1])}};z.hQ=B(hR,F){A f=z.80[hR];(f)&&(f.14(D,F||[]))};z.p5=B(hP,M,bP){A pf=B(){z.hQ(hP,P)};C(bP)?z.2c(M,bP,pf):z.2c(M,pf)}}if(!z.1h["z.X.30"]){z.1h["z.X.30"]=K;z.1Q("z.X.30");z.30=B(hO){D.bM=[];D.id=D.hN();D.2y=-1;D.3M=0;D.4R=[L,L];D.bO=hO;D.7Z=U};z.4M(z.30,{hN:(B(){A n=1;C B(){C n++}})(),4C:B(){if(D.2y==-1){if(D.bO){D.bO(D)}I{D.7Z=K}if(D.2y==-1){A 1G=S 1O("30 p4");1G.dY="4C";D.5i(1G)}}I{if((D.2y==0)&&(D.4R[0]1N z.30)){D.4R[0].4C()}}},7V:B(1v){D.2y=((1v 1N 1O)?1:0);D.4R[D.2y]=1v;D.7U()},bN:B(){if(D.2y!=-1){if(!D.7Z){2m S 1O("p3 p2!")}D.7Z=U;C}},dM:B(1v){D.bN();D.7V(1v)},5i:B(1v){D.bN();if(!(1v 1N 1O)){1v=S 1O(1v)}D.7V(1v)},9e:B(cb,4T){A 6e=z.2p(cb,4T);if(P.G>2){6e=z.7X(6e,P,2)}C D.5k(6e,6e)},ef:B(cb,4T){A 7Y=z.2p(cb,4T);if(P.G>2){7Y=z.7X(7Y,P,2)}C D.5k(7Y,L)},ed:B(cb,4T){A 7W=z.2p(cb,4T);if(P.G>2){7W=z.7X(7W,P,2)}C D.5k(L,7W)},5k:B(cb,eb){D.bM.Y([cb,eb]);if(D.2y>=0){D.7U()}C D},7U:B(){A bL=D.bM;A 4n=D.2y;A 1v=D.4R[4n];A 4S=D;A cb=L;1s((bL.G>0)&&(D.3M==0)){A f=bL.3a()[4n];if(!f){6c}1u{1v=f(1v);4n=((1v 1N 1O)?1:0);if(1v 1N z.30){cb=B(1v){4S.7V(1v);4S.3M--;if((4S.3M==0)&&(4S.2y>=0)){4S.7U()}};D.3M++}}1y(1G){1z.1K(1G);4n=1;1v=1G}}D.2y=4n;D.4R[4n]=1v;if((cb)&&(D.3M)){1v.9e(cb)}}})}if(!z.1h["z.X.2e"]){z.1h["z.X.2e"]=K;z.1Q("z.X.2e");z.5m=B(2e){1u{C 3u("("+2e+")")}1y(e){1z.1K(e);C 2e}};z.bK=B(2H){C("\\""+2H.2f(/(["\\\\])/g,"\\\\$1")+"\\"").2f(/[\\f]/g,"\\\\f").2f(/[\\b]/g,"\\\\b").2f(/[\\n]/g,"\\\\n").2f(/[\\t]/g,"\\\\t").2f(/[\\r]/g,"\\\\r")};z.hM="\\t";z.eq=B(it,4l,4P){4P=4P||"";A 4k=(4l?4P+z.hM:"");A 6b=(4l?"\\n":"");A 4Q=V(it);if(4Q=="1k"){C"1k"}I{if((4Q=="4J")||(4Q=="p1")){C it+""}I{if(it===L){C"L"}}}if(4Q=="3c"){C z.bK(it)}A 6d=P.2O;A 4m;if(V it.hL=="B"){4m=it.hL();if(it!==4m){C 6d(4m,4l,4k)}}if(V it.2e=="B"){4m=it.2e();if(it!==4m){C 6d(4m,4l,4k)}}if(z.2l(it)){A 1v=[];R(A i=0;i<it.G;i++){A 1U=6d(it[i],4l,4k);if(V(1U)!="3c"){1U="1k"}1v.Y(6b+4k+1U)}C"["+1v.22(", ")+6b+4P+"]"}if(4Q=="B"){C L}A bJ=[];R(A 1i in it){A 7T;if(V(1i)=="4J"){7T="\\""+1i+"\\""}I{if(V(1i)=="3c"){7T=z.bK(1i)}I{6c}}1U=6d(it[1i],4l,4k);if(V(1U)!="3c"){6c}bJ.Y(6b+4k+7T+": "+1U)}C"{"+bJ.22(", ")+6b+4P+"}"}}if(!z.1h["z.X.6a"]){z.1h["z.X.6a"]=K;z.1Q("z.X.6a");(B(){A 69=B(Q,M,cb){C[(z.1R(Q)?Q.1A(""):Q),(M||z.1W),(z.1R(cb)?(S bI("1m","hK","6a",cb)):cb)]};z.1x(z,{T:B(bH,hH,hI,hJ){A i=0,2q=1,1d=bH.G;if(hJ){i=1d-1;2q=1d=-1}R(i=hI||i;i!=1d;i+=2q){if(bH[i]==hH){C i}}C-1},31:B(hG,hF,hE){C z.T(hG,hF,hE,K)},1n:B(Q,hD,M){if(!Q||!Q.G){C}A 1I=69(Q,M,hD);Q=1I[0];R(A i=0,l=1I[0].G;i<l;i++){1I[2].2d(1I[1],Q[i],i,Q)}},bE:B(bF,Q,hC,M){A 1I=69(Q,M,hC);Q=1I[0];R(A i=0,l=Q.G;i<l;i++){A bG=!!1I[2].2d(1I[1],Q[i],i,Q);if(bF^bG){C bG}}C bF},ah:B(Q,hB,hA){C D.bE(K,Q,hB,hA)},ag:B(Q,hz,hy){C D.bE(U,Q,hz,hy)},23:B(Q,7t,M){A 1I=69(Q,M,7t);Q=1I[0];A bD=((P[3])?(S P[3]()):[]);R(A i=0;i<Q.G;++i){bD.Y(1I[2].2d(1I[1],Q[i],i,Q))}C bD},3T:B(Q,hx,M){A 1I=69(Q,M,hx);Q=1I[0];A bC=[];R(A i=0;i<Q.G;i++){if(1I[2].2d(1I[1],Q[i],i,Q)){bC.Y(Q[i])}}C bC}})})()}if(!z.1h["z.X.1J"]){z.1h["z.X.1J"]=K;z.1Q("z.X.1J");z.1J=B(bB){if(bB){D.hw(bB)}};z.1J.hp={p0:[0,0,0],oZ:[60,60,60],oY:[2j,2j,2j],oX:[1T,1T,1T],oW:[2j,0,0],oV:[1T,0,0],oU:[2j,0,2j],oT:[1T,0,1T],oS:[0,2j,0],oR:[0,1T,0],oQ:[2j,2j,0],oP:[1T,1T,0],oO:[0,0,2j],oN:[0,0,1T],oM:[0,2j,2j],oL:[0,1T,1T]};z.4M(z.1J,{r:1T,g:1T,b:1T,a:1,bz:B(r,g,b,a){A t=D;t.r=r;t.g=g;t.b=b;t.a=a},hw:B(2Q){A d=z;if(d.1R(2Q)){d.hq(2Q,D)}I{if(d.2l(2Q)){d.7P(2Q,D)}I{D.bz(2Q.r,2Q.g,2Q.b,2Q.a);if(!(2Q 1N d.1J)){D.7Q()}}}C D},7Q:B(){C D},oK:B(){A t=D;C[t.r,t.g,t.b]},oJ:B(){A t=D;C[t.r,t.g,t.b,t.a]},oI:B(){A Q=z.23(["r","g","b"],B(x){A s=D[x].2i(16);C s.G<2?"0"+s:s},D);C"#"+Q.22("")},8F:B(hv){A t=D,7S=t.r+", "+t.g+", "+t.b;C(hv?"hs("+7S+", "+t.a:"7S("+7S)+")"},2i:B(){C D.8F(K)}});z.d8=B(bA,1d,hu,M){A d=z,t=M||S z.1J();d.1n(["r","g","b","a"],B(x){t[x]=bA[x]+(1d[x]-bA[x])*hu;if(x!="a"){t[x]=2Y.oH(t[x])}});C t.7Q()};z.ho=B(ht,M){A m=ht.1M().1f(/^hs?\\(([\\s\\.,0-9]+)\\)/);C m&&z.7P(m[1].1A(/\\s*,\\s*/),M)};z.hn=B(4j,M){A d=z,t=M||S d.1J(),7R=(4j.G==4)?4:8,hr=(1<<7R)-1;4j=2V("oG"+4j.3b(1));if(2L(4j)){C L}d.1n(["b","g","r"],B(x){A c=4j&hr;4j>>=7R;t[x]=7R==4?17*c:c});t.a=1;C t};z.7P=B(a,M){A t=M||S z.1J();t.bz(2V(a[0]),2V(a[1]),2V(a[2]),2V(a[3]));if(2L(t.a)){t.a=1}C t.7Q()};z.hq=B(2H,M){A a=z.1J.hp[2H];C a&&z.7P(a,M)||z.ho(2H,M)||z.hn(2H,M)}}if(!z.1h["z.X"]){z.1h["z.X"]=K;z.1Q("z.X")}if(!z.1h["z.X.5Z"]){z.1h["z.X.5Z"]=K;z.1Q("z.X.5Z");(B(){A 1j=z.b2={2P:B(E,68,fp){if(!E){C}68=1j.4O(68);fp=1j.7G(68,fp);E.66(68,fp,U);C fp},3J:B(E,hm,hl){(E)&&(E.oF(1j.4O(hm),hl,U))},4O:B(1p){C(1p.2w(0,2)=="on"?1p.2w(2):1p)},7G:B(1p,fp){C(1p!="4b"?fp:B(e){C fp.2d(D,1j.4i(e,D))})},4i:B(H,oE){4w(H.Z){2X"4b":1j.7K(H);3f}C H},7K:B(H){H.oD=(H.3h?67.oC(H.3h):"")}};z.oB=B(H,hk){C 1j.4i(H,hk)};z.gY=B(H){H.7J();H.7I()};A 7O=z.3i;z.by=B(M,bx,hh,hg,hi){A hj=M&&(M.2t||M.oA||M.66);A bw=!hj?0:(!hi?1:2),l=[z.3i,1j,7O][bw];A h=l.2P(M,bx,z.2p(hh,hg));C[M,bx,h,bw]};z.bv=B(M,he,hd,hf){([z.3i,1j,7O][hf]).3J(M,he,hd)};z.5W={oz:8,gV:9,oy:12,ox:13,ow:16,ov:17,ou:18,gG:19,ot:20,os:27,or:32,b5:33,b4:34,gE:35,gF:36,b7:37,b9:38,b6:39,b8:40,gD:45,8S:46,oq:47,oo:91,om:92,ol:93,oj:96,oi:97,oh:98,og:99,oe:6D,od:oc,ob:oa,o9:o8,o7:o6,o5:o4,o3:bi,o2:o1,o0:nZ,nY:nX,nW:nV,nU:bk,gS:nT,gR:nS,gQ:nR,gP:nQ,gO:nP,gN:nO,gM:nN,gL:nM,gK:nL,gJ:nK,gI:nJ,gH:nI,nH:nG,nF:nE,nD:nC,gB:nB,gC:nA};if(z.1l){bf=B(e,5h){1u{C(e.3I=5h)}1y(e){C 0}};A 61=z.3i;if(!1o.nz){7O=61=z.gy={b3:[],2P:B(64,bu,hc){64=64||z.1W;A f=64[bu];if(!f||!f.2b){A d=z.gz();d.5V=f&&(7M.Y(f)-1);d.2b=[];f=64[bu]=d}C f.2b.Y(7M.Y(hc)-1)},3J:B(hb,ha,7N){A f=(hb||z.1W)[ha],l=f&&f.2b;if(f&&l&&7N--){63 7M[l[7N]];63 l[7N]}}};A 7M=61.b3}z.1x(1j,{2P:B(E,62,fp){if(!E){C}62=1j.4O(62);if(62=="h3"){A kd=E.bs;if(!kd||!kd.2b||!kd.h9){1j.2P(E,"bs",1j.h4);E.bs.h9=K}}C 61.2P(E,62,1j.7G(fp))},3J:B(E,h8,h7){61.3J(E,1j.4O(h8),h7)},4O:B(7L){C(7L.2w(0,2)!="on"?"on"+7L:7L)},ny:B(){},4i:B(H,4N){if(!H){A w=(4N)&&((4N.aD||4N.1q||4N).nx)||26;H=w.5Z}if(!H){C(H)}H.5V=H.br;H.bh=(4N||H.br);H.nw=H.nv;H.nu=H.nr;A bq=H.br,1e=(bq&&bq.aD)||1q;A bn=((z.1l<6)||(1e["aX"]=="aW"))?1e.3E:1e.5K;A bm=z.aB();H.nq=H.np+z.aH(bn.5I||0)-bm.x;H.nn=H.nm+(bn.5G||0)-bm.y;if(H.Z=="fk"){H.h6=H.nl}if(H.Z=="fj"){H.h6=H.nk}H.7I=1j.bc;H.7J=1j.ba;C 1j.h5(H)},h5:B(H){4w(H.Z){2X"4b":A c=("3h"in H?H.3h:H.3I);if(c==10){c=0;H.3I=13}I{if(c==13||c==27){c=0}I{if(c==3){c=99}}}H.3h=c;1j.7K(H);3f}C H},gZ:{bi:42,bk:47,h2:59,nj:43,ni:44,nh:45,ng:46,nf:47,60:96,h1:91,nb:92,na:93,h0:39},h4:B(H){A kp=H.bh.h3;if(!kp||!kp.2b){C}A k=H.3I;A bj=(k!=13)&&(k!=32)&&(k!=27)&&(k<48||k>90)&&(k<96||k>bk)&&(k<h2||k>60)&&(k<h1||k>h0);if(bj||H.5Y){A c=(bj?0:k);if(H.5Y){if(k==3||k==13){C}I{if(c>95&&c<bi){c-=48}I{if((!H.5X)&&(c>=65&&c<=90)){c+=32}I{c=1j.gZ[c]||c}}}}A 2x=1j.7H(H,{Z:"4b",2x:K,3h:c});kp.2d(H.bh,2x);H.bg=2x.bg;H.bd=2x.bd;bf(H,2x.3I)}},bc:B(){D.bg=K},ba:B(){D.n9=D.3I;if(D.5Y){bf(D,0)}D.bd=U}});z.gY=B(H){H=H||26.5Z;1j.bc.2d(H);1j.ba.2d(H)}}1j.7H=B(H,gX){A 2x=z.1x({},H,gX);1j.7K(2x);2x.7J=B(){H.7J()};2x.7I=B(){H.7I()};C 2x};if(z.2M){z.1x(1j,{4i:B(H,n8){4w(H.Z){2X"4b":A c=H.n7;if(c==3){c=99}c=((c<41)&&(!H.5X)?0:c);if((H.5Y)&&(!H.5X)&&(c>=65)&&(c<=90)){c+=32}C 1j.7H(H,{3h:c})}C H}})}if(z.3o){z.1x(1j,{4i:B(H,n6){4w(H.Z){2X"4b":A c=H.3h,s=H.5X,k=H.3I;k=k||gA[H.gW]||0;if(H.gW=="n5"){c=0}I{if((H.5Y)&&(c>0)&&(c<27)){c+=96}I{if(c==z.5W.gU){c=z.5W.gV;s=K}I{c=(c>=32&&c<gT?c:0)}}}C 1j.7H(H,{3h:c,5X:s,3I:k})}C H}});z.1x(z.5W,{gU:25,b9:gT,b8:n4,b7:n3,b6:n2,gS:n1,gR:n0,gQ:mZ,gP:mY,gO:mX,gN:mW,gM:mV,gL:mU,gK:mT,gJ:mS,gI:mR,gH:mQ,gG:mP,8S:mO,gF:mN,gE:mM,b5:mL,b4:mK,gD:mJ,mI:mH,gC:mG,gB:mF});A dk=z.5W,gA={"mE":dk.b9,"mD":dk.b8,"mC":dk.b7,"mB":dk.b6,"mA":dk.b5,"mz":dk.b4}}})();if(z.1l){z.gz=B(){C B(){A ap=4e.1C,h=z.gy.b3,c=P.2O,ls=c.2b,t=h[c.5V];A r=t&&t.14(D,P);R(A i in ls){if(!(i in ap)){h[ls[i]].14(D,P)}}C r}};z.b2.7G=B(fp){A f=z.b2.4i;C B(e){C fp.2d(D,f(e,D))}}}}if(!z.1h["z.X.b1"]){z.1h["z.X.b1"]=K;z.1Q("z.X.b1");1u{1q.my("mx",U,K)}1y(e){}if(z.1l||z.2M){z.1D=B(id,1e){if(z.1R(id)){A b0=(1e||z.1e);A 11=b0.gv(id);if((11)&&(11.gw.id.1Z==id)){C 11}I{A 5U=b0.gx[id];if(!5U){C}if(!5U.G){C 5U}A i=0;1s(11=5U[i++]){if(11.gw.id.1Z==id){C 11}}}}I{C id}}}I{z.1D=B(id,1e){if(z.1R(id)){C(1e||z.1e).gv(id)}I{C id}}}(B(){A 5T=L;z.mw=B(E){E=z.1D(E);1u{if(!5T){5T=1q.a9("mv")}5T.4c(E.1L?E.1L.fs(E):E);5T.9L=""}1y(e){}};z.mu=B(E,7F){1u{E=z.1D(E);7F=z.1D(7F);1s(E){if(E===7F){C K}E=E.1L}}1y(e){}C U};z.mt=B(E,5S){E=z.1D(E);if(z.gu){E.1c.ms=(5S)?"dg":"7C"}I{if(z.6B){E.1c.mr=(5S)?"8K":"7C"}I{if(z.1l){E.gs=(5S)?"":"on";z.1r("*",E).1n(B(gt){gt.gs=(5S)?"":"on"})}}}};A 5R=B(E,4h){4h.1L.mq(E,4h);C K};A aZ=B(E,4h){A pn=4h.1L;if(4h==pn.fm){pn.4c(E)}I{C 5R(E,4h.71)}C K};z.5E=B(E,2a,3H){if((!E)||(!2a)||(V 3H=="1k")){C U}E=z.1D(E);2a=z.1D(2a);if(V 3H=="4J"){A cn=2a.3W;if(((3H==0)&&(cn.G==0))||(cn.G==3H)){2a.4c(E);C K}if(3H==0){C 5R(E,2a.5A)}C aZ(E,cn[3H-1])}4w(3H.1M()){2X"mo":C 5R(E,2a);2X"a8":C aZ(E,2a);2X"9M":if(2a.5A){C 5R(E,2a.5A)}I{2a.4c(E);C K}3f;aY:2a.4c(E);C K}};z.aP="5g-3G";if(z.1l){A aV=1q.aX;z.aP=(aV=="aW")||(aV=="gr")||(z.1l<6)?"g5-3G":"5g-3G"}A 1E,dv=1q.mn;if(z.3o){1E=B(E){A s=dv.3F(E,L);if(!s&&E.1c){E.1c.gq="";s=dv.3F(E,L)}C s||{}}}I{if(z.1l){1E=B(E){C E.gn}}I{1E=B(E){C dv.3F(E,L)}}}z.3F=1E;if(!z.1l){z.4g=B(mm,gp){C 2k(gp)||0}}I{z.4g=B(go,2N){if(!2N){C 0}if(2N=="ml"){C 4}if(2N.2w&&(2N.2w(-2)=="px")){C 2k(2N)}4G(go){A gm=1c.2g;A gl=aU.2g;aU.2g=gn.2g;1u{1c.2g=2N;2N=1c.mk}1y(e){2N=0}1c.2g=gm;aU.2g=gl}C 2N}}z.ge=(z.1l?B(E){1u{C(E.mj.mi.2W/6D)}1y(e){C 1}}:B(E){C z.3F(E).2W});z.gf=(z.1l?B(E,7D){if(7D==1){E.1c.7E=E.1c.7E.2f(/gk:[^;]*;/i,"");if(E.gj.1M()=="gi"){z.1r("> gh",E).1n(B(i){i.1c.7E=i.1c.7E.2f(/gk:[^;]*;/i,"")})}}I{A o="mh(mg="+(7D*6D)+")";E.1c.3T=o}if(E.gj.1M()=="gi"){z.1r("> gh",E).1n(B(i){i.1c.3T=o})}C 7D}:B(E,gg){C E.1c.2W=gg});A 5Q={3n:K,58:K,2g:K,5J:K};A gd=B(E,Z,5P){Z=Z.1M();if(5Q[Z]===K){C z.4g(E,5P)}I{if(5Q[Z]===U){C 5P}I{if((Z.T("mf")>=0)||(Z.T("md")>=0)||(Z.T("3n")>=0)||(Z.T("58")>=0)||(Z.T("5q")>=0)||(Z.T("mc")>=0)||(Z.T("ma")>=0)){5Q[Z]=K;C z.4g(E,5P)}I{5Q[Z]=U;C 5P}}}};z.1c=B(E,5O,aT){A n=z.1D(E),F=P.G,op=(5O=="2W");if(F==3){C op?z.gf(n,aT):n.1c[5O]=aT}if(F==2&&op){C z.ge(n)}A s=z.3F(n);C(F==1)?s:gd(n,5O,s[5O])};z.7A=B(n,gc){A s=gc||1E(n),px=z.4g,l=px(n,s.m9),t=px(n,s.m8);C{l:l,t:t,w:l+px(n,s.m7),h:t+px(n,s.m6)}};z.5N=B(n,gb){A ne="7C",px=z.4g,s=gb||1E(n),bl=(s.m5!=ne?px(n,s.m4):0),bt=(s.m3!=ne?px(n,s.m2):0);C{l:bl,t:bt,w:bl+(s.m1!=ne?px(n,s.m0):0),h:bt+(s.lZ!=ne?px(n,s.lY):0)}};z.aN=B(n,ga){A s=ga||1E(n),p=z.7A(n,s),b=z.5N(n,s);C{l:p.l+b.l,t:p.t+b.t,w:p.w+b.w,h:p.h+b.h}};z.aM=B(n,g9){A s=g9||1E(n),px=z.4g,l=px(n,s.lX),t=px(n,s.lW),r=px(n,s.lV),b=px(n,s.lU);if(z.3o&&(s.ax!="fU")){r=l}C{l:l,t:t,w:l+r,h:t+b}};z.au=B(E,g8){A s=g8||1E(E),me=z.aM(E,s);A l=E.fT-me.l,t=E.fS-me.t;if(z.7B){A aS=2k(s.2g),aR=2k(s.5J);if(!2L(aS)&&!2L(aR)){l=aS,t=aR}I{A p=E.1L;if(p&&p.1c){A aQ=1E(p);if(aQ.lT!="lS"){A be=z.5N(p,aQ);l+=be.l,t+=be.t}}}}I{if(z.2M){A p=E.1L;if(p){A be=z.5N(p);l-=be.l,t-=be.t}}}C{l:l,t:t,w:E.6v+me.w,h:E.8D+me.h}};z.aK=B(E,g7){A s=g7||1E(E),pe=z.7A(E,s),be=z.5N(E,s),w=E.aF,h;if(!w){w=E.6v,h=E.8D}I{h=E.lR,be.w=be.h=0}if(z.2M){pe.l+=be.l;pe.t+=be.t}C{l:pe.l,t:pe.t,w:w-pe.w-be.w,h:h-pe.h-be.h}};z.lQ=B(E,g6){A s=g6||1E(E),pe=z.7A(E,s),cb=z.aK(E,s);C{l:cb.l-pe.l,t:cb.t-pe.t,w:cb.w+pe.w,h:cb.h+pe.h}};z.aL=B(E,l,t,w,h,u){u=u||"px";4G(E.1c){if(!2L(l)){2g=l+u}if(!2L(t)){5J=t+u}if(w>=0){3n=w+u}if(h>=0){58=h+u}}};z.aO=B(E){A n=E.5w;C(z.aP=="g5-3G")||(n=="lP")||(n=="lO")};z.fX=B(E,7z,7y,g4){A bb=z.aO(E);if(bb){A pb=z.aN(E,g4);if(7z>=0){7z+=pb.w}if(7y>=0){7y+=pb.h}}z.aL(E,g3,g3,7z,7y)};z.fY=B(E,g1,g0,5M,5L,g2){A s=g2||z.3F(E);A bb=z.aO(E),pb=bb?fZ:z.aN(E,s),mb=z.aM(E,s);if(5M>=0){5M=2Y.5q(5M-pb.w-mb.w,0)}if(5L>=0){5L=2Y.5q(5L-pb.h-mb.h,0)}z.aL(E,g1,g0,5M,5L)};A fZ={l:0,t:0,w:0,h:0};z.lN=B(E,3G){A n=z.1D(E),s=1E(n),b=3G;C!b?z.au(n,s):z.fY(n,b.l,b.t,b.w,b.h,s)};z.lM=B(E,3G){A n=z.1D(E),s=1E(n),b=3G;C!b?z.aK(n,s):z.fX(n,b.w,b.h,s)};A 5H=B(E,1a){if(!(E=(E||0).1L)){C 0}A 1U,aJ=0,2h=z.3E();1s(E&&E.1c){if(1E(E).ax=="lL"){C 0}1U=E[1a];if(1U){aJ+=1U-0;if(E==2h){3f}}E=E.1L}C aJ};z.fQ=B(){A 2h=z.3E();A 3g=z.1W;A de=z.1e.5K;C{y:(3g.lK||de.5G||2h.5G||0),x:(3g.lJ||z.aH(de.5I)||2h.5I||0)}};z.aG=B(){C V z.aI=="1k"?(z.aI=z.3F(z.3E()).lI=="lH"):z.aI};z.aB=B(){A de=z.1e.5K;if(z.1l>=7){C{x:de.aC().2g,y:de.aC().5J}}I{C{x:z.aG()||26.am==26?de.fW:de.6v-de.aF-de.fW,y:de.lG}}};z.aH=B(aE){if(z.1l&&!z.aG()){A de=z.1e.5K;C aE+de.aF-de.lF}C aE};z.fP=B(E,aw){A ay=E.aD;A J={x:0,y:0};A 7w=U;A db=z.3E();if(z.1l){A aA=E.aC();A az=z.aB();J.x=aA.2g-az.x;J.y=aA.5J-az.y}I{if(ay["fV"]){A bo=ay.fV(E);J.x=bo.x-5H(E,"5I");J.y=bo.y-5H(E,"5G")}I{if(E["fR"]){7w=K;A 7x;if(z.3o&&(1E(E).ax=="fU")&&(E.1L==db)){7x=db}I{7x=db.1L}if(E.1L!=db){A nd=E;if(z.2M){nd=db}J.x-=5H(nd,"5I");J.y-=5H(nd,"5G")}A 4f=E;do{A n=4f["fT"];if(!z.2M||n>0){J.x+=2L(n)?0:n}A m=4f["fS"];J.y+=2L(m)?0:m;4f=4f.fR}1s((4f!=7x)&&4f)}I{if(E["x"]&&E["y"]){J.x+=2L(E.x)?0:E.x;J.y+=2L(E.y)?0:E.y}}}}if(7w||aw){A av=z.fQ();A m=7w?(!aw?-1:0):1;J.y+=m*av.y;J.x+=m*av.x}C J};z.af=B(E,fO){A n=z.1D(E),s=1E(n),mb=z.au(n,s);A at=z.fP(n,fO);mb.x=at.x;mb.y=at.y;C mb}})();z.fL=B(E,fN){C((" "+E.3A+" ").T(" "+fN+" ")>=0)};z.7s=B(E,ar){A 7v=E.3A;if((" "+7v+" ").T(" "+ar+" ")<0){E.3A=7v+(7v?" ":"")+ar}};z.7r=B(E,fM){A t=z.7g((" "+E.3A+" ").2f(" "+fM+" "," "));if(E.3A!=t){E.3A=t}};z.lE=B(E,aq,7u){if(V 7u=="1k"){7u=!z.fL(E,aq)}z[7u?"7s":"7r"](E,aq)}}if(!z.1h["z.X.1H"]){z.1h["z.X.1H"]=K;z.1Q("z.X.1H");(B(){A d=z;z.1H=B(){A F=P;if((F.G==1)&&(V F[0]=="4J")){D.G=eK(F[0])}I{if(F.G){d.1n(F,B(i){D.Y(i)},D)}}};z.1H.1C=S 4e;if(d.1l){A fK=B(al){C("A a2 = am."+al+"; "+"A ap = 4e.1C; "+"A ao = a2.1C; "+"R(A x in ao){ ap[x] = ao[x]; } "+"am."+al+" = 4e; ")};A fI=fK("z.1H");A aj=26.lD();aj.1q.fJ("<ak>"+fI+"</ak>");aj.lC(1,1,1,1)}z.4M(z.1H,{T:B(fH,fG){C d.T(D,fH,fG)},31:B(lB,lA){A aa=d.4d(P);aa.ae(D);C d.31.14(d,aa)},ah:B(fF,fE){C d.ah(D,fF,fE)},ag:B(fD,fC){C d.ag(D,fD,fC)},1n:B(fB,fA){d.1n(D,fB,fA);C D},23:B(7t,M){C d.23(D,7t,M,d.1H)},af:B(){C d.23(D,d.af)},1c:B(lz,ly){A aa=d.4d(P);aa.ae(D[0]);A s=d.1c.14(d,aa);C(P.G>1)?D:s},lx:B(lw,lv){A aa=d.4d(P);aa.ae(L);A s=D.23(B(i){aa[0]=i;C d.1c.14(d,aa)});C(P.G>1)?D:s},7s:B(fz){C D.1n(B(i){z.7s(i,fz)})},7r:B(fy){C D.1n(B(i){z.7r(i,fy)})},5E:B(fw,7q){A 1m=d.1r(fw)[0];7q=7q||"72";R(A x=0;x<D.G;x++){d.5E(D[x],1m,7q)}C D},2c:B(fv,fu,ft){D.1n(B(1m){d.2c(1m,fv,fu,ft)});C D},lu:B(ad){A ac=(ad)?d.9t(D,ad):D;ac.1n(B(1m){if(1m["1L"]){1m.1L.fs(1m)}});C ac},lt:B(fr,fq){A 1m=D[0];C d.1r(fr).1n(B(ai){d.5E(ai,1m,(fq||"72"))})},1r:B(7p){7p=7p||"";A J=S d.1H();D.1n(B(1m){d.1r(7p,1m).1n(B(ab){if(V ab!="1k"){J.Y(ab)}})});C J},3T:B(fo){A 5F=D;A 1V=P;A r=S d.1H();A rp=B(t){if(V t!="1k"){r.Y(t)}};if(d.1R(fo)){5F=d.9t(D,1V[0]);if(1V.G==1){C 5F}d.1n(d.3T(5F,1V[1],1V[2]),rp);C r}d.1n(d.3T(5F,1V[0],1V[1]),rp);C r},lr:B(7o,7n){A 1S=d.1e.a9("lq");if(d.1R(7o)){1S.9L=7o}I{1S.4c(7o)}A ct=((7n=="9M")||(7n=="a8"))?"fm":"5A";D.1n(B(1m){A 24=1S.a7(K);1s(24[ct]){d.5E(24[ct],1m,7n)}});C D},7m:B(fl,F){A a5=[];F=F||{};D.1n(B(1m){A a6={E:1m};d.1x(a6,F);a5.Y(d[fl](a6))});C d.fx.lp(a5)},8I:B(F){C D.7m("8I",F)},8H:B(F){C D.7m("8H",F)},6y:B(F){C D.7m("6y",F)}});z.1n(["fk","lo","fj","fi","ln","lm","ll","fi","lk","lj","4b"],B(H){A a4="on"+H;z.1H.1C[a4]=B(a,b){C D.2c(a4,a,b)}})})()}if(!z.1h["z.X.1r"]){z.1h["z.X.1r"]=K;z.1Q("z.X.1r");(B(){A d=z;A 2I=B(q){C[q.T("#"),q.T("."),q.T("["),q.T(":")]};A a0=B(a3,fh){A ql=a3.G;A i=2I(a3);A 1d=ql;R(A x=fh;x<i.G;x++){if(i[x]>=0){if(i[x]<1d){1d=i[x]}}}C(1d<0)?ql:1d};A 6X=B(7l){A i=2I(7l);if(i[0]!=-1){C 7l.21(i[0]+1,a0(7l,1))}I{C""}};A 5r=B(7k){A 5D;A i=2I(7k);if((i[0]==0)||(i[1]==0)){5D=0}I{5D=a0(7k,0)}C((5D>0)?7k.3b(0,5D).1M():"*")};A fg=B(Q){A J=-1;R(A x=0;x<Q.G;x++){A 1S=Q[x];if(1S>=0){if((1S>J)||(J==-1)){J=1S}}}C J};A 9H=B(7i){A i=2I(7i);if(-1==i[1]){C""}A di=i[1]+1;A 7j=fg(i.2w(2));if(di<7j){C 7i.21(di,7j)}I{if(-1==7j){C 7i.3b(di)}I{C""}}};A f3=[{1i:"|=",1f:B(15,fe){C"[5z(3U(\' \',@"+15+",\' \'), \' "+fe+"-\')]"}},{1i:"~=",1f:B(15,fd){C"[5z(3U(\' \',@"+15+",\' \'), \' "+fd+" \')]"}},{1i:"^=",1f:B(15,fb){C"[li-4G(@"+15+", \'"+fb+"\')]"}},{1i:"*=",1f:B(15,fa){C"[5z(@"+15+", \'"+fa+"\')]"}},{1i:"$=",1f:B(15,9Z){C"[21(@"+15+", 3c-G(@"+15+")-"+(9Z.G-1)+")=\'"+9Z+"\']"}},{1i:"!=",1f:B(15,f9){C"[3O(@"+15+"=\'"+f9+"\')]"}},{1i:"=",1f:B(15,f8){C"[@"+15+"=\'"+f8+"\']"}}];A 9C=B(9Y,3Z,f7,f6){A 49;A i=2I(3Z);if(i[2]>=0){A 4L=3Z.T("]",i[2]);A 29=3Z.21(i[2]+1,4L);1s(29&&29.G){if(29.2s(0)=="@"){29=29.2w(1)}49=L;R(A x=0;x<9Y.G;x++){A 1S=9Y[x];A 7h=29.T(1S.1i);if(7h>=0){A 15=29.21(0,7h);A 4a=29.21(7h+1S.1i.G);if((4a.2s(0)=="\\"")||(4a.2s(0)=="\'")){4a=4a.21(1,4a.G-1)}49=1S.1f(d.7g(15),d.7g(4a));3f}}if((!49)&&(29.G)){49=f7(29)}if(49){f6(49)}29=L;A 7f=3Z.T("[",4L);if(0<=7f){4L=3Z.T("]",7f);if(0<=4L){29=3Z.21(7f+1,4L)}}}}};A f0=B(f5){A 4K=".";A 7e=f5.1A(" ");1s(7e.G){A 2K=7e.3a();A 7d;if(2K==">"){7d="/";2K=7e.3a()}I{7d="//"}A f4=5r(2K);4K+=7d+f4;A id=6X(2K);if(id.G){4K+="[@id=\'"+id+"\'][1]"}A cn=9H(2K);if(cn.G){A 9X=" ";if(cn.2s(cn.G-1)=="*"){9X="";cn=cn.3b(0,cn.G-1)}4K+="[5z(3U(\' \',@9P,\' \'), \' "+cn+9X+"\')]"}9C(f3,2K,B(f2){C"[@"+f2+"]"},B(f1){4K+=f1})}C 4K};A 7a={};A eC=B(28){if(7a[28]){C 7a[28]}A 1e=d.1e;A 9W=f0(28);A 4H=B(9V){A J=[];A 7b;1u{7b=1e.9x(9W,9V,L,lh.lg,L)}1y(e){1z.1K("lf in le:",9W,"lc:",9V);1z.1K(e)}A 7c=7b.eZ();1s(7c){J.Y(7c);7c=7b.eZ()}C J};C 7a[28]=4H};A 5x={};A 9B={};A 3y=B(79,78){if(!79){C 78}if(!78){C 79}C B(){C 79.14(26,P)&&78.14(26,P)}};A 75=B(9U,3Y,5B,2J){A 2v=2J+1;A 76=(3Y.G==2v);A 2K=3Y[2J];if(2K==">"){A 77=9U.3W;if(!77.G){C}2v++;76=(3Y.G==2v);A 4H=6O(3Y[2J+1]);R(A x=0,11;x<77.G,11=77[x];x++){if(4H(11)){if(76){5B.Y(11)}I{75(11,3Y,5B,2v)}}}}A 5C=6U(2K)(9U);if(76){1s(5C.G){5B.Y(5C.3a())}}I{1s(5C.G){75(5C.3a(),3Y,5B,2v)}}};A eE=B(9T,eY){A J=[];A x=9T.G-1,11;1s(11=9T[x--]){75(11,eY,J,0)}C J};A 6O=B(3D){if(5x[3D]){C 5x[3D]}A ff=L;A 9S=5r(3D);if(9S!="*"){ff=3y(ff,B(N){C((N.2t==1)&&(9S==N.5w.1M()))})}A 9R=6X(3D);if(9R.G){ff=3y(ff,B(N){C((N.2t==1)&&(N.id==9R))})}if(2Y.5q.14(D,2I(3D).2w(1))>=0){ff=3y(ff,9z(3D))}C 5x[3D]=ff};A 5y=B(E){A pn=E.1L;A 9Q=pn.3W;A 2v=-1;A 3C=pn.5A;if(!3C){C 2v}A ci=E["eW"];A cl=pn["eX"];if(((V cl=="4J")&&(cl!=9Q.G))||(V ci!="4J")){pn["eX"]=9Q.G;A 2J=1;do{if(3C===E){2v=2J}if(3C.2t==1){3C["eW"]=2J;2J++}3C=3C.71}1s(3C)}I{2v=ci}C 2v};A lb=0;A 3X=B(N,15){A 74="";if(15=="9P"){C N.3A||74}if(15=="R"){C N.la||74}C N.5t(15,2)||74};A eH=[{1i:"|=",1f:B(15,9O){A eV=" "+9O+"-";C B(N){A ea=" "+(N.5t(15,2)||"");C((ea==9O)||(ea.T(eV)==0))}}},{1i:"^=",1f:B(15,eU){C B(N){C(3X(N,15).T(eU)==0)}}},{1i:"*=",1f:B(15,eT){C B(N){C(3X(N,15).T(eT)>=0)}}},{1i:"~=",1f:B(15,eS){A 9N=" "+eS+" ";C B(N){A ea=" "+3X(N,15)+" ";C(ea.T(9N)>=0)}}},{1i:"$=",1f:B(15,73){A 9N=" "+73;C B(N){A ea=" "+3X(N,15);C(ea.31(73)==(ea.G-73.G))}}},{1i:"!=",1f:B(15,eR){C B(N){C(3X(N,15)!=eR)}}},{1i:"=",1f:B(15,eQ){C B(N){C(3X(N,15)==eQ)}}}];A 9E=[{1i:"9M-9K",1f:B(1p,l9){C B(N){if(N.2t!=1){C U}A fc=N.eP;1s(fc&&(fc.2t!=1)){fc=fc.eP}C(!fc)}}},{1i:"72-9K",1f:B(1p,l8){C B(N){if(N.2t!=1){C U}A nc=N.71;1s(nc&&(nc.2t!=1)){nc=nc.71}C(!nc)}}},{1i:"l7",1f:B(1p,l6){C B(N){A cn=N.3W;A eO=N.3W.G;R(A x=eO-1;x>=0;x--){A nt=cn[x].2t;if((nt==1)||(nt==3)){C U}}C K}}},{1i:"5z",1f:B(1p,eN){C B(N){C(N.9L.T(eN)>=0)}}},{1i:"3O",1f:B(1p,eM){A eL=6O(eM);C B(N){C(!eL(N))}}},{1i:"l5-9K",1f:B(1p,2u){A pi=eK;if(2u=="l4"){C B(N){C(((5y(N))%2)==1)}}I{if((2u=="2n")||(2u=="l3")){C B(N){C((5y(N)%2)==0)}}I{if(2u.T("l2+")==0){A 70=pi(2u.3b(3));C B(N){C(N.1L.3W[70-1]===N)}}I{if((2u.T("n+")>0)&&(2u.G>3)){A 9J=2u.1A("n+",2);A eJ=pi(9J[0]);A 2J=pi(9J[1]);C B(N){C((5y(N)%eJ)==2J)}}I{if(2u.T("n")==-1){A 70=pi(2u);C B(N){C(5y(N)==70)}}}}}}}}];A 9z=B(3e){A 9I=(9B[3e]||5x[3e]);if(9I){C 9I}A ff=L;A i=2I(3e);if(i[0]>=0){A 24=5r(3e);if(24!="*"){ff=3y(ff,B(N){C(N.5w.1M()==24)})}}A 5u;A 3B=9H(3e);if(3B.G){A 9F=3B.2s(3B.G-1)=="*";if(9F){3B=3B.3b(0,3B.G-1)}A re=S 9G("(?:^|\\\\s)"+3B+(9F?".*":"")+"(?:\\\\s|$)");ff=3y(ff,B(N){C re.6Z(N.3A)})}if(i[3]>=0){A 3z=3e.3b(i[3]+1);A 9D="";A 5v=3z.T("(");A 6Y=3z.31(")");if((0<=5v)&&(0<=6Y)&&(6Y>5v)){9D=3z.21(5v+1,6Y);3z=3z.3b(0,5v)}5u=L;R(A x=0;x<9E.G;x++){A 1S=9E[x];if(1S.1i==3z){5u=1S.1f(3z,9D);3f}}if(5u){ff=3y(ff,5u)}}A eG=(d.1l)?B(5s){A eI=5s.1M();C B(N){C N[5s]||N[eI]}}:B(5s){C B(N){C(N&&N.5t&&N.l1(5s))}};9C(eH,3e,eG,B(eF){ff=3y(ff,eF)});if(!ff){ff=B(){C K}}C 9B[3e]=ff};A 6W={};A 6U=B(3d,1B){A 9A=6W[3d];if(9A){C 9A}A i=2I(3d);A id=6X(3d);if(i[0]==0){C 6W[3d]=B(1B){C[d.1D(id)]}}A 9y=9z(3d);A 5p;if(i[0]>=0){5p=B(1B){A 11=d.1D(id);if(9y(11)){C[11]}}}I{A 3V;A 24=5r(3d);if(2Y.5q.14(D,2I(3d))==-1){5p=B(1B){A J=[];A 11,x=0,3V=1B.4I(24);1s(11=3V[x++]){J.Y(11)}C J}}I{5p=B(1B){A J=[];A 11,x=0,3V=1B.4I(24);1s(11=3V[x++]){if(9y(11)){J.Y(11)}}C J}}}C 6W[3d]=5p};A l0={};A 5o={">":B(1B){A J=[];A 11,x=0,3V=1B.3W;1s(11=3V[x++]){if(11.2t==1){J.Y(11)}}C J}};A 9w=B(6V){if(0>6V.T(" ")){C 6U(6V)}A eD=B(1B){A 6S=6V.1A(" ");A 6T;if(6S[0]==">"){6T=[1B]}I{6T=6U(6S.3a())(1B)}C eE(6T,6S)};C eD};A 9v=((1q["9x"]&&!d.3o)?B(3x){A 6R=3x.1A(" ");if((1q["9x"])&&(3x.T(":")==-1)&&((K))){if(((6R.G>2)&&(3x.T(">")==-1))||(6R.G>3)||(3x.T("[")>=0)||((1==6R.G)&&(0<=3x.T(".")))){C eC(3x)}}C 9w(3x)}:9w);A ey=B(3w){if(5o[3w]){C 5o[3w]}if(0>3w.T(",")){C 5o[3w]=9v(3w)}I{A eB=3w.1A(/\\s*,\\s*/);A 4H=B(1B){A eA=0;A J=[];A 6Q;1s(6Q=eB[eA++]){J=J.3U(9v(6Q,6Q.T(" "))(1B))}C J};C 5o[3w]=4H}};A 5n=0;A ez=B(Q){A J=S d.1H();if(!Q){C J}if(Q[0]){J.Y(Q[0])}if(Q.G<2){C J}5n++;Q[0]["9u"]=5n;R(A x=1,11;11=Q[x];x++){if(Q[x]["9u"]!=5n){J.Y(11)}11["9u"]=5n}C J};d.1r=B(6P,1B){if(V 6P!="3c"){C S d.1H(6P)}if(V 1B=="3c"){1B=d.1D(1B)}C ez(ey(6P)(1B||d.1e))};d.9t=B(ex,9s){A 9r=S d.1H();A ff=(9s)?6O(9s):B(){C K};R(A x=0,11;11=ex[x];x++){if(ff(11)){9r.Y(11)}}C 9r}})()}if(!z.1h["z.X.1b"]){z.1h["z.X.1b"]=K;z.1Q("z.X.1b");z.6K=B(ew){A J={};A iq="kZ[Z!=9q][Z!=kY][Z!=et][Z!=kX][Z!=kW], kV, kU";z.1r(iq,ew).3T(B(E){C(!E.kT)}).1n(B(1m){A 3v=1m.1p;A Z=(1m.Z||"").1M();if((Z=="kS")||(Z=="kR")){if(1m.kQ){J[3v]=1m.1Z}}I{if(1m.kP){A ev=J[3v]=[];z.1r("kO[kN]",1m).1n(B(eu){ev.Y(eu.1Z)})}I{J[3v]=1m.1Z;if(Z=="et"){J[3v+".x"]=J[3v+".y"]=J[3v].x=J[3v].y=0}}}});C J};z.9h=B(23){A ec=kM;A J="";A es={};R(A x in 23){if(23[x]!=es[x]){if(z.2l(23[x])){R(A y=0;y<23[x].G;y++){J+=ec(x)+"="+ec(23[x][y])+"&"}}I{J+=ec(x)+"="+ec(23[x])+"&"}}}if((J.G)&&(J.2s(J.G-1)=="&")){J=J.3b(0,J.G-1)}C J};z.kL=B(er){C z.9h(z.6K(er))};z.kK=B(ep){C z.eq(z.6K(ep))};z.kJ=B(2H){A J={};A qp=2H.1A("&");A dc=kI;z.1n(qp,B(1m){if(1m.G){A 9p=1m.1A("=");A 1p=dc(9p.3a());A 1U=dc(9p.22("="));if(z.1R(J[1p])){J[1p]=[J[1p]]}if(z.2l(J[1p])){J[1p].Y(1U)}I{J[1p]=1U}}});C J};z.e1=U;z.e6={"9g":B(1b){C 1b.2G},"2e":B(1b){if(!1o.eo){1z.1K("kH kG kF a kE of 9g/2e-6M-9m"+" 4F kD kC kB kA 4G en kz"+" (ky 1o.eo=K 4F kx kw D kv)")}C z.5m(1b.2G)},"2e-6M-ku":B(1b){A 6N=1b.2G;A 9o=6N.T("/*");A 9n=6N.31("*/");if((9o==-1)||(9n==-1)){C z.5m(1b.2G)}C z.5m(6N.21(9o+2,9n))},"2e-6M-9m":B(1b){A 6L=1b.2G;A 9l=6L.T("/*");A 9k=6L.31("*/");if((9l==-1)||(9k==-1)){1z.1K("kt en ks\'t 6M 9m!");C""}C z.5m(6L.21(9l+2,9k))},"kr":B(1b){C z.3u(1b.2G)},"kq":B(1b){if(z.1l&&!1b.el){z.1n(["ko","em","kn","km"],B(i){1u{A 1e=S 9j(kl[i]+".kk");1e.kj=U;1e.ki(1b.2G);C 1e}1y(e){}})}I{C 1b.el}}};(B(){z.e5=B(F,ej,ei,eh){A 2F={};2F.F=F;A 6J=L;if(F.3R){A 3R=z.1D(F.3R);A 9i=3R.kh("kg");2F.2E=F.2E||(9i?9i.1Z:L);6J=z.6K(3R)}I{2F.2E=F.2E}A 5l=[{}];if(6J){5l.Y(6J)}if(F.5g){5l.Y(F.5g)}if(F.ek){5l.Y({"z.ek":S 5d().8O()})}2F.1r=z.9h(z.1x.14(L,5l));2F.9d=F.9d||"9g";A d=S z.30(ej);d.5k(ei,B(eg){C eh(eg,d)});A ld=F.4E;if(ld&&z.1Y(ld)){d.ef(B(ee){C ld.2d(F,ee,2F)})}A 1G=F.9f;if(1G&&z.1Y(1G)){d.ed(B(e9){C 1G.2d(F,e9,2F)})}A 6I=F.kf;if(6I&&z.1Y(6I)){d.9e(B(e8){C 6I.2d(F,e8,2F)})}d.1F=2F;C d};A e4=B(O){O.e0=K;A 1b=O.1F.1b;if(V 1b.e7=="B"){1b.e7()}};A e3=B(O){C z.e6[O.1F.9d](O.1F.1b)};A e2=B(9c,O){1z.1K(9c);C 9c};A 3Q=B(F){A O=z.e5(F,e4,e3,e2);O.1F.1b=z.9b(O.1F.F);C O};A 5j=L;A 3t=[];A 94=B(){A dZ=(S 5d()).dU();if(!z.e1){z.1n(3t,B(4D,6H){if(!4D){C}A O=4D.O;1u{if(!O||O.e0||!4D.dT(O)){3t.3S(6H,1);C}if(4D.dR(O)){3t.3S(6H,1);4D.dP(O)}I{if(O.9a){if(O.9a+(O.1F.F.6G||0)<dZ){3t.3S(6H,1);A 1G=S 1O("6G ke");1G.dY="6G";O.5i(1G);O.4C()}}}}1y(e){1z.1K(e);O.5i(S 1O("kc!"))}})}if(!3t.G){dX(5j);5j=L;C}};z.dV=B(){1u{z.1n(3t,B(i){i.O.4C()})}1y(e){}};if(z.1l){z.dW(z.dV)}z.dH=B(O,dS,dQ,dO){if(O.1F.F.6G){O.9a=(S 5d()).dU()}3t.Y({O:O,dT:dS,dR:dQ,dP:dO});if(!5j){5j=dN(94,50)}94()};A dJ="8Z/x-kb-3R-ka";A dG=B(O){C O.1F.1b.6F};A dF=B(O){C 4==O.1F.1b.6F};A dE=B(O){if(z.8Y(O.1F.1b)){O.dM(O)}I{O.5i(S 1O("k9 k8 k7 5h:"+O.1F.1b.3N))}};A 3P=B(Z,O){A 3s=O.1F;A F=3s.F;3s.1b.dL(Z,3s.2E,(F.k6!==K),(F.8X?F.8X:1k),(F.8W?F.8W:1k));if(F.6E){R(A 5f in F.6E){if(5f.1M()==="5g-Z"&&!F.8V){F.8V=F.6E[5f]}I{3s.1b.dK(5f,F.6E[5f])}}}3s.1b.dK("k5-k4",(F.8V||dJ));1u{3s.1b.dI(3s.1r)}1y(e){O.4C()}z.dH(O,dG,dF,dE);C O};z.8T=B(4B){if(4B.1r.G){4B.2E+=(4B.2E.T("?")==-1?"?":"&")+4B.1r;4B.1r=L}};z.k3=B(F){A O=3Q(F);z.8T(O.1F);C 3P("dD",O)};z.k2=B(F){C 3P("dC",3Q(F))};z.k1=B(F){A O=3Q(F);O.1F.1r=F.k0;C 3P("dC",O)};z.jZ=B(F){C 3P("dA",3Q(F))};z.jY=B(F){A O=3Q(F);A dB=O.1F;if(F["8U"]){dB.1r=F.8U;F.8U=L}C 3P("dA",O)};z.jX=B(F){A O=3Q(F);z.8T(O.1F);C 3P("8S",O)};z.dz=B(jW){2m S 1O("z.dz 3O jV jU")}})()}if(!z.1h["z.X.fx"]){z.1h["z.X.fx"]=K;z.1Q("z.X.fx");z.dx=B(dy,1d){D.1w=dy;D.1d=1d;D.4x=B(n){C((D.1d-D.1w)*n)+D.1w}};z.2r("z.d6",L,{1P:B(F){z.1x(D,F);if(z.2l(D.2C)){D.2C=S z.dx(D.2C[0],D.2C[1])}},2C:L,8Q:jT,5a:L,4z:0,dj:10,du:L,6x:L,dt:L,8B:L,dh:L,ds:L,dr:L,dm:L,2D:U,2Z:U,4A:L,8N:L,3r:L,2o:0,4y:0,3q:B(H,F){if(D[H]){D[H].14(D,F||[])}C D},5b:B(dw,8R){if(8R){5e(D.3r);D.2D=D.2Z=U;D.2o=0}I{if(D.2D&&!D.2Z){C D}}D.3q("6x");A d=dw||D.du;if(d>0){5c(z.2p(D,B(){D.5b(L,8R)}),d);C D}D.4A=S 5d().8O();if(D.2Z){D.4A-=D.8Q*D.2o}D.8N=D.4A+D.8Q;D.2D=K;D.2Z=U;A 8P=D.2C.4x(D.2o);if(!D.2o){if(!D.4y){D.4y=D.4z}D.3q("dt",[8P])}D.3q("ds",[8P]);D.8M();C D},jS:B(){5e(D.3r);if(!D.2D){C D}D.2Z=K;D.3q("dr",[D.2C.4x(D.2o)]);C D},jR:B(dq,dp){5e(D.3r);D.2D=D.2Z=K;D.2o=dq*6D;if(dp){D.5b()}C D},jQ:B(dn){if(!D.3r){C}5e(D.3r);if(dn){D.2o=1}D.3q("dm",[D.2C.4x(D.2o)]);D.2D=D.2Z=U;C D},3N:B(){if(D.2D){C D.2Z?"3M":"jP"}C"jO"},8M:B(){5e(D.3r);if(D.2D){A dl=S 5d().8O();A 2q=(dl-D.4A)/(D.8N-D.4A);if(2q>=1){2q=1}D.2o=2q;if(D.5a){2q=D.5a(2q)}D.3q("8B",[D.2C.4x(2q)]);if(2q<1){D.3r=5c(z.2p(D,"8M"),D.dj)}I{D.2D=U;if(D.4z>0){D.4z--;D.5b(L,K)}I{if(D.4z==-1){D.5b(L,K)}I{if(D.4y){D.4z=D.4y;D.4y=0}}}D.2o=0;D.3q("dh")}}C D}});(B(){A df=B(E){if(z.1l){A ns=E.1c;if(!ns.8L.G&&z.1c(E,"8L")=="dg"){ns.8L="1"}if(!ns.3n.G&&z.1c(E,"3n")=="8K"){ns.3n="8K"}}};z.6C=B(F){if(V F.1d=="1k"){2m S 1O("z.6C jN an 1d 1Z")}F.E=z.1D(F.E);A 3p=z.1x({6w:{}},F);A 8J=(3p.6w.2W={});8J.1w=(V 3p.1w=="1k")?B(){C 2V(z.1c(3p.E,"2W"))}:3p.1w;8J.1d=3p.1d;A 2U=z.6y(3p);z.2c(2U,"6x",L,B(){df(3p.E)});C 2U};z.8I=B(F){C z.6C(z.1x({1d:1},F))};z.8H=B(F){C z.6C(z.1x({1d:0},F))};if(z.6B&&!z.3o){z.8E=B(n){C 2k("0.5")+((2Y.da((n+2k("1.5"))*2Y.d9))/2)}}I{z.8E=B(n){C 0.5+((2Y.da((n+1.5)*2Y.d9))/2)}}A d4=B(6A){D.8G=6A;R(A p in 6A){A 1a=6A[p];if(1a.1w 1N z.1J){1a.d7=S z.1J()}}D.4x=B(r){A J={};R(A p in D.8G){A 1a=D.8G[p];A 6z=L;if(1a.1w 1N z.1J){6z=z.d8(1a.1w,1a.1d,r,1a.d7).8F()}I{if(!z.2l(1a.1w)){6z=((1a.1d-1a.1w)*r)+1a.1w+(p!="2W"?1a.jM||"px":"")}}J[p]=6z}C J}};z.6y=B(F){F.E=z.1D(F.E);if(!F.5a){F.5a=z.8E}A 2U=S z.d6(F);z.2c(2U,"6x",2U,B(){A pm={};R(A p in D.6w){A 1a=pm[p]=z.1x({},D.6w[p]);if(z.1Y(1a.1w)){1a.1w=1a.1w()}if(z.1Y(1a.1d)){1a.1d=1a.1d()}A d5=(p.1M().T("jL")>=0);B 8C(E,p){4w(p){2X"58":C E.8D;2X"3n":C E.6v}A v=z.1c(E,p);C(p=="2W")?2V(v):2k(v)};if(V 1a.1d=="1k"){1a.1d=8C(D.E,p)}I{if(V 1a.1w=="1k"){1a.1w=8C(D.E,p)}}if(d5){1a.1w=S z.1J(1a.1w);1a.1d=S z.1J(1a.1d)}I{1a.1w=(p=="2W")?2V(1a.1w):2k(1a.1w)}}D.2C=S d4(pm)});z.2c(2U,"8B",2U,B(8A){R(A s in 8A){z.1c(D.E,s,8A[s])}});C 2U}})()}',62,1711,'|||||||||||||||||||||||||||||||||||dojo|var|function|return|this|node|args|length|evt|else|ret|true|null|obj|elem|dfd|arguments|arr|for|new|indexOf|false|typeof||_base|push|type||te|||apply|attr|||||prop|xhr|style|end|doc|match|uri|_hasResource|key|del|undefined|isIE|item|forEach|djConfig|name|document|query|while|_66|try|res|start|mixin|catch|console|split|root|prototype|byId|gcs|ioArgs|err|NodeList|_p|Color|debug|parentNode|toLowerCase|instanceof|Error|constructor|provide|isString|ta|255|val|_a|global|_69|isFunction|value||substring|join|map|tn||window||path|_343|_220|_listeners|connect|call|json|replace|left|_b|toString|128|parseFloat|isArray|throw||_percent|hitch|step|declare|charAt|nodeType|_3c3|nidx|slice|faux|fired|_c4|_7e|loc|curve|_active|url|_44c|responseText|str|_312|idx|tqp|isNaN|isOpera|_22d|callee|add|_18b|_f8|_e2|_41|anim|Number|opacity|case|Math|_paused|Deferred|lastIndexOf|||||||||shift|substr|string|_3e7|_3ce|break|_w|charCode|_listener|_d5|_c5|authority|_49|width|isSafari|_49e|fire|_timer|_47b|_465|eval|_in|_40c|_409|_362|_3d9|className|_3d5|_386|_37a|body|getComputedStyle|box|_221|keyCode|remove|_8d|_46|paused|status|not|_478|_461|form|splice|filter|concat|tret|childNodes|_38b|_367|_33d||||||||||_340|_348|keypress|appendChild|_toArray|Array|_2b0|_toPixelValue|ref|_fixEvent|_19f|_14c|_14a|_150|_141|declaredClass|_d4|_99|_Url|_83|scheme|_67|_3d|switch|getValue|_startRepeatCount|repeat|_startTime|_47e|cancel|tif|load|to|with|tf|getElementsByTagName|number|_34c|_342|extend|_1e3|_normalizeEventName|_14b|_14e|results|self|cbfn|_f9|_d8|_b2|src|_88|dav||baseUrl|fragment|_loadedModules|_44|_43|_loaders|mll|height||easing|play|setTimeout|Date|clearTimeout|hdr|content|code|errback|_464|addCallbacks|_450|fromJson|_413|_3fc|_3ee|max|_31e|cond|getAttribute|_3d4|obi|tagName|_360|_381|contains|firstChild|_368|_372|_320|place|_2fa|scrollTop|_299|scrollLeft|top|documentElement|_288|_287|_getBorderExtents|_23f|_23d|_239|_218|_216|_211|eles|target|keys|shiftKey|ctrlKey|event|192|iel|_1db|delete|_1cf||addEventListener|String|_1af|_157|array|_14d|continue|_14f|_137|_11f|_106|_findMethod|has|_delegate|_dc|_d3|loaded|_9a|_loadInit|_inFlightCount|getObject|tv|_4f|_postLoad|_2d|offsetWidth|properties|beforeBegin|animateProperty|_4ad|_4a6|isKhtml|_fade|100|headers|readyState|timeout|_469|_457|_44d|formToObject|_441|comment|_43d|_36f|_419|tp|_40a|_406|_407|_373|_403|_3e6|_31b|cbi|test|_3c7|nextSibling|last|_3a1|_38e|_365|_36b|ecn|_364|_363|_356|_35e|_35f|_34f|_34d|_349|trim|tci|_328|_32b|_31f|_31c|_anim|_300|_2ff|_2f5|_2e7|removeClass|addClass|func|_2c4|cls|_2a9|_2ae|_280|_27f|_getPadExtents|isMoz|none|_233|cssText|_214|_fixCallback|_synthesizeEvent|stopPropagation|preventDefault|_setKeyChar|_1e1|ieh|_1d7|_1be|colorFromArray|sanitize|bits|rgb|_156|_fire|_resback|_13d|partial|_13a|silentlyCancelled|_topics|_127|_f1|_f0|superclass|_ec|_e3|mct|setObject|_bf|_b3|object|require|_92|_khtmlTimer|location|XMLHTTP|locale|dua|_71|_modulePrefixes|_55|_loadModule|_51|_50|_4e|pop|_3f|_callLoaded|_unloaders|_loadNotifying|_loadedUrls|_27|_24|_1d|_5|_4b7|onAnimate|getStyle|offsetHeight|_defaultEasing|toCss|_properties|fadeOut|fadeIn|_49f|auto|zoom|_cycle|_endTime|valueOf|_494|duration|_492|DELETE|_ioAddQueryToUrl|putData|contentType|password|user|_isDocumentOk|application|||||_466||||||startTime|_xhrObj|_45f|handleAs|addBoth|error|text|objectToQuery|_44f|ActiveXObject|_443|_442|filtered|_43f|_43e|_437|file|tnl|_41c|_filterQueryResult|_zipIdx|_408|_402|evaluate|_3ed|_380|fHit|_361|_33b|_3da|_3ab|_3d6|RegExp|_327|_3cf|_3c9|child|innerHTML|first|tval|_391|class|pnc|_37e|_37c|_375|_366|_35c|_35a|_353|_33c|_336|_314|||_315|_oe|_307|_309|cloneNode|after|createElement||_2f8|_2ef|_2ee|unshift|coords|some|every||_2cb|script|_2c9|parent||a2p||_2c3|_2bd||abs|_getMarginBox|_2b3|_2a6|position|_2a7|_2ac|_2ab|_getIeDocumentElementOffset|getBoundingClientRect|ownerDocument|_2a3|clientWidth|_isBodyLtr|_fixIeBiDiScrollLeft|_bodyLtr|_29d|_getContentBox|_setBox|_getMarginExtents|_getPadBorderExtents|_usesBorderBox|boxModel|pcs|st|sl|_240|runtimeStyle|_dcm|BackCompat|compatMode|default|_21b|_d|html|_event_listener|handlers|PAGE_DOWN|PAGE_UP|RIGHT_ARROW|LEFT_ARROW|DOWN_ARROW|UP_ARROW|_preventDefault||_stopPropagation|returnValue||_trySetKeyCode|cancelBubble|currentTarget|106|_1ee|111||_1e8|_1e7|||se|srcElement|onkeydown||_1d0|_disconnect|lid|_1c0|_connect|_set|_195|_185|_183|_17d|_everyOrSome|_16b|_172|_15b|Function|_154|_escapeString|_140|chain|_check|canceller|_12d|_124|_11a|_10d|_107|inherited|_fa|_f2|_findMixin|_constructor|preamble|_de|clone|tmp|_c7|TMP|_be|_ba|_mixin|isBrowser|lang|firebug||param|modulePaths|_a7|_fireCallback|_a0|setContext||_9c|unloaded||||_96|_93|navigator|_90|_89||protocol|_84|_86|_XMLHTTP_PROGIDS|gears|google|setAttribute|_80|_77|cfg|_6f|_getModuleSymbols|_5a|_58|_53|_4d|_4c|_45|_40|_moduleHasPrefix|_loadUri|_28|_26|_21|_22|tests|doh|_20|_1f|_1c|version|_1b|_19|_getProp|_11|_4|_4a5|_4b3|_Animation|tempColor|blendColors|PI|sin|||||_49a|normal|onEnd||rate||curr|onStop|_497||_496|pct|onPause|onPlay|onBegin|delay||_491|_Line|_48b|wrapForm|PUT|_487|POST|GET|_476|_474|_472|_ioWatch|send|_471|setRequestHeader|open|callback|setInterval|_470|resHandle|_46f|ioCheck|_46e|validCheck|getTime|_ioCancelAll|addOnUnload|clearInterval|dojoType|now|canceled|_blockAsync|_45e|_45c|_459|_ioSetArgs|_contentHandlers|abort|_458|_456||||addErrback|_454|addCallback|_452|_44b|_44a|_449|preventCache|responseXML|Microsoft|JSON|usePlainJson|_431|toJson|_430|_42d|image|opt|ria|_421|_41b|_40b|_zip|_410|_40d|_357|sqf|_374|_3e5|_3df|_38f|clc|pred|parseInt|ntf|_3bf|_3bc|cnl|previousSibling|_3a9|_3a6|_39c|_399|_396|_392|__cachedIndex|__cachedLength|_376|iterateNext|_34a|_355|_354|_32c|_350|_34b|_33f|_33e|_33a|_338|_334|_332||_330|_32e||_322|_316|mousemove|mouseout|mouseover|_305|lastChild||_2f9||_2f2|_2f1|removeChild|_2ec|_2eb|_2ea|_2e6||_2e4|_2e2|_2d6|_2d5|_2d4|_2d3|_2d2|_2d1|_2cd|_2cc|scs|write|_2c8|hasClass|_2c0|_2bb|_2b5|_abs|_docScroll|offsetParent|offsetTop|offsetLeft|absolute|getBoxObjectFor|clientLeft|_setContentSize|_setMarginBox|_28d|_286|_285|_289|NaN|_281|border|_272|_26b|_260|_258|_253|_24c|_246|_23a|_getOpacity|_setOpacity|_238|td|tr|nodeName|FILTER|_22f|_22e|currentStyle|_22c|_22b|display|QuirksMode|unselectable|_217|isMozilla|getElementById|attributes|all|_ie_listener|_getIeDispatcher|_1fd|NUM_LOCK|SCROLL_LOCK|INSERT|END|HOME|PAUSE|F12|F11|F10|F9|F8|F7|F6|F5|F4|F3|F2|F1|63232|SHIFT_TAB|TAB|keyIdentifier|_1f3|stopEvent|_punctMap|222|219|186|onkeypress|_stealthKeyDown|_fixKeys|relatedTarget|_1e0|_1df|_stealthKeydown|_1d6|_1d5|_1d1|_1ca|_1c9|_1cb|_1c2|_1c1|_1c3|_1c4|_1bc|_1b3|_1b2|colorFromHex|colorFromRgb|named|colorFromString|mask|rgba|_19c|_197|_192|setColor|_180|_178|_177|_175|_174|_16d|_166|_164|_163|_162|_15c|_15d|_15e|index|__json__|toJsonIndentStr|_nextId|_12f|_12b|publish|_128|_126|_125|_122|_121|_123|_11c|_11b|_10c|_10b|_108|getDispatcher|argument|nom|_construct|_core|_makeCtor|_df|_db|deprecated|isObject|_cc||scope||_hitchArgs|_c2||pre|_c1|native|isDebug||registerModulePath|_a8||finally|||_a6|_a5|_a4|_a3|_a2|_a1|_9f|_9e|_9d|_9b|_98|_97|onbeforeunload|ipt|scr|complete|_95|userAgent|_modulesLoaded|initialized|_initFired|_8c|_8a|_getText|_87|ieForceActiveXXhr|Msxml2|isGears|_81|_gearsObject|googlegears|GearsFactory|isFF|_7d|Safari|_72|_name|_6c|ire|ore|_68|i18n|_5b|requireIf|_56|_52|loading|_4a|_loadPath|_47|_48|_global_omit_module_check|_getModulePrefix|_3c|_3a|_37|_30|Boolean|_loadUriAndCheck|_2e||cacheBust|_1e|_1a|_17|_16|_15|_14|_f|_10|_e|_9|_8|revision|flag|patch|minor|major|_6|color|units|needs|stopped|playing|stop|gotoPercent|pause|1000|implemented|yet|_48a|xhrDelete|rawXhrPut|xhrPut|postData|rawXhrPost|xhrPost|xhrGet|Type|Content|sync|response|http|bad|urlencoded|www|_watchInFlightError||exceeded|handle|action|getAttributeNode|loadXML|async|XMLDOM|prefixes|MSXML3|MSXML|MSXML2||xml|javascript|wasn|your|optional|message|off|turn|use|endpoints|issues|security|potential|avoid|mimetype|using|consider|please|decodeURIComponent|queryToObject|formToJson|formToQuery|encodeURIComponent|selected|option|multiple|checked|checkbox|radio|disabled|textarea|select|button|reset|submit|input|_3fb|hasAttribute|0n|even|odd|nth|_3b5|empty|_3b1|_3ad|htmlFor|_38a|under||exprssion|failure|ANY_TYPE|XPathResult|starts|keyup|keydown|mouseup|mousedown|blur|click|combine|span|addContent||adopt|orphan|_2de|_2dd|styles|_2da|_2d9|_2cf|_2ce|show|createPopup|toggleClass|scrollWidth|clientTop|ltr|direction|pageXOffset|pageYOffset|fixed|contentBox|marginBox|BUTTON|TABLE|_getBorderBox|clientHeight|visible|overflow|marginBottom|marginRight|marginTop|marginLeft|borderBottomWidth|borderBottomStyle|borderRightWidth|borderRightStyle|borderTopWidth|borderTopStyle|borderLeftWidth|borderLeftStyle|paddingBottom|paddingRight|paddingTop|paddingLeft|offset||min|padding||margin|Opacity|Alpha|alpha|filters|pixelLeft|medium|_22a|defaultView|before||insertBefore|KhtmlUserSelect|MozUserSelect|setSelectable|isDescendant|div|_destroyElement|BackgroundImageCache|execCommand|PageDown|PageUp|Right|Left|Down|Up|63289|63249|63248|PRINT_SCREEN|63302|63277|63276|63275|63273|63272|63250|63247|63246|63245|63244|63243|63242|63241|63240|63239|63238|63237|63236|63235|63234|63233|Enter|_1f9|which|_1f6|bubbledKeyCode|221|220||||191|190|189|188|187|toElement|fromElement|clientY|pageY||clientX|pageX|offsetY|||layerY|offsetX|layerX|parentWindow|_nop|_allow_leaks|145|144|126|F15|125|F14|124|F13|123|122|121|120|119|118|117|116|115|114|113|112|NUMPAD_DIVIDE|110|NUMPAD_PERIOD|109|NUMPAD_MINUS|108|NUMPAD_ENTER|107|NUMPAD_PLUS|NUMPAD_MULTIPLY|105|NUMPAD_9|104|NUMPAD_8|103|NUMPAD_7|102|NUMPAD_6|101|NUMPAD_5|NUMPAD_4||NUMPAD_3|NUMPAD_2|NUMPAD_1|NUMPAD_0||SELECT|RIGHT_WINDOW||LEFT_WINDOW||HELP|SPACE|ESCAPE|CAPS_LOCK|ALT|CTRL|SHIFT|ENTER|CLEAR|BACKSPACE|attachEvent|fixEvent|fromCharCode|keyChar|_1b9|removeEventListener|0x|round|toHex|toRgba|toRgb|aqua|teal|blue|navy|yellow|olive|lime|green|fuchsia|purple|red|maroon|white|gray|silver|black|boolean|called|already|Cancelled|connectPublisher|unsubscribe|subscribe|disconnect|_113|_112||_111|_110|||found|was||must|_|module|||required|likely|It|declaration|Mixin|separate|instead|property|initializer||pass|_c9|_bb|_b7|nfunction|isAlien|isFinite|isArrayLike|_firebug|withDoc|withGlobal|_writeIncludes|VML|behavior|addRule|createStyleSheet|vml|com|microsoft|schemas|urn|namespaces|onunload|onreadystatechange|defer|khtml|WebKit|DOMContentLoaded|enableMozDomContentLoaded|domcontentloaded|Unable|base|chrome|1223|304|300|200|available|XMLHttpRequest|_println|language|userLanguage|isQuirks|factory|mimeTypes|Factory|Gears|_7f|MSIE||Firefox|Gecko|Konqueror||Opera|appVersion|xd|browser|moduleUrl|port|host|hostenv|_requireLocalization|_5f|_5e|_5d|_5c|requireLocalization|requireAfterIf|_57|common|platformRequire|defined|symbol|_isXDomain|tried|Could|__package__|packageFileName|_42|useXDomain|flight|still|files|addOnLoad|failed|sourceURL|util|notice|without|change|subject|APIs|EXPERIMENTAL|experimental|removed|will|DEPRECATED|exists|10315|Rev|Mobile|Spidermonkey|Rhino||Browser|delayMozLoadingFix|preventBackButtonFix|libraryScriptUri|baseRelativePath|baseScriptUri|allowQueryConfig|warn|trace|timeEnd||time|profileEnd|profile|log|info|groupEnd|group|dirxml|dir|count|assert'.split('|'),0,{}); + + +/* + +Prototype 1.5 rc0 + - Adapted from Ruby on Rails - http://dev.rubyonrails.org/browser/spinoffs/prototype/src + - By Lunarmedia, 06 August, 2006 + - Available at (and packed with) JavascriptCompressor.com + +Please note this version is missing the selector.js component of the full Prototype library. +You can get the compressed version of selector at JavascriptCompressor.com + +*/ + +var decompressedPrototype = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[(function(e){return d[e]})];e=(function(){return'\\w+'});c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('d T={4l:\'1.5.8P\',3E:\'(?:<3G.*?>)((\\n|\\r|.)*?)(?:<\\/3G>)\',2v:7(){},K:7(x){c x}};d 1b={17:7(){c 7(){6.1I.2n(6,N)}}};d 1e=z q();q.u=7(5d,O){G(d 1G 2M O){5d[1G]=O[1G]}c 5d};q.1U=7(U){1j{f(U==1v)c\'1v\';f(U==1L)c\'1L\';c U.1U?U.1U():U.2C()}1s(e){f(e 8R 9l)c\'...\';25 e}};7j.v.1d=7(){d 43=6,23=$A(N),U=23.8S();c 7(){c 43.2n(U,23.3s($A(N)))}};7j.v.8U=7(U){d 43=6;c 7(C){c 43.8V(U,C||1W.C)}};q.u(8Q.v,{8W:7(){d 4Z=6.2C(16);f(6<16)c\'0\'+4Z;c 4Z},5j:7(){c 6+1},8Y:7(o){$R(0,6,11).V(o);c 6}});d 6s={6j:7(){d 48;G(d i=0;i<N.t;i++){d 6L=N[i];1j{48=6L();1y}1s(e){}}c 48}};d 6Q=1b.17();6Q.v={1I:7(1a,1J){6.1a=1a;6.1J=1J;6.41=Y;6.2A()},2A:7(){5Z(6.2D.1d(6),6.1J*4z)},2D:7(){f(!6.41){1j{6.41=11;6.1a()}8Z{6.41=Y}}}};q.u(4b.v,{2T:7(1A,1z){d L=\'\',O=6,I;1z=N.90.52(1z);1H(O.t>0){f(I=O.I(1A)){L+=O.47(0,I.w);L+=(1z(I)||\'\').2C();O=O.47(I.w+I[0].t)}1D{L+=O,O=\'\'}}c L},92:7(1A,1z,3i){1z=6.2T.52(1z);3i=3i===1v?1:3i;c 6.2T(1A,7(I){f(--3i<0)c I[0];c 1z(I)})},93:7(1A,o){6.2T(1A,o);c 6},94:7(t,2S){t=t||30;2S=2S===1v?\'...\':2S;c 6.t>t?6.47(0,t-2S.t)+2S:6},9F:7(){c 6.2y(/^\\s+/,\'\').2y(/\\s+$/,\'\')},71:7(){c 6.2y(/<\\/?[^>]+>/7Y,\'\')},2Q:7(){c 6.2y(z 3O(T.3E,\'5P\'),\'\')},70:7(){d 6Y=z 3O(T.3E,\'5P\');d 5p=z 3O(T.3E,\'98\');c(6.I(6Y)||[]).1C(7(5o){c(5o.I(5p)||[\'\',\'\'])[1]})},3q:7(){c 6.70().1C(7(3G){c 4q(3G)})},9E:7(){d 1q=J.4Y(\'1q\');d 1Y=J.9D(6);1q.75(1Y);c 1q.3h},9c:7(){d 1q=J.4Y(\'1q\');1q.3h=6.71();c 1q.2z[0]?1q.2z[0].6q:\'\'},78:7(){d 7i=6.I(/^\\??(.*)$/)[1].3j(\'&\');c 7i.36({},7(5b,72){d 1i=72.3j(\'=\');5b[1i[0]]=1i[1];c 5b})},1Z:7(){c 6.3j(\'\')},3P:7(){d 2l=6.3j(\'-\');f(2l.t==1)c 2l[0];d 54=6.5g(\'-\')==0?2l[0].7e(0).3Y()+2l[0].7g(1):2l[0];G(d i=1,73=2l.t;i<73;i++){d s=2l[i];54+=s.7e(0).3Y()+s.7g(1)}c 54},1U:7(){c"\'"+6.2y(/\\\\/g,\'\\\\\\\\\').2y(/\'/g,\'\\\\\\\'\')+"\'"}});4b.v.2T.52=7(1z){f(2i 1z==\'7\')c 1z;d 2U=z 3n(1z);c 7(I){c 2U.7a(I)}};4b.v.9h=4b.v.78;d 3n=1b.17();3n.79=/(^|.|\\r|\\n)(#\\{(.*?)\\})/;3n.v={1I:7(2U,1A){6.2U=2U.2C();6.1A=1A||3n.79},7a:7(U){c 6.2U.2T(6.1A,7(I){d 53=I[1];f(53==\'\\\\\')c I[2];c 53+(U[I[3]]||\'\').2C()})}};d $1y=z q();d $49=z q();d 1p={V:7(o){d w=0;1j{6.2m(7(h){1j{o(h,w++)}1s(e){f(e!=$49)25 e}})}1s(e){f(e!=$1y)25 e}},9n:7(o){d L=11;6.V(7(h,w){L=L&&!!(o||T.K)(h,w);f(!L)25 $1y});c L},9o:7(o){d L=11;6.V(7(h,w){f(L=!!(o||T.K)(h,w))25 $1y});c L},3e:7(o){d P=[];6.V(7(h,w){P.W(o(h,w))});c P},7n:7(o){d L;6.V(7(h,w){f(o(h,w)){L=h;25 $1y}});c L},7o:7(o){d P=[];6.V(7(h,w){f(o(h,w))P.W(h)});c P},9p:7(1A,o){d P=[];6.V(7(h,w){d 7c=h.2C();f(7c.I(1A))P.W((o||T.K)(h,w))});c P},1M:7(U){d 51=Y;6.V(7(h){f(h==U){51=11;25 $1y}});c 51},36:7(45,o){6.V(7(h,w){45=o(45,h,w)});c 45},9q:7(1F){d 23=$A(N).47(1);c 6.3e(7(h){c h[1F].2n(h,23)})},9s:7(o){d L;6.V(7(h,w){h=(o||T.K)(h,w);f(L==1v||h>=L)L=h});c L},9u:7(o){d L;6.V(7(h,w){h=(o||T.K)(h,w);f(L==1v||h<L)L=h});c L},9v:7(o){d 50=[],58=[];6.V(7(h,w){((o||T.K)(h,w)?50:58).W(h)});c[50,58]},3r:7(1G){d P=[];6.V(7(h,w){P.W(h[1G])});c P},9x:7(o){d P=[];6.V(7(h,w){f(!o(h,w))P.W(h)});c P},9y:7(o){c 6.3e(7(h,w){c{h:h,59:o(h,w)}}).9z(7(18,3U){d a=18.59,b=3U.59;c a<b?-1:a>b?1:0}).3r(\'h\')},1Z:7(){c 6.3e(T.K)},9B:7(){d o=T.K,23=$A(N);f(2i 23.5e()==\'7\')o=23.9C();d 7l=[6].3s(23).1C($A);c 6.1C(7(h,w){c o(7l.3r(w))})},1U:7(){c\'#<1p:\'+6.1Z().1U()+\'>\'}};q.u(1p,{1C:1p.3e,5v:1p.7n,1k:1p.7o,8M:1p.1M,7p:1p.1Z});d $A=1E.7q=7(2R){f(!2R)c[];f(2R.1Z){c 2R.1Z()}1D{d P=[];G(d i=0;i<2R.t;i++)P.W(2R[i]);c P}};q.u(1E.v,1p);f(!1E.v.4d)1E.v.4d=1E.v.4m;q.u(1E.v,{2m:7(o){G(d i=0;i<6.t;i++)o(6[i])},5i:7(){6.t=0;c 6},7r:7(){c 6[0]},5e:7(){c 6[6.t-1]},7s:7(){c 6.1k(7(h){c h!=1v||h!=1L})},6J:7(){c 6.36([],7(6H,h){c 6H.3s(h&&h.5D==1E?h.6J():[h])})},5s:7(){d 4N=$A(N);c 6.1k(7(h){c!4N.1M(h)})},5g:7(U){G(d i=0;i<6.t;i++)f(6[i]==U)c i;c-1},4m:7(5h){c(5h!==Y?6:6.1Z()).4d()},1U:7(){c\'[\'+6.1C(q.1U).1N(\', \')+\']\'}});d 4h={2m:7(o){G(d 1O 2M 6){d h=6[1O];f(2i h==\'7\')49;d 1i=[1O,h];1i.1O=1O;1i.h=h;o(1i)}},7t:7(){c 6.3r(\'1O\')},4N:7(){c 6.3r(\'h\')},7u:7(2N){c $H(2N).36($H(6),7(4Q,1i){4Q[1i.1O]=1i.h;c 4Q})},7w:7(){c 6.1C(7(1i){c 1i.1C(4n).1N(\'=\')}).1N(\'&\')},1U:7(){c\'#<4h:{\'+6.1C(7(1i){c 1i.1C(q.1U).1N(\': \')}).1N(\', \')+\'}>\'}};7 $H(U){d 2N=q.u({},U||{});q.u(2N,1p);q.u(2N,4h);c 2N};3L=1b.17();q.u(3L.v,1p);q.u(3L.v,{1I:7(22,2x,2H){6.22=22;6.2x=2x;6.2H=2H},2m:7(o){d h=6.22;2q{o(h);h=h.5j()}1H(6.1M(h))},1M:7(h){f(h<6.22)c Y;f(6.2H)c h<6.2x;c h<=6.2x}});d $R=7(22,2x,2H){c z 3L(22,2x,2H)};d M={4w:7(){c 6s.6j(7(){c z 5C()},7(){c z 5n(\'7y.6d\')},7(){c z 5n(\'7z.6d\')})||Y},4s:0};M.2W={3b:[],2m:7(o){6.3b.2m(o)},69:7(4F){f(!6.1M(4F))6.3b.W(4F)},7A:7(5t){6.3b=6.3b.5s(5t)},3y:7(1a,26,E,2Z){6.V(7(3o){f(3o[1a]&&2i 3o[1a]==\'7\'){1j{3o[1a].2n(3o,[26,E,2Z])}1s(e){}}})}};q.u(M.2W,1p);M.2W.69({5G:7(){M.4s++},1B:7(){M.4s--}});M.44=7(){};M.44.v={4a:7(m){6.m={1F:\'4j\',4p:11,5H:\'5E/x-86-Q-7C\',28:\'\'};q.u(6.m,m||{})},3l:7(){c 6.E.32==1v||6.E.32==0||(6.E.32>=84&&6.E.32<7E)},7G:7(){c!6.3l()}};M.3t=1b.17();M.3t.5L=[\'7H\',\'80\',\'7I\',\'7J\',\'4t\'];M.3t.v=q.u(z M.44(),{1I:7(1l,m){6.E=M.4w();6.4a(m);6.26(1l)},26:7(1l){d 28=6.m.28||\'\';f(28.t>0)28+=\'&7K=\';1j{6.1l=1l;f(6.m.1F==\'7L\'&&28.t>0)6.1l+=(6.1l.I(/\\?/)?\'&\':\'?\')+28;M.2W.3y(\'5G\',6,6.E);6.E.7N(6.m.1F,6.1l,6.m.4p);f(6.m.4p){6.E.5T=6.5J.1d(6);2Y((7(){6.4r(1)}).1d(6),10)}6.5A();d 1c=6.m.5V?6.m.5V:28;6.E.7O(6.m.1F==\'4j\'?1c:1L)}1s(e){6.3p(e)}},5A:7(){d 1P=[\'X-7P-7Q\',\'5C\',\'X-T-4l\',T.4l,\'7R\',\'1Y/7m, 1Y/2e, 5E/5F, 1Y/5F, */*\'];f(6.m.1F==\'4j\'){1P.W(\'5Q-2g\',6.m.5H);f(6.E.7S)1P.W(\'7T\',\'7U\')}f(6.m.1P)1P.W.2n(1P,6.m.1P);G(d i=0;i<1P.t;i+=2)6.E.7V(1P[i],1P[i+1])},5J:7(){d 2F=6.E.2F;f(2F!=1)6.4r(6.E.2F)},4A:7(B){1j{c 6.E.7W(B)}1s(e){}},5M:7(){1j{c 4q(\'(\'+6.4A(\'X-7X\')+\')\')}1s(e){}},5R:7(){1j{c 4q(6.E.3F)}1s(e){6.3p(e)}},4r:7(2F){d C=M.3t.5L[2F];d E=6.E,2Z=6.5M();f(C==\'4t\'){1j{(6.m[\'2I\'+6.E.32]||6.m[\'2I\'+(6.3l()?\'81\':\'82\')]||T.2v)(E,2Z)}1s(e){6.3p(e)}f((6.4A(\'5Q-2g\')||\'\').I(/^1Y\\/7m/i))6.5R()}1j{(6.m[\'2I\'+C]||T.2v)(E,2Z);M.2W.3y(\'2I\'+C,6,E,2Z)}1s(e){6.3p(e)}f(C==\'4t\')6.E.5T=T.2v},3p:7(57){(6.m.5W||T.2v)(6,57);M.2W.3y(\'5W\',6,57)}});M.4C=1b.17();q.u(q.u(M.4C.v,M.3t.v),{1I:7(1w,1l,m){6.4x={3m:1w.3m?$(1w.3m):$(1w),3z:1w.3z?$(1w.3z):(1w.3m?1L:$(1w))};6.E=M.4w();6.4a(m);d 1B=6.m.1B||T.2v;6.m.1B=(7(E,U){6.5Y();1B(E,U)}).1d(6);6.26(1l)},5Y:7(){d 3A=6.3l()?6.4x.3m:6.4x.3z;d 3k=6.E.3F;f(!6.m.3q)3k=3k.2Q();f(3A){f(6.m.60){z 6.m.60(3A,3k)}1D{k.6h(3A,3k)}}f(6.3l()){f(6.1B)2Y(6.1B.1d(6),10)}}});M.61=1b.17();M.61.v=q.u(z M.44(),{1I:7(1w,1l,m){6.4a(m);6.1B=6.m.1B;6.1J=(6.m.1J||2);6.2s=(6.m.2s||1);6.4B={};6.1w=1w;6.1l=1l;6.22()},22:7(){6.m.1B=6.63.1d(6);6.2D()},7b:7(){6.4B.1B=1v;89(6.65);(6.1B||T.2v).2n(6,N)},63:7(26){f(6.m.2s){6.2s=(26.3F==6.64?6.2s*6.m.2s:1);6.64=26.3F}6.65=2Y(6.2D.1d(6),6.2s*6.1J*4z)},2D:7(){6.4B=z M.4C(6.1w,6.1l,6.m)}});7 $(){d P=[],4;G(d i=0;i<N.t;i++){4=N[i];f(2i 4==\'8c\')4=J.8d(4);P.W(k.u(4))}c P.t<2?P[0]:P};J.8f=7(1f,6a){d 6b=($(6a)||J.1c).4D(\'*\');c $A(6b).36([],7(12,4E){f(4E.1f.I(z 3O("(^|\\\\s)"+1f+"(\\\\s|$)")))12.W(k.u(4E));c 12})};f(!1W.k)d k=z q();k.u=7(4){f(!4)c;f(4X)c 4;f(!4.6e&&4.1h&&4!=1W){d 2a=k.3d,2r=k.u.2r;G(d 1G 2M 2a){d h=2a[1G];f(2i h==\'7\')4[1G]=2r.4W(h)}}4.6e=11;c 4};k.u.2r={4W:7(h){c 6[h]=6[h]||7(){c h.2n(1L,[6].3s($A(N)))}}};k.3d={4U:7(4){c $(4).l.2B!=\'3Q\'},6N:7(){G(d i=0;i<N.t;i++){d 4=$(N[i]);k[k.4U(4)?\'6f\':\'6w\'](4)}},6f:7(){G(d i=0;i<N.t;i++){d 4=$(N[i]);4.l.2B=\'3Q\'}},6w:7(){G(d i=0;i<N.t;i++){d 4=$(N[i]);4.l.2B=\'\'}},42:7(4){4=$(4);4.1X.8h(4)},6h:7(4,2e){$(4).3h=2e.2Q();2Y(7(){2e.3q()},10)},2y:7(4,2e){4=$(4);f(4.6k){4.6k=2e.2Q()}1D{d 1K=4.6R.6S();1K.56(4);4.1X.8i(1K.6T(2e.2Q()),4)}2Y(7(){2e.3q()},10)},8k:7(4){4=$(4);c 4.2k},3K:7(4){c z k.3S(4)},8l:7(4,1f){f(!(4=$(4)))c;c k.3K(4).1M(1f)},8m:7(4,1f){f(!(4=$(4)))c;c k.3K(4).7k(1f)},8n:7(4,1f){f(!(4=$(4)))c;c k.3K(4).42(1f)},8p:7(4){4=$(4);G(d i=0;i<4.2z.t;i++){d 3M=4.2z[i];f(3M.8q==3&&!/\\S/.4v(3M.6q))k.42(3M)}},8r:7(4){c $(4).3h.I(/^\\s*$/)},8s:7(4,3I){4=$(4),3I=$(3I);1H(4=4.1X)f(4==3I)c 11;c Y},6t:7(4){4=$(4);d x=4.x?4.x:4.2f,y=4.y?4.y:4.29;1W.6t(x,y)},1R:7(4,l){4=$(4);d h=4.l[l.3P()];f(!h){f(J.4J&&J.4J.6v){d 4L=J.4J.6v(4,1L);h=4L?4L.8v(l):1L}1D f(4.6x){h=4.6x[l.3P()]}}f(1W.6E&&[\'18\',\'1n\',\'3U\',\'6G\'].1M(l))f(k.1R(4,\'14\')==\'4G\')h=\'6y\';c h==\'6y\'?1L:h},8x:7(4,l){4=$(4);G(d B 2M l)4.l[B.3P()]=l[B]},8y:7(4){4=$(4);f(k.1R(4,\'2B\')!=\'3Q\')c{21:4.2p,24:4.2k};d 20=4.l;d 6B=20.4O;d 6A=20.14;20.4O=\'31\';20.14=\'2o\';20.2B=\'\';d 6C=4.6m;d 6D=4.6p;20.2B=\'3Q\';20.14=6A;20.4O=6B;c{21:6C,24:6D}},8z:7(4){4=$(4);d 4R=k.1R(4,\'14\');f(4R==\'4G\'||!4R){4.4T=11;4.l.14=\'3T\';f(1W.6E){4.l.1n=0;4.l.18=0}}},8A:7(4){4=$(4);f(4.4T){4.4T=1v;4.l.14=4.l.1n=4.l.18=4.l.6G=4.l.3U=\'\'}},8B:7(4){4=$(4);f(4.3c)c;4.3c=4.l.3V;f((k.1R(4,\'3V\')||\'4U\')!=\'31\')4.l.3V=\'31\'},8D:7(4){4=$(4);f(4.3c)c;4.l.3V=4.3c;4.3c=1v}};q.u(k,k.3d);d 4X=Y;f(!3W&&/3x|3w|3u/.4v(33.62)){d 3W={}};k.6K=7(2a){q.u(k.3d,2a||{});f(2i 3W!=\'1v\'){d 2a=k.3d,2r=k.u.2r;G(d 1G 2M 2a){d h=2a[1G];f(2i h==\'7\')3W.v[1G]=2r.4W(h)}4X=11}};k.6K();d 6M=z q();6M.2B=k.6N;1e.1g=7(3f){6.3f=3f};1e.1g.v={1I:7(4,2t){6.4=$(4);6.2t=2t.2Q();f(6.3f&&6.4.6O){1j{6.4.6O(6.3f,6.2t)}1s(e){d 1h=6.4.1h.2w();f(1h==\'4V\'||1h==\'8N\'){6.2X(6.6U())}1D{25 e}}}1D{6.1K=6.4.6R.6S();f(6.2V)6.2V();6.2X([6.1K.6T(6.2t)])}2Y(7(){2t.3q()},10)},6U:7(){d 1q=J.4Y(\'1q\');1q.3h=\'<6V><4V>\'+6.2t+\'</4V></6V>\';c $A(1q.2z[0].2z[0].2z)}};d 1g=z q();1g.6W=1b.17();1g.6W.v=q.u(z 1e.1g(\'96\'),{2V:7(){6.1K.97(6.4)},2X:7(2h){2h.V((7(2j){6.4.1X.55(2j,6.4)}).1d(6))}});1g.5m=1b.17();1g.5m.v=q.u(z 1e.1g(\'99\'),{2V:7(){6.1K.56(6.4);6.1K.74(11)},2X:7(2h){2h.4m(Y).V((7(2j){6.4.55(2j,6.4.9a)}).1d(6))}});1g.7h=1b.17();1g.7h.v=q.u(z 1e.1g(\'9d\'),{2V:7(){6.1K.56(6.4);6.1K.74(6.4)},2X:7(2h){2h.V((7(2j){6.4.75(2j)}).1d(6))}});1g.76=1b.17();1g.76.v=q.u(z 1e.1g(\'9i\'),{2V:7(){6.1K.9m(6.4)},2X:7(2h){2h.V((7(2j){6.4.1X.55(2j,6.4.9t)}).1d(6))}});k.3S=1b.17();k.3S.v={1I:7(4){6.4=$(4)},2m:7(o){6.4.1f.3j(/\\s+/).1k(7(B){c B.t>0}).2m(o)},5c:7(1f){6.4.1f=1f},7k:7(5a){f(6.1M(5a))c;6.5c(6.1Z().3s(5a).1N(\' \'))},42:7(4c){f(!6.1M(4c))c;6.5c(6.1k(7(1f){c 1f!=4c}).1N(\' \'))},2C:7(){c 6.1Z().1N(\' \')}};q.u(k.3S.v,1p);d 5I={5i:7(){G(d i=0;i<N.t;i++)$(N[i]).h=\'\'},4f:7(4){$(4).4f()},7v:7(){G(d i=0;i<N.t;i++)f($(N[i]).h==\'\')c Y;c 11},1k:7(4){$(4).1k()},5y:7(4){4=$(4);4.4f();f(4.1k)4.1k()}};d D={3a:7(Q){d 12=D.2L($(Q));d 4I=z 1E();G(d i=0;i<12.t;i++){d 4g=D.k.3a(12[i]);f(4g)4I.W(4g)}c 4I.1N(\'&\')},2L:7(Q){Q=$(Q);d 12=z 1E();G(d 1h 2M D.k.2E){d 4H=Q.4D(1h);G(d j=0;j<4H.t;j++)12.W(4H[j])}c 12},7x:7(Q,3N,B){Q=$(Q);d 3H=Q.4D(\'2u\');f(!3N&&!B)c 3H;d 4y=z 1E();G(d i=0;i<3H.t;i++){d 2u=3H[i];f((3N&&2u.2g!=3N)||(B&&2u.B!=B))49;4y.W(2u)}c 4y},7B:7(Q){d 12=D.2L(Q);G(d i=0;i<12.t;i++){d 4=12[i];4.7D();4.4o=\'11\'}},7F:7(Q){d 12=D.2L(Q);G(d i=0;i<12.t;i++){d 4=12[i];4.4o=\'\'}},5z:7(Q){c D.2L(Q).5v(7(4){c 4.2g!=\'31\'&&!4.4o&&[\'2u\',\'1k\',\'3J\'].1M(4.1h.2w())})},7M:7(Q){5I.5y(D.5z(Q))},5w:7(Q){$(Q).5w()}};D.k={3a:7(4){4=$(4);d 1F=4.1h.2w();d 1S=D.k.2E[1F](4);f(1S){d 1O=4n(1S[0]);f(1O.t==0)c;f(1S[1].5D!=1E)1S[1]=[1S[1]];c 1S[1].1C(7(h){c 1O+\'=\'+4n(h)}).1N(\'&\')}},1x:7(4){4=$(4);d 1F=4.1h.2w();d 1S=D.k.2E[1F](4);f(1S)c 1S[1]}};D.k.2E={2u:7(4){6c(4.2g.2w()){1r\'7Z\':1r\'31\':1r\'6l\':1r\'1Y\':c D.k.2E.3J(4);1r\'6g\':1r\'6i\':c D.k.2E.5O(4)}c Y},5O:7(4){f(4.83)c[4.B,4.h]},3J:7(4){c[4.B,4.h]},1k:7(4){c D.k.2E[4.2g==\'1k-6n\'?\'5S\':\'5X\'](4)},5S:7(4){d h=\'\',2b,w=4.85;f(w>=0){2b=4.m[w];h=2b.h||2b.1Y}c[4.B,h]},5X:7(4){d h=[];G(d i=0;i<4.t;i++){d 2b=4.m[i];f(2b.87)h.W(2b.h||2b.1Y)}c[4.B,h]}};d $F=D.k.1x;1e.3D=7(){};1e.3D.v={1I:7(4,1J,1a){6.1J=1J;6.4=$(4);6.1a=1a;6.2K=6.1x();6.2A()},2A:7(){5Z(6.2D.1d(6),6.1J*4z)},2D:7(){d h=6.1x();f(6.2K!=h){6.1a(6.4,h);6.2K=h}}};D.k.3C=1b.17();D.k.3C.v=q.u(z 1e.3D(),{1x:7(){c D.k.1x(6.4)}});D.3C=1b.17();D.3C.v=q.u(z 1e.3D(),{1x:7(){c D.3a(6.4)}});1e.2c=7(){};1e.2c.v={1I:7(4,1a){6.4=$(4);6.1a=1a;6.2K=6.1x();f(6.4.1h.2w()==\'Q\')6.67();1D 6.2A(6.4)},4K:7(){d h=6.1x();f(6.2K!=h){6.1a(6.4,h);6.2K=h}},67:7(){d 12=D.2L(6.4);G(d i=0;i<12.t;i++)6.2A(12[i])},2A:7(4){f(4.2g){6c(4.2g.2w()){1r\'6g\':1r\'6i\':1o.3B(4,\'8j\',6.4K.1d(6));1y;1r\'6l\':1r\'1Y\':1r\'3J\':1r\'1k-6n\':1r\'1k-8t\':1o.3B(4,\'8u\',6.4K.1d(6));1y}}}};D.k.2c=1b.17();D.k.2c.v=q.u(z 1e.2c(),{1x:7(){c D.k.1x(6.4)}});D.2c=1b.17();D.2c.v=q.u(z 1e.2c(),{1x:7(){c D.3a(6.4)}});f(!1W.1o){d 1o=z q()}q.u(1o,{8C:8,8F:9,8H:13,8I:27,8J:37,8L:38,8O:39,8T:40,8X:46,4:7(C){c C.Z||C.91},95:7(C){c(((C.6X)&&(C.6X==1))||((C.6Z)&&(C.6Z==1)))},9b:7(C){c C.9e||(C.9f+(J.3R.2G||J.1c.2G))},9g:7(C){c C.9j||(C.9k+(J.3R.2O||J.1c.2O))},7b:7(C){f(C.7d){C.7d();C.9r()}1D{C.48=Y;C.9w=11}},9A:7(C,1h){d 4=1o.4(C);1H(4.1X&&(!4.1h||(4.1h.3Y()!=1h.3Y())))4=4.1X;c 4},1T:Y,5u:7(4,B,1V,1u){f(!6.1T)6.1T=[];f(4.5f){6.1T.W([4,B,1V,1u]);4.5f(B,1V,1u)}1D f(4.4i){6.1T.W([4,B,1V,1u]);4.4i(\'2I\'+B,1V)}},66:7(){f(!1o.1T)c;G(d i=0;i<1o.1T.t;i++){1o.5N.2n(6,1o.1T[i]);1o.1T[i][0]=1L}1o.1T=Y},3B:7(4,B,1V,1u){d 4=$(4);1u=1u||Y;f(B==\'5U\'&&(33.4u.I(/3x|3w|3u/)||4.4i))B=\'5K\';6.5u(4,B,1V,1u)},5N:7(4,B,1V,1u){d 4=$(4);1u=1u||Y;f(B==\'5U\'&&(33.4u.I(/3x|3w|3u/)||4.4k))B=\'5K\';f(4.5x){4.5x(B,1V,1u)}1D f(4.4k){1j{4.4k(\'2I\'+B,1V)}1s(e){}}}});f(33.4u.I(/\\88\\b/))1o.3B(1W,\'8a\',1o.66,Y);d 2d={6o:Y,4P:7(){6.6z=1W.8e||J.3R.2G||J.1c.2G||0;6.6F=1W.8g||J.3R.2O||J.1c.2O||0},6u:7(4){d 19=0,15=0;2q{19+=4.2O||0;15+=4.2G||0;4=4.1X}1H(4);c[15,19]},35:7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;4=4.1Q}1H(4);c[15,19]},68:7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;4=4.1Q;f(4){p=k.1R(4,\'14\');f(p==\'3T\'||p==\'2o\')1y}}1H(4);c[15,19]},1Q:7(4){f(4.1Q)c 4.1Q;f(4==J.1c)c 4;1H((4=4.1X)&&4!=J.1c)f(k.1R(4,\'14\')!=\'4G\')c 4;c J.1c},8o:7(4,x,y){f(6.6o)c 6.6r(4,x,y);6.3g=x;6.34=y;6.1t=6.35(4);c(y>=6.1t[1]&&y<6.1t[1]+4.2k&&x>=6.1t[0]&&x<6.1t[0]+4.2p)},6r:7(4,x,y){d 4S=6.6u(4);6.3g=x+4S[0]-6.6z;6.34=y+4S[1]-6.6F;6.1t=6.35(4);c(6.34>=6.1t[1]&&6.34<6.1t[1]+4.2k&&6.3g>=6.1t[0]&&6.3g<6.1t[0]+4.2p)},8E:7(3Z,4){f(!3Z)c 0;f(3Z==\'8G\')c((6.1t[1]+4.2k)-6.34)/4.2k;f(3Z==\'8K\')c((6.1t[0]+4.2p)-6.3g)/4.2p},77:7(O,Z){O=$(O);Z=$(Z);Z.l.14=\'2o\';d 2P=6.35(O);Z.l.1n=2P[1]+\'1m\';Z.l.18=2P[0]+\'1m\';Z.l.21=O.2p+\'1m\';Z.l.24=O.2k+\'1m\'},4e:7(4M){d 19=0,15=0;d 4=4M;2q{19+=4.29||0;15+=4.2f||0;f(4.1Q==J.1c)f(k.1R(4,\'14\')==\'2o\')1y}1H(4=4.1Q);4=4M;2q{19-=4.2O||0;15-=4.2G||0}1H(4=4.1X);c[15,19]},77:7(O,Z){d m=q.u({5l:11,5r:11,5B:11,5q:11,29:0,2f:0},N[2]||{});O=$(O);d p=2d.4e(O);Z=$(Z);d 2J=[0,0];d 3v=1L;f(k.1R(Z,\'14\')==\'2o\'){3v=2d.1Q(Z);2J=2d.4e(3v)}f(3v==J.1c){2J[0]-=J.1c.2f;2J[1]-=J.1c.29}f(m.5l)Z.l.18=(p[0]-2J[0]+m.2f)+\'1m\';f(m.5r)Z.l.1n=(p[1]-2J[1]+m.29)+\'1m\';f(m.5B)Z.l.21=O.2p+\'1m\';f(m.5q)Z.l.24=O.2k+\'1m\'},8b:7(4){4=$(4);f(4.l.14==\'2o\')c;2d.4P();d 2P=2d.68(4);d 1n=2P[1];d 18=2P[0];d 21=4.6m;d 24=4.6p;4.6P=18-3X(4.l.18||0);4.6I=1n-3X(4.l.1n||0);4.5k=4.l.21;4.7f=4.l.24;4.l.14=\'2o\';4.l.1n=1n+\'1m\';4.l.18=18+\'1m\';4.l.21=21+\'1m\';4.l.24=24+\'1m\'},8w:7(4){4=$(4);f(4.l.14==\'3T\')c;2d.4P();4.l.14=\'3T\';d 1n=3X(4.l.1n||0)-(4.6I||0);d 18=3X(4.l.18||0)-(4.6P||0);4.l.1n=1n+\'1m\';4.l.18=18+\'1m\';4.l.24=4.7f;4.l.21=4.5k}};f(/3x|3w|3u/.4v(33.62)){2d.35=7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;f(4.1Q==J.1c)f(k.1R(4,\'14\')==\'2o\')1y;4=4.1Q}1H(4);c[15,19]}};',62,600,'||||element||this|function|||||return|var||if||value|||Element|style|options||iterator||Object|||length|extend|prototype|index|||new||name|event|Form|transport||for||match|document||result|Ajax|arguments|source|results|form|||Prototype|object|each|push||false|target||true|elements||position|valueL||create|left|valueT|callback|Class|body|bind|Abstract|className|Insertion|tagName|pair|try|select|url|px|top|Event|Enumerable|div|case|catch|offset|useCapture|undefined|container|getValue|break|replacement|pattern|onComplete|map|else|Array|method|property|while|initialize|frequency|range|null|include|join|key|requestHeaders|offsetParent|getStyle|parameter|observers|inspect|observer|window|parentNode|text|toArray|els|width|start|args|height|throw|request||parameters|offsetTop|methods|opt|EventObserver|Position|html|offsetLeft|type|fragments|typeof|fragment|offsetHeight|oStringList|_each|apply|absolute|offsetWidth|do|cache|decay|content|input|emptyFunction|toLowerCase|end|replace|childNodes|registerCallback|display|toString|onTimerEvent|Serializers|readyState|scrollLeft|exclusive|on|delta|lastValue|getElements|in|hash|scrollTop|offsets|stripScripts|iterable|truncation|gsub|template|initializeRange|Responders|insertContent|setTimeout|json||hidden|status|navigator|ycomp|cumulativeOffset|inject||||serialize|responders|_overflow|Methods|collect|adjacency|xcomp|innerHTML|count|split|response|responseIsSuccess|success|Template|responder|dispatchException|evalScripts|pluck|concat|Request|KHTML|parent|Safari|Konqueror|dispatch|failure|receiver|observe|Observer|TimedObserver|ScriptFragment|responseText|script|inputs|ancestor|textarea|classNames|ObjectRange|node|typeName|RegExp|camelize|none|documentElement|ClassNames|relative|right|overflow|HTMLElement|parseFloat|toUpperCase|mode||currentlyExecuting|remove|__method|Base|memo||slice|returnValue|continue|setOptions|String|classNameToRemove|_reverse|page|focus|queryComponent|Hash|attachEvent|post|detachEvent|Version|reverse|encodeURIComponent|disabled|asynchronous|eval|respondToReadyState|activeRequestCount|Complete|appVersion|test|getTransport|containers|matchingInputs|1000|header|updater|Updater|getElementsByTagName|child|responderToAdd|static|tagElements|queryComponents|defaultView|onElementEvent|css|forElement|values|visibility|prepare|mergedHash|pos|offsetcache|_madePositioned|visible|tbody|findOrStore|_nativeExtensions|createElement|digits|trues|found|prepareReplacement|before|camelizedString|insertBefore|selectNodeContents|exception|falses|criteria|classNameToAdd|params|set|destination|last|addEventListener|indexOf|inline|clear|succ|_originalWidth|setLeft|Top|ActiveXObject|scriptTag|matchOne|setHeight|setTop|without|responderToRemove|_observeAndCache|find|reset|removeEventListener|activate|findFirstElement|setRequestHeaders|setWidth|XMLHttpRequest|constructor|application|xml|onCreate|contentType|Field|onStateChange|keydown|Events|evalJSON|stopObserving|inputSelector|img|Content|evalResponse|selectOne|onreadystatechange|keypress|postBody|onException|selectMany|updateContent|setInterval|insertion|PeriodicalUpdater|userAgent|updateComplete|lastText|timer|unloadCache|registerFormCallbacks|positionedOffset|register|parentElement|children|switch|XMLHTTP|_extended|hide|checkbox|update|radio|these|outerHTML|password|clientWidth|one|includeScrollOffsets|clientHeight|nodeValue|withinIncludingScrolloffsets|Try|scrollTo|realOffset|getComputedStyle|show|currentStyle|auto|deltaX|originalPosition|originalVisibility|originalWidth|originalHeight|opera|deltaY|bottom|array|_originalTop|flatten|addMethods|lambda|Toggle|toggle|insertAdjacentHTML|_originalLeft|PeriodicalExecuter|ownerDocument|createRange|createContextualFragment|contentFromAnonymousTable|table|Before|which|matchAll|button|extractScripts|stripTags|pairString|len|collapse|appendChild|After|clone|toQueryParams|Pattern|evaluate|stop|stringValue|preventDefault|charAt|_originalHeight|substring|Bottom|pairs|Function|add|collections|javascript|detect|findAll|entries|from|first|compact|keys|merge|present|toQueryString|getInputs|Msxml2|Microsoft|unregister|disable|urlencoded|blur|300|enable|responseIsFailure|Uninitialized|Loaded|Interactive|_|get|focusFirstElement|open|send|Requested|With|Accept|overrideMimeType|Connection|close|setRequestHeader|getResponseHeader|JSON|gi|submit|Loading|Success|Failure|checked|200|selectedIndex|www|selected|bMSIE|clearTimeout|unload|absolutize|string|getElementById|pageXOffset|getElementsByClassName|pageYOffset|removeChild|replaceChild|click|getHeight|hasClassName|addClassName|removeClassName|within|cleanWhitespace|nodeType|empty|childOf|multiple|change|getPropertyValue|relativize|setStyle|getDimensions|makePositioned|undoPositioned|makeClipping|KEY_BACKSPACE|undoClipping|overlap|KEY_TAB|vertical|KEY_RETURN|KEY_ESC|KEY_LEFT|horizontal|KEY_UP|member|tr|KEY_RIGHT|0_RC_0|Number|instanceof|shift|KEY_DOWN|bindAsEventListener|call|toColorPart|KEY_DELETE|times|finally|callee|srcElement|sub|scan|truncate|isLeftClick|beforeBegin|setStartBefore|im|afterBegin|firstChild|pointerX|unescapeHTML|beforeEnd|pageX|clientX|pointerY|parseQuery|afterEnd|pageY|clientY|RangeError|setStartAfter|all|any|grep|invoke|stopPropagation|max|nextSibling|min|partition|cancelBubble|reject|sortBy|sort|findElement|zip|pop|createTextNode|escapeHTML|strip'.split('|'),0,{}) + +} + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/sunspider/string-validate-input.html b/build/pgo/js-input/sunspider/string-validate-input.html new file mode 100644 index 0000000000..72cf920b26 --- /dev/null +++ b/build/pgo/js-input/sunspider/string-validate-input.html @@ -0,0 +1,139 @@ +<!DOCTYPE html> +<head> +<!-- + Copyright (C) 2007 Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<title>SunSpider string-validate-input</title> + +</head> + +<body> +<h3>string-validate-input</h3> +<div id="console"> +</div> + +<script> + +var _sunSpiderStartDate = new Date(); + +letters = new Array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"); +numbers = new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26); +colors = new Array("FF","CC","99","66","33","00"); + +var endResult; + +function doTest() +{ + endResult = ""; + + // make up email address + for (var k=0;k<4000;k++) + { + name = makeName(6); + (k%2)?email=name+"@mac.com":email=name+"(at)mac.com"; + + // validate the email address + var pattern = /^[a-zA-Z0-9\-\._]+@[a-zA-Z0-9\-_]+(\.?[a-zA-Z0-9\-_]*)\.[a-zA-Z]{2,3}$/; + + if(pattern.test(email)) + { + var r = email + " appears to be a valid email address."; + addResult(r); + } + else + { + r = email + " does NOT appear to be a valid email address."; + addResult(r); + } + } + + // make up ZIP codes + for (var s=0;s<4000;s++) + { + var zipGood = true; + var zip = makeNumber(4); + (s%2)?zip=zip+"xyz":zip=zip.concat("7"); + + // validate the zip code + for (var i = 0; i < zip.length; i++) { + var ch = zip.charAt(i); + if (ch < "0" || ch > "9") { + zipGood = false; + r = zip + " contains letters."; + addResult(r); + } + } + if (zipGood && zip.length>5) + { + zipGood = false; + r = zip + " is longer than five characters."; + addResult(r); + } + if (zipGood) + { + r = zip + " appears to be a valid ZIP code."; + addResult(r); + } + } +} + +function makeName(n) +{ + var tmp = ""; + for (var i=0;i<n;i++) + { + var l = Math.floor(26*Math.random()); + tmp += letters[l]; + } + return tmp; +} + +function makeNumber(n) +{ + var tmp = ""; + for (var i=0;i<n;i++) + { + var l = Math.floor(9*Math.random()); + tmp = tmp.concat(l); + } + return tmp; +} + +function addResult(r) +{ + endResult += "\n" + r; +} + +doTest(); + + +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; + +document.getElementById("console").innerHTML = _sunSpiderInterval; +</script> + + +</body> +</html> diff --git a/build/pgo/js-input/valid-xhtml10.png b/build/pgo/js-input/valid-xhtml10.png Binary files differnew file mode 100644 index 0000000000..2275ee6ea1 --- /dev/null +++ b/build/pgo/js-input/valid-xhtml10.png diff --git a/build/pgo/profileserver.py b/build/pgo/profileserver.py new file mode 100755 index 0000000000..6eab7889b0 --- /dev/null +++ b/build/pgo/profileserver.py @@ -0,0 +1,254 @@ +#!/usr/bin/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/. + +import glob +import json +import os +import subprocess +import sys + +import mozcrash +from mozbuild.base import BinaryNotFoundException, MozbuildObject +from mozfile import TemporaryDirectory +from mozhttpd import MozHttpd +from mozprofile import FirefoxProfile, Preferences +from mozprofile.permissions import ServerLocations +from mozrunner import CLI, FirefoxRunner +from six import string_types + +PORT = 8888 + +PATH_MAPPINGS = { + "/webkit/PerformanceTests": "third_party/webkit/PerformanceTests", + # It is tempting to map to `testing/talos/talos/tests` instead, to avoid + # writing `tests/` in every path, but we can't do that because some files + # refer to scripts located in `../..`. + "/talos": "testing/talos/talos", +} + + +def get_crashreports(directory, name=None): + rc = 0 + upload_path = os.environ.get("UPLOAD_PATH") + if not upload_path: + upload_path = os.environ.get("UPLOAD_DIR") + if upload_path: + # For automation, log the minidumps with stackwalk and get them moved to + # the artifacts directory. + fetches_dir = os.environ.get("MOZ_FETCHES_DIR") + if not fetches_dir: + raise Exception( + "Unable to process minidump in automation because " + "$MOZ_FETCHES_DIR is not set in the environment" + ) + stackwalk_binary = os.path.join( + fetches_dir, "minidump-stackwalk", "minidump-stackwalk" + ) + if sys.platform == "win32": + stackwalk_binary += ".exe" + minidump_path = os.path.join(directory, "minidumps") + rc = mozcrash.check_for_crashes( + minidump_path, + symbols_path=fetches_dir, + stackwalk_binary=stackwalk_binary, + dump_save_path=upload_path, + test_name=name, + ) + return rc + + +if __name__ == "__main__": + cli = CLI() + debug_args, interactive = cli.debugger_arguments() + runner_args = cli.runner_args() + + build = MozbuildObject.from_environment() + + binary = runner_args.get("binary") + if not binary: + try: + binary = build.get_binary_path(where="staged-package") + except BinaryNotFoundException as e: + print("{}\n\n{}\n".format(e, e.help())) + sys.exit(1) + binary = os.path.normpath(os.path.abspath(binary)) + + path_mappings = { + k: os.path.join(build.topsrcdir, v) for k, v in PATH_MAPPINGS.items() + } + httpd = MozHttpd( + port=PORT, + docroot=os.path.join(build.topsrcdir, "build", "pgo"), + path_mappings=path_mappings, + ) + httpd.start(block=False) + + sp3_httpd = MozHttpd( + port=8000, + docroot=os.path.join( + build.topsrcdir, "third_party", "webkit", "PerformanceTests", "Speedometer3" + ), + path_mappings=path_mappings, + ) + sp3_httpd.start(block=False) + print("started SP3 server on port 8000") + locations = ServerLocations() + locations.add_host(host="127.0.0.1", port=PORT, options="primary,privileged") + + old_profraw_files = glob.glob("*.profraw") + for f in old_profraw_files: + os.remove(f) + + with TemporaryDirectory() as profilePath: + # TODO: refactor this into mozprofile + profile_data_dir = os.path.join(build.topsrcdir, "testing", "profiles") + with open(os.path.join(profile_data_dir, "profiles.json"), "r") as fh: + base_profiles = json.load(fh)["profileserver"] + + prefpaths = [ + os.path.join(profile_data_dir, profile, "user.js") + for profile in base_profiles + ] + + prefs = {} + for path in prefpaths: + prefs.update(Preferences.read_prefs(path)) + + interpolation = {"server": "%s:%d" % httpd.httpd.server_address} + sp3_interpolation = {"server": "%s:%d" % sp3_httpd.httpd.server_address} + for k, v in prefs.items(): + if isinstance(v, string_types): + v = v.format(**interpolation) + prefs[k] = Preferences.cast(v) + + profile = FirefoxProfile( + profile=profilePath, + preferences=prefs, + addons=[ + os.path.join( + build.topsrcdir, "tools", "quitter", "quitter@mozilla.org.xpi" + ) + ], + locations=locations, + ) + + env = os.environ.copy() + env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" + env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" + env["XPCOM_DEBUG_BREAK"] = "warn" + # We disable sandboxing to make writing profiling data actually work + # Bug 1553850 considers fixing this. + env["MOZ_DISABLE_CONTENT_SANDBOX"] = "1" + env["MOZ_DISABLE_RDD_SANDBOX"] = "1" + env["MOZ_DISABLE_SOCKET_PROCESS_SANDBOX"] = "1" + env["MOZ_DISABLE_GPU_SANDBOX"] = "1" + env["MOZ_DISABLE_GMP_SANDBOX"] = "1" + env["MOZ_DISABLE_NPAPI_SANDBOX"] = "1" + env["MOZ_DISABLE_VR_SANDBOX"] = "1" + + # Ensure different pids write to different files + env["LLVM_PROFILE_FILE"] = "default_%p_random_%m.profraw" + + # Write to an output file if we're running in automation + process_args = {"universal_newlines": True} + if "UPLOAD_PATH" in env: + process_args["logfile"] = os.path.join( + env["UPLOAD_PATH"], "profile-run-1.log" + ) + + # Run Firefox a first time to initialize its profile + runner = FirefoxRunner( + profile=profile, + binary=binary, + cmdargs=["data:text/html,<script>Quitter.quit()</script>"], + env=env, + process_args=process_args, + ) + runner.start() + ret = runner.wait() + if ret: + print("Firefox exited with code %d during profile initialization" % ret) + logfile = process_args.get("logfile") + if logfile: + print("Firefox output (%s):" % logfile) + with open(logfile) as f: + print(f.read()) + sp3_httpd.stop() + httpd.stop() + get_crashreports(profilePath, name="Profile initialization") + sys.exit(ret) + + jarlog = os.getenv("JARLOG_FILE") + if jarlog: + env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog) + print("jarlog: %s" % env["MOZ_JAR_LOG_FILE"]) + if os.path.exists(jarlog): + os.remove(jarlog) + + if "UPLOAD_PATH" in env: + process_args["logfile"] = os.path.join( + env["UPLOAD_PATH"], "profile-run-2.log" + ) + cmdargs = ["http://localhost:%d/index.html" % PORT] + runner = FirefoxRunner( + profile=profile, + binary=binary, + cmdargs=cmdargs, + env=env, + process_args=process_args, + ) + runner.start(debug_args=debug_args, interactive=interactive) + ret = runner.wait() + sp3_httpd.stop() + httpd.stop() + if ret: + print("Firefox exited with code %d during profiling" % ret) + logfile = process_args.get("logfile") + if logfile: + print("Firefox output (%s):" % logfile) + with open(logfile) as f: + print(f.read()) + get_crashreports(profilePath, name="Profiling run") + sys.exit(ret) + + # Try to move the crash reports to the artifacts even if Firefox appears + # to exit successfully, in case there's a crash that doesn't set the + # return code to non-zero for some reason. + if get_crashreports(profilePath, name="Firefox exited successfully?") != 0: + print("Firefox exited successfully, but produced a crashreport") + sys.exit(1) + + llvm_profdata = env.get("LLVM_PROFDATA") + if llvm_profdata: + profraw_files = glob.glob("*.profraw") + if not profraw_files: + print( + "Could not find profraw files in the current directory: %s" + % os.getcwd() + ) + sys.exit(1) + + merged_profdata = "merged.profdata" + merge_cmd = [ + llvm_profdata, + "merge", + "-o", + merged_profdata, + ] + profraw_files + rc = subprocess.call(merge_cmd) + if rc != 0: + print("INFRA-ERROR: Failed to merge profile data. Corrupt profile?") + # exit with TBPL_RETRY + sys.exit(4) + + # llvm-profdata may fail while still exiting without an error. + if not os.path.isfile(merged_profdata): + print(merged_profdata, "was not created", file=sys.stderr) + sys.exit(1) + + if os.path.getsize(merged_profdata) == 0: + print(merged_profdata, "was created but it is empty", file=sys.stderr) + sys.exit(1) diff --git a/build/pgo/server-locations.txt b/build/pgo/server-locations.txt new file mode 100644 index 0000000000..2d97a79f3f --- /dev/null +++ b/build/pgo/server-locations.txt @@ -0,0 +1,394 @@ +# +# 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/. + +# +# This file defines the locations at which this HTTP server may be accessed. +# It is referred to by the following page, so if this file moves, that page must +# be modified accordingly: +# +# https://firefox-source-docs.mozilla.org/testing/mochitest-plain/faq.html +# +# Empty lines and lines which begin with "#" are ignored and may be used for +# storing comments. All other lines consist of an origin followed by whitespace +# and a comma-separated list of options (if indeed any options are needed). +# +# The format of an origin is, referring to RFC 2396, a scheme (either "http" or +# "https"), followed by "://", followed by a host, followed by ":", followed by +# a port number. The colon and port number must be present even if the port +# number is the default for the protocol. +# +# Unrecognized options are ignored. Recognized options are "primary" and +# "privileged", "nocert", "cert=some_cert_nickname", "redir=hostname" and +# "failHandshake". +# +# "primary" denotes a location which is the canonical location of +# the server; this location is the one assumed for requests which don't +# otherwise identify a particular origin (e.g. HTTP/1.0 requests). +# +# "privileged" denotes a location which should have the ability to request +# elevated privileges; the default is no privileges. +# +# "nocert" makes sense only for https:// hosts and means there is not +# any certificate automatically generated for this host. +# +# "failHandshake" causes the tls handshake to fail (by sending a client hello to +# the client). +# +# "cert=nickname" tells the pgo server to use a particular certificate +# for this host. The certificate is referenced by its nickname that must +# not contain any spaces. The certificate key files (PKCS12 modules) +# for custom certification are loaded from build/pgo/certs +# directory. When new certificate is added to this dir pgo/ssltunnel +# must be built then. This is only necessary for cases where we really do +# want specific certs. +# You can find instructions on how to add or modify certificates at: +# https://firefox-source-docs.mozilla.org/build/buildsystem/test_certificates.html +# +# "redir=hostname" tells the pgo server is only used for https:// +# hosts while processing the CONNECT tunnel request. It responds +# to the CONNECT with a 302 and redirection to the hostname instead +# of connecting to the real back end and replying with a 200. This +# mode exists primarily to ensure we don't allow a proxy to do that. +# + +# +# This is the primary location from which tests run. +# +http://mochi.test:8888 primary,privileged + +# +# These are a common set of prefixes scattered across one TLD with two ports and +# another TLD on a single port. +# +http://127.0.0.1:80 privileged +http://127.0.0.1:8888 privileged +http://test:80 privileged +http://mochi.test:8888 privileged +http://mochi.xorigin-test:8888 privileged +http://test1.mochi.test:8888 +http://sub1.test1.mochi.test:8888 +http://sub2.xn--lt-uia.mochi.test:8888 +http://test2.mochi.test:8888 +http://example.org:80 privileged +http://test1.example.org:80 privileged +http://test2.example.org:80 privileged +http://test3.example.org:80 privileged +http://sub1.test1.example.org:80 privileged +http://sub1.test2.example.org:80 privileged +http://sub2.test1.example.org:80 privileged +http://sub2.test2.example.org:80 privileged +http://example.org:8000 privileged +http://test1.example.org:8000 privileged +http://test2.example.org:8000 privileged +http://sub1.test1.example.org:8000 privileged +http://sub1.test2.example.org:8000 privileged +http://sub2.test1.example.org:8000 privileged +http://sub2.test2.example.org:8000 privileged +http://example.com:80 privileged +http://www.example.com:80 privileged +http://test1.example.com:80 privileged +http://test2.example.com:80 privileged +http://sub1.test1.example.com:80 privileged +http://sub1.test2.example.com:80 privileged +http://sub2.test1.example.com:80 privileged +http://sub2.test2.example.com:80 privileged +http://example.net:80 privileged +http://supports-insecure.expired.example.com:80 privileged +# Used to test that clearing Service Workers for domain example.com, does not clear prefixexample.com +http://prefixexample.com:80 + +# The first HTTPS location is used to generate the Common Name (CN) value of the +# certificate's Issued To field. +https://example.com:443 privileged +https://www.example.com:443 privileged +https://test1.example.com:443 privileged +https://test2.example.com:443 privileged +https://example.org:443 privileged +https://test1.example.org:443 privileged +https://test2.example.org:443 privileged +https://sub1.test1.example.org:443 privileged +https://sub1.test2.example.org:443 privileged +https://sub2.test1.example.org:443 privileged +https://sub2.test2.example.org:443 privileged +https://sub1.test1.example.com:443 privileged +https://sub1.test2.example.com:443 privileged +https://sub2.test1.example.com:443 privileged +https://sub2.test2.example.com:443 privileged +https://example.net:443 privileged +https://nocert.example.com:443 privileged,nocert +https://nocert.example.org:443 privileged,nocert +https://self-signed.example.com:443 privileged,cert=selfsigned +https://untrusted.example.com:443 privileged,cert=untrusted +https://expired.example.com:443 privileged,cert=expired +https://requestclientcert.example.com:443 privileged,clientauth=request +https://requireclientcert.example.com:443 privileged,clientauth=require +https://requireclientcert-2.example.com:443 privileged,clientauth=require +https://requireclientcert-untrusted.example.com:443 privileged,clientauth=require,cert=untrusted +https://mismatch.expired.example.com:443 privileged,cert=expired +https://mismatch.untrusted.example.com:443 privileged,cert=untrusted +https://untrusted-expired.example.com:443 privileged,cert=untrustedandexpired +https://mismatch.untrusted-expired.example.com:443 privileged,cert=untrustedandexpired +https://supports-insecure.expired.example.com:443 privileged,cert=expired +https://no-subject-alt-name.example.com:443 cert=noSubjectAltName + +# Used for secure contexts on ip addresses, see bug 1616675. Note that +# 127.0.0.1 prompts ssltunnel.cpp to do special-cases, so we use .2 +https://127.0.0.2:443 privileged,ipV4Address +https://secureonly.example.com:443 + +# Prevent safebrowsing tests from hitting the network for its-a-trap.html and +# its-an-attack.html. +http://www.itisatrap.org:80 +https://www.itisatrap.org:443 + +# +# These are subdomains of <ält.example.org>. +# +http://sub1.xn--lt-uia.example.org:8000 privileged +http://sub2.xn--lt-uia.example.org:80 privileged +http://xn--exmple-cua.test:80 privileged +http://sub1.xn--exmple-cua.test:80 privileged +http://xn--exaple-kqf.test:80 privileged +http://sub1.xn--exaple-kqf.test:80 privileged + +https://xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged +https://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged + +# +# These are subdomains of <παράδειγμα.δοκιμή>, the Greek IDN for example.test. +# +http://xn--hxajbheg2az3al.xn--jxalpdlp:80 privileged +http://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80 privileged + +# Bug 413909 test host +https://bug413909.xn--hxajbheg2az3al.xn--jxalpdlp:443 privileged,cert=bug413909cert + +# +# These hosts are used in tests which exercise privilege-granting functionality; +# we could reuse some of the names above, but specific names make it easier to +# distinguish one from the other in tests (as well as what functionality is +# being tested). +# +http://sectest1.example.org:80 privileged +http://sub.sectest2.example.org:80 privileged +http://sectest2.example.org:80 +http://sub.sectest1.example.org:80 + +https://sectest1.example.org:443 privileged +https://sub.sectest2.example.org:443 privileged +https://sectest2.example.org:443 +https://sub.sectest1.example.org:443 + +# +# Used while testing the url-classifier +# +http://malware.example.com:80 +http://unwanted.example.com:80 +http://tracking.example.com:80 +http://cryptomining.example.com:80 +http://fingerprinting.example.com:80 +http://not-tracking.example.com:80 +http://tracking.example.org:80 +http://another-tracking.example.net:80 +http://social-tracking.example.org:80 +http://itisatracker.org:80 +https://itisatracker.org:443 +http://trackertest.org:80 +http://email-tracking.example.org:80 +# +# Used while testing TLS session ticket resumption for third-party trackers (bug 1500533) +# (DO NOT USE THIS HOST IN OTHER TESTS!) +# +https://tlsresumptiontest.example.org:443 + +https://malware.example.com:443 +https://unwanted.example.com:443 +https://tracking.example.com:443 +https://cryptomining.example.com:443 +https://fingerprinting.example.com:443 +https://not-tracking.example.com:443 +https://tracking.example.org:443 +https://another-tracking.example.net:443 +https://social-tracking.example.org:443 +https://email-tracking.example.org:443 + +# +# Used while testing flash blocking (Bug 1307604) +# +http://flashallow.example.com:80 +http://exception.flashallow.example.com:80 +http://flashblock.example.com:80 +http://exception.flashblock.example.com:80 +http://subdocument.example.com:80 +https://subdocument.example.com:443 +http://exception.subdocument.example.com:80 + +# +# Used while testing tracking protection (Bug 1580416) +# Not that apps.fbsbx.com is a public suffix +# +http://mochitest.apps.fbsbx.com:80 + +# +# Flash usage can fail unless this URL exists +# +http://fpdownload2.macromedia.com:80 +https://fpdownload2.macromedia.com:443 + +# Bug 1281083 +http://bug1281083.example.com:80 + +# Bug 483437, 484111 +https://www.bank1.com:443 privileged,cert=escapeattack1 + +# +# CONNECT for redirproxy results in a 302 redirect to +# test1.example.com +# +https://redirproxy.example.com:443 privileged,redir=test1.example.com + +# Host used for IndexedDB Quota testing +http://bug704464-1.example.com:80 privileged +http://bug704464-2.example.com:80 privileged +http://bug704464-3.example.com:80 privileged +http://bug702292.example.com:80 privileged + +# W3C hosts. +# See http://www.w3.org/wiki/Testing/Requirements#The_Web_test_server_must_be_available_through_different_domain_names +http://w3c-test.org:80 +http://w3c-test.org:81 +http://w3c-test.org:82 +http://w3c-test.org:83 +http://www.w3c-test.org:80 +http://www.w3c-test.org:81 +http://www.w3c-test.org:82 +http://www.w3c-test.org:83 +http://www1.w3c-test.org:80 +http://www1.w3c-test.org:81 +http://www1.w3c-test.org:82 +http://www1.w3c-test.org:83 +http://www2.w3c-test.org:80 +http://www2.w3c-test.org:81 +http://www2.w3c-test.org:82 +http://www2.w3c-test.org:83 +# http://天気の良い日.w3c-test.org +http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:80 +http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:81 +http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:82 +http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:83 +# http://élève.w3c-test.org +http://xn--lve-6lad.w3c-test.org:80 +http://xn--lve-6lad.w3c-test.org:81 +http://xn--lve-6lad.w3c-test.org:82 +http://xn--lve-6lad.w3c-test.org:83 +# HTTPS versions of the above +https://w3c-test.org:443 +https://www.w3c-test.org:443 +https://www1.w3c-test.org:443 +https://www2.w3c-test.org:443 +https://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:443 +https://xn--lve-6lad.w3c-test.org:443 +http://test.w3.org:80 + +# Hosts for testing TLD-based fallback encoding +http://example.tw:80 privileged +http://example.cn:80 privileged +http://example.co.jp:80 privileged +http://example.fi:80 privileged +http://example.in:80 privileged +http://example.lk:80 privileged + +# Host for HPKP +https://include-subdomains.pinning-dynamic.example.com:443 privileged,cert=dynamicPinningGood +https://bad.include-subdomains.pinning-dynamic.example.com:443 privileged,cert=dynamicPinningBad + +# Host for static pin tests +https://badchain.include-subdomains.pinning.example.com:443 privileged,cert=staticPinningBad +https://fail-handshake.example.com:443 privileged,failHandshake + +# Host for bad cert domain fixup test +https://badcertdomain.example.com:443 privileged,cert=badCertDomain +https://www.badcertdomain.example.com:443 privileged,cert=badCertDomain +https://127.0.0.3:433 privileged,cert=badCertDomain +https://badcertdomain.example.com:82 privileged,cert=badCertDomain +https://mismatch.badcertdomain.example.com:443 privileged,cert=badCertDomain + +# Hosts for HTTPS-First upgrades/downgrades +http://httpsfirst.com:80 privileged +https://httpsfirst.com:443 privileged,nocert + +# Hosts for sha1 console warning tests +https://sha1ee.example.com:443 privileged,cert=sha1_end_entity +https://sha256ee.example.com:443 privileged,cert=sha256_end_entity + +# Hosts for imminent distrust warning tests +https://imminently-distrusted.example.com:443 privileged,cert=imminently_distrusted + +# Hosts for ssl3/3des/tls1 tests +https://ssl3.example.com:443 privileged,ssl3 +https://3des.example.com:443 privileged,3des,tls1,tls1_2 +https://tls1.example.com:443 privileged,tls1 +https://tls11.example.com:443 privileged,tls1_1 +https://tls12.example.com:443 privileged,tls1_2 +https://tls13.example.com:443 privileged,tls1,tls1_3 + +# Hosts for youtube rewrite tests +https://mochitest.youtube.com:443 + +# Host for U2F localhost tests +https://localhost:443 + +# Bug 1402530 +http://localhost:80 privileged + +http://localhost:9898 +http://localhost:9899 + +# Host for testing APIs whitelisted for mozilla.org +https://www.mozilla.org:443 + +# local-IP origins for password manager tests (Bug 1582499) +http://10.0.0.0:80 privileged +http://192.168.0.0:80 privileged + +# testing HTTPS-Only Suggestions on the Error Page (Bug 1665057) +https://www.suggestion-example.com:443 privileged,cert=bug1665057cert +http://suggestion-example.com:80 privileged +https://suggestion-example.com:443 privileged,cert=badCertDomain +http://no-suggestion-example.com:80 privileged +https://no-suggestion-example.com:443 privileged,cert=badCertDomain + +# testing HTTPS-First doesn't show warning page for bad cert +http://nocert.example.com:80 privileged +http://self-signed.example.com:80 privileged +http://untrusted.example.com:80 privileged +http://untrusted-expired.example.com:80 privileged +http://no-subject-alt-name.example.com:80 privileged +http://expired.example.com:80 privileged + +# testing HTTPS-First behaviour for redirection (Bug 1706126) +http://redirect-example.com:80 privileged +https://redirect-example.com:443 privileged,cert=bug1706126cert +https://www.redirect-example.com:443 privileged,cert=bug1706126cert + +# DoH server +https://foo.example.com:4433 privileged,cert=http2-cert.pem + +# Mochitest +https://mochi.test:443 privileged,cert=mochitest-cert.pem + +# condprof common transactions +http://profile.stage.mozaws.net:80 privileged +https://profile.stage.mozaws.net:443 privileged +http://ocsp.pki.goog:80 privileged +https://ocsp.pki.goog:443 privileged + +# External IP address only available via http (Bug 1855734) +http://123.123.123.123:80 privileged +https://123.123.123.123:443 privileged,nocert + +# Domain with HSTS preloaded +http://includesubdomains.preloaded.test:80 privileged +https://includesubdomains.preloaded.test:443 privileged diff --git a/build/psutil_requirements.in b/build/psutil_requirements.in new file mode 100644 index 0000000000..22cc083951 --- /dev/null +++ b/build/psutil_requirements.in @@ -0,0 +1,2 @@ +psutil==5.9.4 + diff --git a/build/psutil_requirements.txt b/build/psutil_requirements.txt new file mode 100644 index 0000000000..cd14f98539 --- /dev/null +++ b/build/psutil_requirements.txt @@ -0,0 +1,22 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# pip-compile --generate-hashes --output-file=build/psutil_requirements.txt build/psutil_requirements.in +# +psutil==5.9.4 \ + --hash=sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff \ + --hash=sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1 \ + --hash=sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62 \ + --hash=sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549 \ + --hash=sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08 \ + --hash=sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7 \ + --hash=sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e \ + --hash=sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe \ + --hash=sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24 \ + --hash=sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad \ + --hash=sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94 \ + --hash=sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8 \ + --hash=sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7 \ + --hash=sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4 + # via -r build/psutil_requirements.in diff --git a/build/pure_virtual/moz.build b/build/pure_virtual/moz.build new file mode 100644 index 0000000000..2e5169fec6 --- /dev/null +++ b/build/pure_virtual/moz.build @@ -0,0 +1,23 @@ +# -*- 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/. + +Library("pure_virtual") + +SOURCES += ["pure_virtual.c"] + +FORCE_STATIC_LIB = True + +USE_STATIC_LIBS = True + +# Build a real library so that the linker can remove it if the symbol +# is never used. +NO_EXPAND_LIBS = True + +# LTO can mess things up. +if CONFIG["CC_TYPE"] == "clang-cl": + CFLAGS += ["-clang:-fno-lto"] +else: + CFLAGS += ["-fno-lto"] diff --git a/build/pure_virtual/pure_virtual.c b/build/pure_virtual/pure_virtual.c new file mode 100644 index 0000000000..23b18f2aae --- /dev/null +++ b/build/pure_virtual/pure_virtual.c @@ -0,0 +1,27 @@ +/* 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/Assertions.h> + +// This function is used in vtables to point at pure virtual methods. +// The implementation in the standard library usually aborts, but +// the function is normally never called (a call would be a bug). +// Each of these entries in vtables, however, require an unnecessary +// dynamic relocation. Defining our own function makes the linker +// point the vtables here instead of the standard library, replacing +// the dynamic relocations with relative relocations. +// +// On Windows, it doesn't really make a difference, but on macOS it +// can be packed better, saving about 10KB in libxul, and on 64-bits +// ELF systems, with packed relative relocations, it saves 140KB. +// +// Another advantage of having our own is that we can use MOZ_CRASH +// instead of the system's abort. +#ifdef _MSC_VER +int __cdecl _purecall() { MOZ_CRASH("pure virtual call"); } +#else +__attribute__((visibility("hidden"))) void __cxa_pure_virtual() { + MOZ_CRASH("pure virtual call"); +} +#endif diff --git a/build/qemu-wrap b/build/qemu-wrap new file mode 100755 index 0000000000..e33938955d --- /dev/null +++ b/build/qemu-wrap @@ -0,0 +1,24 @@ +#!/bin/bash +# this script creates a wrapper shell script for an executable. The idea is the actual executable cannot be +# executed natively (it was cross compiled), but we want to run tests natively. Running this script +# as part of the compilation process will move the non-native executable to a new location, and replace it +# with a script that will run it under qemu. +while [[ -n $1 ]]; do + case $1 in + --qemu) QEMU="$2"; shift 2;; + --libdir) LIBDIR="$2"; shift 2;; + --ld) LD="$2"; shift 2;; + *) exe="$1"; shift;; + esac +done +if [[ -z $LIBDIR ]]; then + echo "You need to specify a directory for the cross libraries when you configure the shell" + echo "You can do this with --with-cross-lib=" + exit 1 +fi +LD=${LD:-$LIBDIR/ld-linux.so.3} +mv $exe $exe.target +# Just hardcode the path to the executable. It'll be pretty obvious if it is doing the wrong thing. + +echo $'#!/bin/bash\n' $QEMU -E LD_LIBRARY_PATH="${LIBDIR}" "$LD" "$(readlink -f "$exe.target")" '"$@"' >"$exe" +chmod +x $exe
\ No newline at end of file diff --git a/build/rust/backtrace/Cargo.toml b/build/rust/backtrace/Cargo.toml new file mode 100644 index 0000000000..a251228e71 --- /dev/null +++ b/build/rust/backtrace/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "backtrace" +version = "0.3.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/backtrace/lib.rs b/build/rust/backtrace/lib.rs new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/build/rust/backtrace/lib.rs diff --git a/build/rust/base64/Cargo.toml b/build/rust/base64/Cargo.toml new file mode 100644 index 0000000000..ce9fdc2836 --- /dev/null +++ b/build/rust/base64/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "base64" +version = "0.13.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.base64] +version = "0.21.0" diff --git a/build/rust/base64/lib.rs b/build/rust/base64/lib.rs new file mode 100644 index 0000000000..d5d4ce6af4 --- /dev/null +++ b/build/rust/base64/lib.rs @@ -0,0 +1,42 @@ +/* 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/. */ + +pub use base64::engine::general_purpose::*; +pub use base64::DecodeError; +use base64::Engine; + +// Re-implement some of the 0.13 APIs on top of 0.21 + +pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError> { + STANDARD.decode(input) +} + +pub fn encode<T: AsRef<[u8]>>(input: T) -> String { + STANDARD.encode(input) +} + +pub fn decode_config<T: AsRef<[u8]>>( + input: T, + engine: GeneralPurpose, +) -> Result<Vec<u8>, DecodeError> { + engine.decode(input) +} + +pub fn encode_config<T: AsRef<[u8]>>(input: T, engine: GeneralPurpose) -> String { + engine.encode(input) +} + +pub fn encode_config_slice<T: AsRef<[u8]>>( + input: T, + engine: GeneralPurpose, + output: &mut [u8], +) -> usize { + engine + .encode_slice(input, output) + .expect("Output buffer too small") +} + +pub fn encode_config_buf<T: AsRef<[u8]>>(input: T, engine: GeneralPurpose, buf: &mut String) { + engine.encode_string(input, buf) +} diff --git a/build/rust/bindgen-0.63/Cargo.toml b/build/rust/bindgen-0.63/Cargo.toml new file mode 100644 index 0000000000..200ff7a961 --- /dev/null +++ b/build/rust/bindgen-0.63/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "bindgen" +version = "0.63.999" +edition = "2018" +license = "BSD-3-Clause" + +[lib] +path = "lib.rs" + +[dependencies.bindgen] +version = "0.69" +default-features = false + +[features] +logging = ["bindgen/logging"] +runtime = ["bindgen/runtime"] +static = ["bindgen/static"] +which-rustfmt = ["bindgen/which-rustfmt"] diff --git a/build/rust/bindgen-0.63/lib.rs b/build/rust/bindgen-0.63/lib.rs new file mode 100644 index 0000000000..6828a430d5 --- /dev/null +++ b/build/rust/bindgen-0.63/lib.rs @@ -0,0 +1,26 @@ +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +pub use bindgen::*; diff --git a/build/rust/bitflags/Cargo.toml b/build/rust/bitflags/Cargo.toml new file mode 100644 index 0000000000..7595f3b5bb --- /dev/null +++ b/build/rust/bitflags/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "bitflags" +version = "1.999.999" +edition = "2018" +license = "MIT/Apache-2.0" + +[lib] +path = "lib.rs" + +[dependencies.bitflags] +version = "2" diff --git a/build/rust/bitflags/lib.rs b/build/rust/bitflags/lib.rs new file mode 100644 index 0000000000..3a3c67e4fd --- /dev/null +++ b/build/rust/bitflags/lib.rs @@ -0,0 +1,61 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use bitflags::bitflags as bitflags2; +pub use bitflags::parser; + +// Copy of the macro from bitflags 1.3.2, with the implicit derives +// removed, because in 2.0, they're expected to be explicitly given +// in the macro invocation. And because bitflags 1.3.2 itself always +// adds an impl Debug, we need to remove #[derive(Debug)] from what +// is passed in, which is what the __impl_bitflags_remove_derive_debug +// macro does. +#[macro_export(local_inner_macros)] +macro_rules! bitflags { + ( + $(#[$($outer:tt)+])* + $vis:vis struct $BitFlags:ident: $T:ty { + $( + $(#[$inner:ident $($args:tt)*])* + const $Flag:ident = $value:expr; + )* + } + + $($t:tt)* + ) => { + $(#[$($outer)+])* + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + $vis struct $BitFlags($T); + + impl core::fmt::Debug for $BitFlags { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if self.is_empty() { + core::write!(f, "{:#x}", Self::empty().bits()) + } else { + $crate::parser::to_writer(self, f) + } + } + } + + bitflags2! { + impl $BitFlags: $T { + $( + $(#[$inner $($args)*])* + const $Flag = $value; + )* + } + } + + bitflags! { + $($t)* + } + }; + () => {}; +} diff --git a/build/rust/cfg-if/Cargo.toml b/build/rust/cfg-if/Cargo.toml new file mode 100644 index 0000000000..fff5b54155 --- /dev/null +++ b/build/rust/cfg-if/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "cfg-if" +version = "0.1.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies] +cfg-if = "1.0" diff --git a/build/rust/cfg-if/lib.rs b/build/rust/cfg-if/lib.rs new file mode 100644 index 0000000000..70c009f840 --- /dev/null +++ b/build/rust/cfg-if/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use cfg_if::*; diff --git a/build/rust/cmake/Cargo.toml b/build/rust/cmake/Cargo.toml new file mode 100644 index 0000000000..8bae1af5eb --- /dev/null +++ b/build/rust/cmake/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cmake" +version = "0.1.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/cmake/lib.rs b/build/rust/cmake/lib.rs new file mode 100644 index 0000000000..e0032240a4 --- /dev/null +++ b/build/rust/cmake/lib.rs @@ -0,0 +1,3 @@ +/* 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/. */ diff --git a/build/rust/derive_more/Cargo.toml b/build/rust/derive_more/Cargo.toml new file mode 100644 index 0000000000..6df64025d9 --- /dev/null +++ b/build/rust/derive_more/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "derive_more" +version = "0.99.999" +edition = "2021" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.derive_more] +version = "1.0.0-beta.2" + +[features] +add = ["derive_more/add"] +add_assign = ["derive_more/add_assign"] +as_mut = ["derive_more/as_mut"] +as_ref = ["derive_more/as_ref"] +constructor = ["derive_more/constructor"] +debug = ["derive_more/debug"] +default = ["derive_more/default"] +deref = ["derive_more/deref"] +deref_mut = ["derive_more/deref_mut"] +display = ["derive_more/display"] +error = ["derive_more/error"] +from = ["derive_more/from"] +from_str = ["derive_more/from_str"] +full = ["derive_more/full"] +index = ["derive_more/index"] +index_mut = ["derive_more/index_mut"] +into = ["derive_more/into"] +into_iterator = ["derive_more/into_iterator"] +is_variant = ["derive_more/is_variant"] +iterator = ["derive_more/iterator"] +mul = ["derive_more/mul"] +mul_assign = ["derive_more/mul_assign"] +not = ["derive_more/not"] +std = ["derive_more/std"] diff --git a/build/rust/derive_more/lib.rs b/build/rust/derive_more/lib.rs new file mode 100644 index 0000000000..1df30b23ca --- /dev/null +++ b/build/rust/derive_more/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use derive_more::*; diff --git a/build/rust/dummy-web/js-sys/Cargo.toml b/build/rust/dummy-web/js-sys/Cargo.toml new file mode 100644 index 0000000000..b0d3999ef2 --- /dev/null +++ b/build/rust/dummy-web/js-sys/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "js-sys" +version = "0.3.100" +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/dummy-web/js-sys/lib.rs b/build/rust/dummy-web/js-sys/lib.rs new file mode 100644 index 0000000000..e0032240a4 --- /dev/null +++ b/build/rust/dummy-web/js-sys/lib.rs @@ -0,0 +1,3 @@ +/* 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/. */ diff --git a/build/rust/dummy-web/wasm-bindgen/Cargo.toml b/build/rust/dummy-web/wasm-bindgen/Cargo.toml new file mode 100644 index 0000000000..a4a421466e --- /dev/null +++ b/build/rust/dummy-web/wasm-bindgen/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "wasm-bindgen" +version = "0.2.100" +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/dummy-web/wasm-bindgen/lib.rs b/build/rust/dummy-web/wasm-bindgen/lib.rs new file mode 100644 index 0000000000..e0032240a4 --- /dev/null +++ b/build/rust/dummy-web/wasm-bindgen/lib.rs @@ -0,0 +1,3 @@ +/* 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/. */ diff --git a/build/rust/dummy-web/web-sys/Cargo.toml b/build/rust/dummy-web/web-sys/Cargo.toml new file mode 100644 index 0000000000..4251c3e73d --- /dev/null +++ b/build/rust/dummy-web/web-sys/Cargo.toml @@ -0,0 +1,1423 @@ +[package] +name = "web-sys" +version = "0.3.100" +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +path = "lib.rs" + +# This list is taken from web-sys 0.3.55's Cargo.toml +[features] +AbortController = [] +AbortSignal = ["EventTarget"] +AddEventListenerOptions = [] +AesCbcParams = [] +AesCtrParams = [] +AesDerivedKeyParams = [] +AesGcmParams = [] +AesKeyAlgorithm = [] +AesKeyGenParams = [] +Algorithm = [] +AlignSetting = [] +AllowedBluetoothDevice = [] +AllowedUsbDevice = [] +AnalyserNode = ["AudioNode", "EventTarget"] +AnalyserOptions = [] +AngleInstancedArrays = [] +Animation = ["EventTarget"] +AnimationEffect = [] +AnimationEvent = ["Event"] +AnimationEventInit = [] +AnimationPlayState = [] +AnimationPlaybackEvent = ["Event"] +AnimationPlaybackEventInit = [] +AnimationPropertyDetails = [] +AnimationPropertyValueDetails = [] +AnimationTimeline = [] +AssignedNodesOptions = [] +AttestationConveyancePreference = [] +Attr = ["EventTarget", "Node"] +AttributeNameValue = [] +AudioBuffer = [] +AudioBufferOptions = [] +AudioBufferSourceNode = ["AudioNode", "AudioScheduledSourceNode", "EventTarget"] +AudioBufferSourceOptions = [] +AudioConfiguration = [] +AudioContext = ["BaseAudioContext", "EventTarget"] +AudioContextOptions = [] +AudioContextState = [] +AudioDestinationNode = ["AudioNode", "EventTarget"] +AudioListener = [] +AudioNode = ["EventTarget"] +AudioNodeOptions = [] +AudioParam = [] +AudioParamMap = [] +AudioProcessingEvent = ["Event"] +AudioScheduledSourceNode = ["AudioNode", "EventTarget"] +AudioStreamTrack = ["EventTarget", "MediaStreamTrack"] +AudioTrack = [] +AudioTrackList = ["EventTarget"] +AudioWorklet = ["Worklet"] +AudioWorkletGlobalScope = ["WorkletGlobalScope"] +AudioWorkletNode = ["AudioNode", "EventTarget"] +AudioWorkletNodeOptions = [] +AudioWorkletProcessor = [] +AuthenticationExtensionsClientInputs = [] +AuthenticationExtensionsClientOutputs = [] +AuthenticatorAssertionResponse = ["AuthenticatorResponse"] +AuthenticatorAttachment = [] +AuthenticatorAttestationResponse = ["AuthenticatorResponse"] +AuthenticatorResponse = [] +AuthenticatorSelectionCriteria = [] +AuthenticatorTransport = [] +AutoKeyword = [] +AutocompleteInfo = [] +BarProp = [] +BaseAudioContext = ["EventTarget"] +BaseComputedKeyframe = [] +BaseKeyframe = [] +BasePropertyIndexedKeyframe = [] +BasicCardRequest = [] +BasicCardResponse = [] +BasicCardType = [] +BatteryManager = ["EventTarget"] +BeforeUnloadEvent = ["Event"] +BinaryType = [] +BiquadFilterNode = ["AudioNode", "EventTarget"] +BiquadFilterOptions = [] +BiquadFilterType = [] +Blob = [] +BlobEvent = ["Event"] +BlobEventInit = [] +BlobPropertyBag = [] +BlockParsingOptions = [] +Bluetooth = ["EventTarget"] +BluetoothAdvertisingEvent = ["Event"] +BluetoothAdvertisingEventInit = [] +BluetoothCharacteristicProperties = [] +BluetoothDataFilterInit = [] +BluetoothDevice = ["EventTarget"] +BluetoothLeScanFilterInit = [] +BluetoothManufacturerDataMap = [] +BluetoothPermissionDescriptor = [] +BluetoothPermissionResult = ["EventTarget", "PermissionStatus"] +BluetoothPermissionStorage = [] +BluetoothRemoteGattCharacteristic = ["EventTarget"] +BluetoothRemoteGattDescriptor = [] +BluetoothRemoteGattServer = [] +BluetoothRemoteGattService = ["EventTarget"] +BluetoothServiceDataMap = [] +BluetoothUuid = [] +BoxQuadOptions = [] +BroadcastChannel = ["EventTarget"] +BrowserElementDownloadOptions = [] +BrowserElementExecuteScriptOptions = [] +BrowserFeedWriter = [] +BrowserFindCaseSensitivity = [] +BrowserFindDirection = [] +Cache = [] +CacheBatchOperation = [] +CacheQueryOptions = [] +CacheStorage = [] +CacheStorageNamespace = [] +CanvasCaptureMediaStream = ["EventTarget", "MediaStream"] +CanvasGradient = [] +CanvasPattern = [] +CanvasRenderingContext2d = [] +CanvasWindingRule = [] +CaretChangedReason = [] +CaretPosition = [] +CaretStateChangedEventInit = [] +CdataSection = ["CharacterData", "EventTarget", "Node", "Text"] +ChannelCountMode = [] +ChannelInterpretation = [] +ChannelMergerNode = ["AudioNode", "EventTarget"] +ChannelMergerOptions = [] +ChannelPixelLayout = [] +ChannelPixelLayoutDataType = [] +ChannelSplitterNode = ["AudioNode", "EventTarget"] +ChannelSplitterOptions = [] +CharacterData = ["EventTarget", "Node"] +CheckerboardReason = [] +CheckerboardReport = [] +CheckerboardReportService = [] +ChromeFilePropertyBag = [] +ChromeWorker = ["EventTarget", "Worker"] +Client = [] +ClientQueryOptions = [] +ClientRectsAndTexts = [] +ClientType = [] +Clients = [] +Clipboard = ["EventTarget"] +ClipboardEvent = ["Event"] +ClipboardEventInit = [] +ClipboardItem = [] +ClipboardItemOptions = [] +ClipboardPermissionDescriptor = [] +CloseEvent = ["Event"] +CloseEventInit = [] +CollectedClientData = [] +Comment = ["CharacterData", "EventTarget", "Node"] +CompositeOperation = [] +CompositionEvent = ["Event", "UiEvent"] +CompositionEventInit = [] +ComputedEffectTiming = [] +ConnStatusDict = [] +ConnectionType = [] +ConsoleCounter = [] +ConsoleCounterError = [] +ConsoleEvent = [] +ConsoleInstance = [] +ConsoleInstanceOptions = [] +ConsoleLevel = [] +ConsoleLogLevel = [] +ConsoleProfileEvent = [] +ConsoleStackEntry = [] +ConsoleTimerError = [] +ConsoleTimerLogOrEnd = [] +ConsoleTimerStart = [] +ConstantSourceNode = ["AudioNode", "AudioScheduledSourceNode", "EventTarget"] +ConstantSourceOptions = [] +ConstrainBooleanParameters = [] +ConstrainDomStringParameters = [] +ConstrainDoubleRange = [] +ConstrainLongRange = [] +ContextAttributes2d = [] +ConvertCoordinateOptions = [] +ConvolverNode = ["AudioNode", "EventTarget"] +ConvolverOptions = [] +Coordinates = [] +Credential = [] +CredentialCreationOptions = [] +CredentialRequestOptions = [] +CredentialsContainer = [] +Crypto = [] +CryptoKey = [] +CryptoKeyPair = [] +Csp = [] +CspPolicies = [] +CspReport = [] +CspReportProperties = [] +CssAnimation = ["Animation", "EventTarget"] +CssBoxType = [] +CssConditionRule = ["CssGroupingRule", "CssRule"] +CssCounterStyleRule = ["CssRule"] +CssFontFaceRule = ["CssRule"] +CssFontFeatureValuesRule = ["CssRule"] +CssGroupingRule = ["CssRule"] +CssImportRule = ["CssRule"] +CssKeyframeRule = ["CssRule"] +CssKeyframesRule = ["CssRule"] +CssMediaRule = ["CssConditionRule", "CssGroupingRule", "CssRule"] +CssNamespaceRule = ["CssRule"] +CssPageRule = ["CssRule"] +CssPseudoElement = [] +CssRule = [] +CssRuleList = [] +CssStyleDeclaration = [] +CssStyleRule = ["CssRule"] +CssStyleSheet = ["StyleSheet"] +CssStyleSheetParsingMode = [] +CssSupportsRule = ["CssConditionRule", "CssGroupingRule", "CssRule"] +CssTransition = ["Animation", "EventTarget"] +CustomElementRegistry = [] +CustomEvent = ["Event"] +CustomEventInit = [] +DataTransfer = [] +DataTransferItem = [] +DataTransferItemList = [] +DateTimeValue = [] +DecoderDoctorNotification = [] +DecoderDoctorNotificationType = [] +DedicatedWorkerGlobalScope = ["EventTarget", "WorkerGlobalScope"] +DelayNode = ["AudioNode", "EventTarget"] +DelayOptions = [] +DeviceAcceleration = [] +DeviceAccelerationInit = [] +DeviceLightEvent = ["Event"] +DeviceLightEventInit = [] +DeviceMotionEvent = ["Event"] +DeviceMotionEventInit = [] +DeviceOrientationEvent = ["Event"] +DeviceOrientationEventInit = [] +DeviceProximityEvent = ["Event"] +DeviceProximityEventInit = [] +DeviceRotationRate = [] +DeviceRotationRateInit = [] +DhKeyDeriveParams = [] +DirectionSetting = [] +Directory = [] +DisplayMediaStreamConstraints = [] +DisplayNameOptions = [] +DisplayNameResult = [] +DistanceModelType = [] +DnsCacheDict = [] +DnsCacheEntry = [] +DnsLookupDict = [] +Document = ["EventTarget", "Node"] +DocumentFragment = ["EventTarget", "Node"] +DocumentTimeline = ["AnimationTimeline"] +DocumentTimelineOptions = [] +DocumentType = ["EventTarget", "Node"] +DomError = [] +DomException = [] +DomImplementation = [] +DomMatrix = ["DomMatrixReadOnly"] +DomMatrixReadOnly = [] +DomParser = [] +DomPoint = ["DomPointReadOnly"] +DomPointInit = [] +DomPointReadOnly = [] +DomQuad = [] +DomQuadInit = [] +DomQuadJson = [] +DomRect = ["DomRectReadOnly"] +DomRectInit = [] +DomRectList = [] +DomRectReadOnly = [] +DomRequest = ["EventTarget"] +DomRequestReadyState = [] +DomStringList = [] +DomStringMap = [] +DomTokenList = [] +DomWindowResizeEventDetail = [] +DragEvent = ["Event", "MouseEvent", "UiEvent"] +DragEventInit = [] +DynamicsCompressorNode = ["AudioNode", "EventTarget"] +DynamicsCompressorOptions = [] +EcKeyAlgorithm = [] +EcKeyGenParams = [] +EcKeyImportParams = [] +EcdhKeyDeriveParams = [] +EcdsaParams = [] +EffectTiming = [] +Element = ["EventTarget", "Node"] +ElementCreationOptions = [] +ElementDefinitionOptions = [] +EndingTypes = [] +ErrorCallback = [] +ErrorEvent = ["Event"] +ErrorEventInit = [] +Event = [] +EventInit = [] +EventListener = [] +EventListenerOptions = [] +EventModifierInit = [] +EventSource = ["EventTarget"] +EventSourceInit = [] +EventTarget = [] +Exception = [] +ExtBlendMinmax = [] +ExtColorBufferFloat = [] +ExtColorBufferHalfFloat = [] +ExtDisjointTimerQuery = [] +ExtFragDepth = [] +ExtSRgb = [] +ExtShaderTextureLod = [] +ExtTextureFilterAnisotropic = [] +ExtendableEvent = ["Event"] +ExtendableEventInit = [] +ExtendableMessageEvent = ["Event", "ExtendableEvent"] +ExtendableMessageEventInit = [] +External = [] +FakePluginMimeEntry = [] +FakePluginTagInit = [] +FetchEvent = ["Event", "ExtendableEvent"] +FetchEventInit = [] +FetchObserver = ["EventTarget"] +FetchReadableStreamReadDataArray = [] +FetchReadableStreamReadDataDone = [] +FetchState = [] +File = ["Blob"] +FileCallback = [] +FileList = [] +FilePropertyBag = [] +FileReader = ["EventTarget"] +FileReaderSync = [] +FileSystem = [] +FileSystemDirectoryEntry = ["FileSystemEntry"] +FileSystemDirectoryReader = [] +FileSystemEntriesCallback = [] +FileSystemEntry = [] +FileSystemEntryCallback = [] +FileSystemFileEntry = ["FileSystemEntry"] +FileSystemFlags = [] +FillMode = [] +FlashClassification = [] +FlexLineGrowthState = [] +FocusEvent = ["Event", "UiEvent"] +FocusEventInit = [] +FontFace = [] +FontFaceDescriptors = [] +FontFaceLoadStatus = [] +FontFaceSet = ["EventTarget"] +FontFaceSetIterator = [] +FontFaceSetIteratorResult = [] +FontFaceSetLoadEvent = ["Event"] +FontFaceSetLoadEventInit = [] +FontFaceSetLoadStatus = [] +FormData = [] +FrameType = [] +FuzzingFunctions = [] +GainNode = ["AudioNode", "EventTarget"] +GainOptions = [] +Gamepad = [] +GamepadAxisMoveEvent = ["Event", "GamepadEvent"] +GamepadAxisMoveEventInit = [] +GamepadButton = [] +GamepadButtonEvent = ["Event", "GamepadEvent"] +GamepadButtonEventInit = [] +GamepadEvent = ["Event"] +GamepadEventInit = [] +GamepadHand = [] +GamepadHapticActuator = [] +GamepadHapticActuatorType = [] +GamepadMappingType = [] +GamepadPose = [] +GamepadServiceTest = [] +Geolocation = [] +GetNotificationOptions = [] +GetRootNodeOptions = [] +GetUserMediaRequest = [] +Gpu = [] +GpuAdapter = [] +GpuAddressMode = [] +GpuBindGroup = [] +GpuBindGroupDescriptor = [] +GpuBindGroupEntry = [] +GpuBindGroupLayout = [] +GpuBindGroupLayoutDescriptor = [] +GpuBindGroupLayoutEntry = [] +GpuBlendComponent = [] +GpuBlendFactor = [] +GpuBlendOperation = [] +GpuBlendState = [] +GpuBuffer = [] +GpuBufferBinding = [] +GpuBufferBindingLayout = [] +GpuBufferBindingType = [] +GpuBufferDescriptor = [] +GpuBufferUsage = [] +GpuCanvasCompositingAlphaMode = [] +GpuCanvasConfiguration = [] +GpuCanvasContext = [] +GpuColorDict = [] +GpuColorTargetState = [] +GpuColorWrite = [] +GpuCommandBuffer = [] +GpuCommandBufferDescriptor = [] +GpuCommandEncoder = [] +GpuCommandEncoderDescriptor = [] +GpuCompareFunction = [] +GpuCompilationInfo = [] +GpuCompilationMessage = [] +GpuCompilationMessageType = [] +GpuComputePassDescriptor = [] +GpuComputePassEncoder = [] +GpuComputePipeline = [] +GpuComputePipelineDescriptor = [] +GpuCullMode = [] +GpuDepthStencilState = [] +GpuDevice = ["EventTarget"] +GpuDeviceDescriptor = [] +GpuDeviceLostInfo = [] +GpuDeviceLostReason = [] +GpuErrorFilter = [] +GpuExtent3dDict = [] +GpuExternalTexture = [] +GpuExternalTextureBindingLayout = [] +GpuExternalTextureDescriptor = [] +GpuFeatureName = [] +GpuFilterMode = [] +GpuFragmentState = [] +GpuFrontFace = [] +GpuImageCopyBuffer = [] +GpuImageCopyExternalImage = [] +GpuImageCopyTexture = [] +GpuImageCopyTextureTagged = [] +GpuImageDataLayout = [] +GpuIndexFormat = [] +GpuLoadOp = [] +GpuMapMode = [] +GpuMultisampleState = [] +GpuObjectDescriptorBase = [] +GpuOrigin2dDict = [] +GpuOrigin3dDict = [] +GpuOutOfMemoryError = [] +GpuPipelineDescriptorBase = [] +GpuPipelineLayout = [] +GpuPipelineLayoutDescriptor = [] +GpuPipelineStatisticName = [] +GpuPowerPreference = [] +GpuPredefinedColorSpace = [] +GpuPrimitiveState = [] +GpuPrimitiveTopology = [] +GpuProgrammableStage = [] +GpuQuerySet = [] +GpuQuerySetDescriptor = [] +GpuQueryType = [] +GpuQueue = [] +GpuRenderBundle = [] +GpuRenderBundleDescriptor = [] +GpuRenderBundleEncoder = [] +GpuRenderBundleEncoderDescriptor = [] +GpuRenderPassColorAttachment = [] +GpuRenderPassDepthStencilAttachment = [] +GpuRenderPassDescriptor = [] +GpuRenderPassEncoder = [] +GpuRenderPassLayout = [] +GpuRenderPipeline = [] +GpuRenderPipelineDescriptor = [] +GpuRequestAdapterOptions = [] +GpuSampler = [] +GpuSamplerBindingLayout = [] +GpuSamplerBindingType = [] +GpuSamplerDescriptor = [] +GpuShaderModule = [] +GpuShaderModuleDescriptor = [] +GpuShaderStage = [] +GpuStencilFaceState = [] +GpuStencilOperation = [] +GpuStorageTextureAccess = [] +GpuStorageTextureBindingLayout = [] +GpuStoreOp = [] +GpuSupportedFeatures = [] +GpuSupportedLimits = [] +GpuTexture = [] +GpuTextureAspect = [] +GpuTextureBindingLayout = [] +GpuTextureDescriptor = [] +GpuTextureDimension = [] +GpuTextureFormat = [] +GpuTextureSampleType = [] +GpuTextureUsage = [] +GpuTextureView = [] +GpuTextureViewDescriptor = [] +GpuTextureViewDimension = [] +GpuUncapturedErrorEvent = ["Event"] +GpuUncapturedErrorEventInit = [] +GpuValidationError = [] +GpuVertexAttribute = [] +GpuVertexBufferLayout = [] +GpuVertexFormat = [] +GpuVertexState = [] +GpuVertexStepMode = [] +GridDeclaration = [] +GridTrackState = [] +GroupedHistoryEventInit = [] +HalfOpenInfoDict = [] +HashChangeEvent = ["Event"] +HashChangeEventInit = [] +Headers = [] +HeadersGuardEnum = [] +Hid = ["EventTarget"] +HidCollectionInfo = [] +HidConnectionEvent = ["Event"] +HidConnectionEventInit = [] +HidDevice = ["EventTarget"] +HidDeviceFilter = [] +HidDeviceRequestOptions = [] +HidInputReportEvent = ["Event"] +HidInputReportEventInit = [] +HidReportInfo = [] +HidReportItem = [] +HidUnitSystem = [] +HiddenPluginEventInit = [] +History = [] +HitRegionOptions = [] +HkdfParams = [] +HmacDerivedKeyParams = [] +HmacImportParams = [] +HmacKeyAlgorithm = [] +HmacKeyGenParams = [] +HtmlAllCollection = [] +HtmlAnchorElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlAreaElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlAudioElement = ["Element", "EventTarget", "HtmlElement", "HtmlMediaElement", "Node"] +HtmlBaseElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlBodyElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlBrElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlButtonElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlCanvasElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlCollection = [] +HtmlDListElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDataElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDataListElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDetailsElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDialogElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDirectoryElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDivElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlDocument = ["Document", "EventTarget", "Node"] +HtmlElement = ["Element", "EventTarget", "Node"] +HtmlEmbedElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlFieldSetElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlFontElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlFormControlsCollection = ["HtmlCollection"] +HtmlFormElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlFrameElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlFrameSetElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlHeadElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlHeadingElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlHrElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlHtmlElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlIFrameElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlImageElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlInputElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlLabelElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlLegendElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlLiElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlLinkElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlMapElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlMediaElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlMenuElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlMenuItemElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlMetaElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlMeterElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlModElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlOListElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlObjectElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlOptGroupElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlOptionElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlOptionsCollection = ["HtmlCollection"] +HtmlOutputElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlParagraphElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlParamElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlPictureElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlPreElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlProgressElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlQuoteElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlScriptElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlSelectElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlSlotElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlSourceElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlSpanElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlStyleElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTableCaptionElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTableCellElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTableColElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTableElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTableRowElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTableSectionElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTemplateElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTextAreaElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTimeElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTitleElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlTrackElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlUListElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlUnknownElement = ["Element", "EventTarget", "HtmlElement", "Node"] +HtmlVideoElement = ["Element", "EventTarget", "HtmlElement", "HtmlMediaElement", "Node"] +HttpConnDict = [] +HttpConnInfo = [] +HttpConnectionElement = [] +IdbCursor = [] +IdbCursorDirection = [] +IdbCursorWithValue = ["IdbCursor"] +IdbDatabase = ["EventTarget"] +IdbFactory = [] +IdbFileHandle = ["EventTarget"] +IdbFileMetadataParameters = [] +IdbFileRequest = ["DomRequest", "EventTarget"] +IdbIndex = [] +IdbIndexParameters = [] +IdbKeyRange = [] +IdbLocaleAwareKeyRange = ["IdbKeyRange"] +IdbMutableFile = ["EventTarget"] +IdbObjectStore = [] +IdbObjectStoreParameters = [] +IdbOpenDbOptions = [] +IdbOpenDbRequest = ["EventTarget", "IdbRequest"] +IdbRequest = ["EventTarget"] +IdbRequestReadyState = [] +IdbTransaction = ["EventTarget"] +IdbTransactionMode = [] +IdbVersionChangeEvent = ["Event"] +IdbVersionChangeEventInit = [] +IdleDeadline = [] +IdleRequestOptions = [] +IirFilterNode = ["AudioNode", "EventTarget"] +IirFilterOptions = [] +ImageBitmap = [] +ImageBitmapFormat = [] +ImageBitmapRenderingContext = [] +ImageCapture = [] +ImageCaptureError = [] +ImageCaptureErrorEvent = ["Event"] +ImageCaptureErrorEventInit = [] +ImageData = [] +InputEvent = ["Event", "UiEvent"] +InputEventInit = [] +InstallTriggerData = [] +IntersectionObserver = [] +IntersectionObserverEntry = [] +IntersectionObserverEntryInit = [] +IntersectionObserverInit = [] +IntlUtils = [] +IterableKeyAndValueResult = [] +IterableKeyOrValueResult = [] +IterationCompositeOperation = [] +JsonWebKey = [] +KeyAlgorithm = [] +KeyEvent = [] +KeyIdsInitData = [] +KeyboardEvent = ["Event", "UiEvent"] +KeyboardEventInit = [] +KeyframeEffect = ["AnimationEffect"] +KeyframeEffectOptions = [] +L10nElement = [] +L10nValue = [] +LifecycleCallbacks = [] +LineAlignSetting = [] +ListBoxObject = [] +LocalMediaStream = ["EventTarget", "MediaStream"] +LocaleInfo = [] +Location = [] +MediaCapabilities = [] +MediaCapabilitiesInfo = [] +MediaConfiguration = [] +MediaDecodingConfiguration = [] +MediaDecodingType = [] +MediaDeviceInfo = [] +MediaDeviceKind = [] +MediaDevices = ["EventTarget"] +MediaElementAudioSourceNode = ["AudioNode", "EventTarget"] +MediaElementAudioSourceOptions = [] +MediaEncodingConfiguration = [] +MediaEncodingType = [] +MediaEncryptedEvent = ["Event"] +MediaError = [] +MediaKeyError = ["Event"] +MediaKeyMessageEvent = ["Event"] +MediaKeyMessageEventInit = [] +MediaKeyMessageType = [] +MediaKeyNeededEventInit = [] +MediaKeySession = ["EventTarget"] +MediaKeySessionType = [] +MediaKeyStatus = [] +MediaKeyStatusMap = [] +MediaKeySystemAccess = [] +MediaKeySystemConfiguration = [] +MediaKeySystemMediaCapability = [] +MediaKeySystemStatus = [] +MediaKeys = [] +MediaKeysPolicy = [] +MediaKeysRequirement = [] +MediaList = [] +MediaQueryList = ["EventTarget"] +MediaQueryListEvent = ["Event"] +MediaQueryListEventInit = [] +MediaRecorder = ["EventTarget"] +MediaRecorderErrorEvent = ["Event"] +MediaRecorderErrorEventInit = [] +MediaRecorderOptions = [] +MediaSource = ["EventTarget"] +MediaSourceEndOfStreamError = [] +MediaSourceEnum = [] +MediaSourceReadyState = [] +MediaStream = ["EventTarget"] +MediaStreamAudioDestinationNode = ["AudioNode", "EventTarget"] +MediaStreamAudioSourceNode = ["AudioNode", "EventTarget"] +MediaStreamAudioSourceOptions = [] +MediaStreamConstraints = [] +MediaStreamError = [] +MediaStreamEvent = ["Event"] +MediaStreamEventInit = [] +MediaStreamTrack = ["EventTarget"] +MediaStreamTrackEvent = ["Event"] +MediaStreamTrackEventInit = [] +MediaStreamTrackState = [] +MediaTrackConstraintSet = [] +MediaTrackConstraints = [] +MediaTrackSettings = [] +MediaTrackSupportedConstraints = [] +MessageChannel = [] +MessageEvent = ["Event"] +MessageEventInit = [] +MessagePort = ["EventTarget"] +MidiAccess = ["EventTarget"] +MidiConnectionEvent = ["Event"] +MidiConnectionEventInit = [] +MidiInput = ["EventTarget", "MidiPort"] +MidiInputMap = [] +MidiMessageEvent = ["Event"] +MidiMessageEventInit = [] +MidiOptions = [] +MidiOutput = ["EventTarget", "MidiPort"] +MidiOutputMap = [] +MidiPort = ["EventTarget"] +MidiPortConnectionState = [] +MidiPortDeviceState = [] +MidiPortType = [] +MimeType = [] +MimeTypeArray = [] +MouseEvent = ["Event", "UiEvent"] +MouseEventInit = [] +MouseScrollEvent = ["Event", "MouseEvent", "UiEvent"] +MozDebug = [] +MutationEvent = ["Event"] +MutationObserver = [] +MutationObserverInit = [] +MutationObservingInfo = [] +MutationRecord = [] +NamedNodeMap = [] +NativeOsFileReadOptions = [] +NativeOsFileWriteAtomicOptions = [] +NavigationType = [] +Navigator = [] +NavigatorAutomationInformation = [] +NetworkCommandOptions = [] +NetworkInformation = ["EventTarget"] +NetworkResultOptions = [] +Node = ["EventTarget"] +NodeFilter = [] +NodeIterator = [] +NodeList = [] +Notification = ["EventTarget"] +NotificationBehavior = [] +NotificationDirection = [] +NotificationEvent = ["Event", "ExtendableEvent"] +NotificationEventInit = [] +NotificationOptions = [] +NotificationPermission = [] +ObserverCallback = [] +OesElementIndexUint = [] +OesStandardDerivatives = [] +OesTextureFloat = [] +OesTextureFloatLinear = [] +OesTextureHalfFloat = [] +OesTextureHalfFloatLinear = [] +OesVertexArrayObject = [] +OfflineAudioCompletionEvent = ["Event"] +OfflineAudioCompletionEventInit = [] +OfflineAudioContext = ["BaseAudioContext", "EventTarget"] +OfflineAudioContextOptions = [] +OfflineResourceList = ["EventTarget"] +OffscreenCanvas = ["EventTarget"] +OpenWindowEventDetail = [] +OptionalEffectTiming = [] +OrientationLockType = [] +OrientationType = [] +OscillatorNode = ["AudioNode", "AudioScheduledSourceNode", "EventTarget"] +OscillatorOptions = [] +OscillatorType = [] +OverSampleType = [] +PageTransitionEvent = ["Event"] +PageTransitionEventInit = [] +PaintRequest = [] +PaintRequestList = [] +PaintWorkletGlobalScope = ["WorkletGlobalScope"] +PannerNode = ["AudioNode", "EventTarget"] +PannerOptions = [] +PanningModelType = [] +Path2d = [] +PaymentAddress = [] +PaymentComplete = [] +PaymentMethodChangeEvent = ["Event", "PaymentRequestUpdateEvent"] +PaymentMethodChangeEventInit = [] +PaymentRequestUpdateEvent = ["Event"] +PaymentRequestUpdateEventInit = [] +PaymentResponse = [] +Pbkdf2Params = [] +PcImplIceConnectionState = [] +PcImplIceGatheringState = [] +PcImplSignalingState = [] +PcObserverStateType = [] +Performance = ["EventTarget"] +PerformanceEntry = [] +PerformanceEntryEventInit = [] +PerformanceEntryFilterOptions = [] +PerformanceMark = ["PerformanceEntry"] +PerformanceMeasure = ["PerformanceEntry"] +PerformanceNavigation = [] +PerformanceNavigationTiming = ["PerformanceEntry", "PerformanceResourceTiming"] +PerformanceObserver = [] +PerformanceObserverEntryList = [] +PerformanceObserverInit = [] +PerformanceResourceTiming = ["PerformanceEntry"] +PerformanceServerTiming = [] +PerformanceTiming = [] +PeriodicWave = [] +PeriodicWaveConstraints = [] +PeriodicWaveOptions = [] +PermissionDescriptor = [] +PermissionName = [] +PermissionState = [] +PermissionStatus = ["EventTarget"] +Permissions = [] +PlaybackDirection = [] +Plugin = [] +PluginArray = [] +PluginCrashedEventInit = [] +PointerEvent = ["Event", "MouseEvent", "UiEvent"] +PointerEventInit = [] +PopStateEvent = ["Event"] +PopStateEventInit = [] +PopupBlockedEvent = ["Event"] +PopupBlockedEventInit = [] +Position = [] +PositionAlignSetting = [] +PositionError = [] +PositionOptions = [] +Presentation = [] +PresentationAvailability = ["EventTarget"] +PresentationConnection = ["EventTarget"] +PresentationConnectionAvailableEvent = ["Event"] +PresentationConnectionAvailableEventInit = [] +PresentationConnectionBinaryType = [] +PresentationConnectionCloseEvent = ["Event"] +PresentationConnectionCloseEventInit = [] +PresentationConnectionClosedReason = [] +PresentationConnectionList = ["EventTarget"] +PresentationConnectionState = [] +PresentationReceiver = [] +PresentationRequest = ["EventTarget"] +PresentationStyle = [] +ProcessingInstruction = ["CharacterData", "EventTarget", "Node"] +ProfileTimelineLayerRect = [] +ProfileTimelineMarker = [] +ProfileTimelineMessagePortOperationType = [] +ProfileTimelineStackFrame = [] +ProfileTimelineWorkerOperationType = [] +ProgressEvent = ["Event"] +ProgressEventInit = [] +PromiseNativeHandler = [] +PromiseRejectionEvent = ["Event"] +PromiseRejectionEventInit = [] +PublicKeyCredential = ["Credential"] +PublicKeyCredentialCreationOptions = [] +PublicKeyCredentialDescriptor = [] +PublicKeyCredentialEntity = [] +PublicKeyCredentialParameters = [] +PublicKeyCredentialRequestOptions = [] +PublicKeyCredentialRpEntity = [] +PublicKeyCredentialType = [] +PublicKeyCredentialUserEntity = [] +PushEncryptionKeyName = [] +PushEvent = ["Event", "ExtendableEvent"] +PushEventInit = [] +PushManager = [] +PushMessageData = [] +PushPermissionState = [] +PushSubscription = [] +PushSubscriptionInit = [] +PushSubscriptionJson = [] +PushSubscriptionKeys = [] +PushSubscriptionOptions = [] +PushSubscriptionOptionsInit = [] +QueuingStrategy = [] +RadioNodeList = ["NodeList"] +Range = [] +RcwnPerfStats = [] +RcwnStatus = [] +ReadableStream = [] +ReadableStreamByobReadResult = [] +ReadableStreamByobReader = [] +ReadableStreamDefaultReadResult = [] +ReadableStreamDefaultReader = [] +ReadableStreamGetReaderOptions = [] +ReadableStreamIteratorOptions = [] +ReadableStreamReaderMode = [] +ReadableWritablePair = [] +RecordingState = [] +ReferrerPolicy = [] +RegisterRequest = [] +RegisterResponse = [] +RegisteredKey = [] +RegistrationOptions = [] +Request = [] +RequestCache = [] +RequestCredentials = [] +RequestDestination = [] +RequestDeviceOptions = [] +RequestInit = [] +RequestMediaKeySystemAccessNotification = [] +RequestMode = [] +RequestRedirect = [] +ResizeObserver = [] +ResizeObserverBoxOptions = [] +ResizeObserverEntry = [] +ResizeObserverOptions = [] +ResizeObserverSize = [] +Response = [] +ResponseInit = [] +ResponseType = [] +RsaHashedImportParams = [] +RsaOaepParams = [] +RsaOtherPrimesInfo = [] +RsaPssParams = [] +RtcAnswerOptions = [] +RtcBundlePolicy = [] +RtcCertificate = [] +RtcCertificateExpiration = [] +RtcCodecStats = [] +RtcConfiguration = [] +RtcDataChannel = ["EventTarget"] +RtcDataChannelEvent = ["Event"] +RtcDataChannelEventInit = [] +RtcDataChannelInit = [] +RtcDataChannelState = [] +RtcDataChannelType = [] +RtcDegradationPreference = [] +RtcFecParameters = [] +RtcIceCandidate = [] +RtcIceCandidateInit = [] +RtcIceCandidatePairStats = [] +RtcIceCandidateStats = [] +RtcIceComponentStats = [] +RtcIceConnectionState = [] +RtcIceCredentialType = [] +RtcIceGatheringState = [] +RtcIceServer = [] +RtcIceTransportPolicy = [] +RtcIdentityAssertion = [] +RtcIdentityAssertionResult = [] +RtcIdentityProvider = [] +RtcIdentityProviderDetails = [] +RtcIdentityProviderOptions = [] +RtcIdentityProviderRegistrar = [] +RtcIdentityValidationResult = [] +RtcInboundRtpStreamStats = [] +RtcLifecycleEvent = [] +RtcMediaStreamStats = [] +RtcMediaStreamTrackStats = [] +RtcOfferAnswerOptions = [] +RtcOfferOptions = [] +RtcOutboundRtpStreamStats = [] +RtcPeerConnection = ["EventTarget"] +RtcPeerConnectionIceEvent = ["Event"] +RtcPeerConnectionIceEventInit = [] +RtcPriorityType = [] +RtcRtcpParameters = [] +RtcRtpCodecParameters = [] +RtcRtpContributingSource = [] +RtcRtpEncodingParameters = [] +RtcRtpHeaderExtensionParameters = [] +RtcRtpParameters = [] +RtcRtpReceiver = [] +RtcRtpSender = [] +RtcRtpSourceEntry = [] +RtcRtpSourceEntryType = [] +RtcRtpSynchronizationSource = [] +RtcRtpTransceiver = [] +RtcRtpTransceiverDirection = [] +RtcRtpTransceiverInit = [] +RtcRtxParameters = [] +RtcSdpType = [] +RtcSessionDescription = [] +RtcSessionDescriptionInit = [] +RtcSignalingState = [] +RtcStats = [] +RtcStatsIceCandidatePairState = [] +RtcStatsIceCandidateType = [] +RtcStatsReport = [] +RtcStatsReportInternal = [] +RtcStatsType = [] +RtcTrackEvent = ["Event"] +RtcTrackEventInit = [] +RtcTransportStats = [] +RtcdtmfSender = ["EventTarget"] +RtcdtmfToneChangeEvent = ["Event"] +RtcdtmfToneChangeEventInit = [] +RtcrtpContributingSourceStats = [] +RtcrtpStreamStats = [] +Screen = ["EventTarget"] +ScreenColorGamut = [] +ScreenLuminance = [] +ScreenOrientation = ["EventTarget"] +ScriptProcessorNode = ["AudioNode", "EventTarget"] +ScrollAreaEvent = ["Event", "UiEvent"] +ScrollBehavior = [] +ScrollBoxObject = [] +ScrollIntoViewOptions = [] +ScrollLogicalPosition = [] +ScrollOptions = [] +ScrollRestoration = [] +ScrollSetting = [] +ScrollState = [] +ScrollToOptions = [] +ScrollViewChangeEventInit = [] +SecurityPolicyViolationEvent = ["Event"] +SecurityPolicyViolationEventDisposition = [] +SecurityPolicyViolationEventInit = [] +Selection = [] +ServerSocketOptions = [] +ServiceWorker = ["EventTarget"] +ServiceWorkerContainer = ["EventTarget"] +ServiceWorkerGlobalScope = ["EventTarget", "WorkerGlobalScope"] +ServiceWorkerRegistration = ["EventTarget"] +ServiceWorkerState = [] +ServiceWorkerUpdateViaCache = [] +ShadowRoot = ["DocumentFragment", "EventTarget", "Node"] +ShadowRootInit = [] +ShadowRootMode = [] +SharedWorker = ["EventTarget"] +SharedWorkerGlobalScope = ["EventTarget", "WorkerGlobalScope"] +SignResponse = [] +SocketElement = [] +SocketOptions = [] +SocketReadyState = [] +SocketsDict = [] +SourceBuffer = ["EventTarget"] +SourceBufferAppendMode = [] +SourceBufferList = ["EventTarget"] +SpeechGrammar = [] +SpeechGrammarList = [] +SpeechRecognition = ["EventTarget"] +SpeechRecognitionAlternative = [] +SpeechRecognitionError = ["Event"] +SpeechRecognitionErrorCode = [] +SpeechRecognitionErrorInit = [] +SpeechRecognitionEvent = ["Event"] +SpeechRecognitionEventInit = [] +SpeechRecognitionResult = [] +SpeechRecognitionResultList = [] +SpeechSynthesis = ["EventTarget"] +SpeechSynthesisErrorCode = [] +SpeechSynthesisErrorEvent = ["Event", "SpeechSynthesisEvent"] +SpeechSynthesisErrorEventInit = [] +SpeechSynthesisEvent = ["Event"] +SpeechSynthesisEventInit = [] +SpeechSynthesisUtterance = ["EventTarget"] +SpeechSynthesisVoice = [] +StereoPannerNode = ["AudioNode", "EventTarget"] +StereoPannerOptions = [] +Storage = [] +StorageEstimate = [] +StorageEvent = ["Event"] +StorageEventInit = [] +StorageManager = [] +StorageType = [] +StreamPipeOptions = [] +StyleRuleChangeEventInit = [] +StyleSheet = [] +StyleSheetApplicableStateChangeEventInit = [] +StyleSheetChangeEventInit = [] +StyleSheetList = [] +SubtleCrypto = [] +SupportedType = [] +SvgAngle = [] +SvgAnimateElement = ["Element", "EventTarget", "Node", "SvgAnimationElement", "SvgElement"] +SvgAnimateMotionElement = ["Element", "EventTarget", "Node", "SvgAnimationElement", "SvgElement"] +SvgAnimateTransformElement = ["Element", "EventTarget", "Node", "SvgAnimationElement", "SvgElement"] +SvgAnimatedAngle = [] +SvgAnimatedBoolean = [] +SvgAnimatedEnumeration = [] +SvgAnimatedInteger = [] +SvgAnimatedLength = [] +SvgAnimatedLengthList = [] +SvgAnimatedNumber = [] +SvgAnimatedNumberList = [] +SvgAnimatedPreserveAspectRatio = [] +SvgAnimatedRect = [] +SvgAnimatedString = [] +SvgAnimatedTransformList = [] +SvgAnimationElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgBoundingBoxOptions = [] +SvgCircleElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgClipPathElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgComponentTransferFunctionElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgDefsElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgDescElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgElement = ["Element", "EventTarget", "Node"] +SvgEllipseElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgFilterElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgForeignObjectElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgGeometryElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgGradientElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgGraphicsElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgImageElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgLength = [] +SvgLengthList = [] +SvgLineElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgLinearGradientElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGradientElement"] +SvgMarkerElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgMaskElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgMatrix = [] +SvgMetadataElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgNumber = [] +SvgNumberList = [] +SvgPathElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgPathSeg = [] +SvgPathSegArcAbs = ["SvgPathSeg"] +SvgPathSegArcRel = ["SvgPathSeg"] +SvgPathSegClosePath = ["SvgPathSeg"] +SvgPathSegCurvetoCubicAbs = ["SvgPathSeg"] +SvgPathSegCurvetoCubicRel = ["SvgPathSeg"] +SvgPathSegCurvetoCubicSmoothAbs = ["SvgPathSeg"] +SvgPathSegCurvetoCubicSmoothRel = ["SvgPathSeg"] +SvgPathSegCurvetoQuadraticAbs = ["SvgPathSeg"] +SvgPathSegCurvetoQuadraticRel = ["SvgPathSeg"] +SvgPathSegCurvetoQuadraticSmoothAbs = ["SvgPathSeg"] +SvgPathSegCurvetoQuadraticSmoothRel = ["SvgPathSeg"] +SvgPathSegLinetoAbs = ["SvgPathSeg"] +SvgPathSegLinetoHorizontalAbs = ["SvgPathSeg"] +SvgPathSegLinetoHorizontalRel = ["SvgPathSeg"] +SvgPathSegLinetoRel = ["SvgPathSeg"] +SvgPathSegLinetoVerticalAbs = ["SvgPathSeg"] +SvgPathSegLinetoVerticalRel = ["SvgPathSeg"] +SvgPathSegList = [] +SvgPathSegMovetoAbs = ["SvgPathSeg"] +SvgPathSegMovetoRel = ["SvgPathSeg"] +SvgPatternElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgPoint = [] +SvgPointList = [] +SvgPolygonElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgPolylineElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgPreserveAspectRatio = [] +SvgRadialGradientElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGradientElement"] +SvgRect = [] +SvgRectElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGeometryElement", "SvgGraphicsElement"] +SvgScriptElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgSetElement = ["Element", "EventTarget", "Node", "SvgAnimationElement", "SvgElement"] +SvgStopElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgStringList = [] +SvgStyleElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgSwitchElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgSymbolElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgTextContentElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgTextElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement", "SvgTextContentElement", "SvgTextPositioningElement"] +SvgTextPathElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement", "SvgTextContentElement"] +SvgTextPositioningElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement", "SvgTextContentElement"] +SvgTitleElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgTransform = [] +SvgTransformList = [] +SvgUnitTypes = [] +SvgUseElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgViewElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgZoomAndPan = [] +SvgaElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgfeBlendElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeColorMatrixElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeComponentTransferElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeCompositeElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeConvolveMatrixElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeDiffuseLightingElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeDisplacementMapElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeDistantLightElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeDropShadowElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeFloodElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeFuncAElement = ["Element", "EventTarget", "Node", "SvgComponentTransferFunctionElement", "SvgElement"] +SvgfeFuncBElement = ["Element", "EventTarget", "Node", "SvgComponentTransferFunctionElement", "SvgElement"] +SvgfeFuncGElement = ["Element", "EventTarget", "Node", "SvgComponentTransferFunctionElement", "SvgElement"] +SvgfeFuncRElement = ["Element", "EventTarget", "Node", "SvgComponentTransferFunctionElement", "SvgElement"] +SvgfeGaussianBlurElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeImageElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeMergeElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeMergeNodeElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeMorphologyElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeOffsetElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfePointLightElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeSpecularLightingElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeSpotLightElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeTileElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgfeTurbulenceElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvggElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgmPathElement = ["Element", "EventTarget", "Node", "SvgElement"] +SvgsvgElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement"] +SvgtSpanElement = ["Element", "EventTarget", "Node", "SvgElement", "SvgGraphicsElement", "SvgTextContentElement", "SvgTextPositioningElement"] +TcpReadyState = [] +TcpServerSocket = ["EventTarget"] +TcpServerSocketEvent = ["Event"] +TcpServerSocketEventInit = [] +TcpSocket = ["EventTarget"] +TcpSocketBinaryType = [] +TcpSocketErrorEvent = ["Event"] +TcpSocketErrorEventInit = [] +TcpSocketEvent = ["Event"] +TcpSocketEventInit = [] +Text = ["CharacterData", "EventTarget", "Node"] +TextDecodeOptions = [] +TextDecoder = [] +TextDecoderOptions = [] +TextEncoder = [] +TextMetrics = [] +TextTrack = ["EventTarget"] +TextTrackCue = ["EventTarget"] +TextTrackCueList = [] +TextTrackKind = [] +TextTrackList = ["EventTarget"] +TextTrackMode = [] +TimeEvent = ["Event"] +TimeRanges = [] +Touch = [] +TouchEvent = ["Event", "UiEvent"] +TouchEventInit = [] +TouchInit = [] +TouchList = [] +TrackEvent = ["Event"] +TrackEventInit = [] +TransformStream = [] +TransitionEvent = ["Event"] +TransitionEventInit = [] +Transport = [] +TreeBoxObject = [] +TreeCellInfo = [] +TreeView = [] +TreeWalker = [] +U2f = [] +U2fClientData = [] +UdpMessageEventInit = [] +UdpOptions = [] +UiEvent = ["Event"] +UiEventInit = [] +Url = [] +UrlSearchParams = [] +Usb = ["EventTarget"] +UsbAlternateInterface = [] +UsbConfiguration = [] +UsbConnectionEvent = ["Event"] +UsbConnectionEventInit = [] +UsbControlTransferParameters = [] +UsbDevice = [] +UsbDeviceFilter = [] +UsbDeviceRequestOptions = [] +UsbDirection = [] +UsbEndpoint = [] +UsbEndpointType = [] +UsbInTransferResult = [] +UsbInterface = [] +UsbIsochronousInTransferPacket = [] +UsbIsochronousInTransferResult = [] +UsbIsochronousOutTransferPacket = [] +UsbIsochronousOutTransferResult = [] +UsbOutTransferResult = [] +UsbPermissionDescriptor = [] +UsbPermissionResult = ["EventTarget", "PermissionStatus"] +UsbPermissionStorage = [] +UsbRecipient = [] +UsbRequestType = [] +UsbTransferStatus = [] +UserProximityEvent = ["Event"] +UserProximityEventInit = [] +UserVerificationRequirement = [] +ValidityState = [] +ValueEvent = ["Event"] +ValueEventInit = [] +VideoConfiguration = [] +VideoFacingModeEnum = [] +VideoPlaybackQuality = [] +VideoStreamTrack = ["EventTarget", "MediaStreamTrack"] +VideoTrack = [] +VideoTrackList = ["EventTarget"] +VisibilityState = [] +VoidCallback = [] +VrDisplay = ["EventTarget"] +VrDisplayCapabilities = [] +VrEye = [] +VrEyeParameters = [] +VrFieldOfView = [] +VrFrameData = [] +VrLayer = [] +VrMockController = [] +VrMockDisplay = [] +VrPose = [] +VrServiceTest = [] +VrStageParameters = [] +VrSubmitFrameResult = [] +VttCue = ["EventTarget", "TextTrackCue"] +VttRegion = [] +WakeLock = [] +WakeLockSentinel = ["EventTarget"] +WakeLockType = [] +WatchAdvertisementsOptions = [] +WaveShaperNode = ["AudioNode", "EventTarget"] +WaveShaperOptions = [] +WebGl2RenderingContext = [] +WebGlActiveInfo = [] +WebGlBuffer = [] +WebGlContextAttributes = [] +WebGlContextEvent = ["Event"] +WebGlContextEventInit = [] +WebGlFramebuffer = [] +WebGlPowerPreference = [] +WebGlProgram = [] +WebGlQuery = [] +WebGlRenderbuffer = [] +WebGlRenderingContext = [] +WebGlSampler = [] +WebGlShader = [] +WebGlShaderPrecisionFormat = [] +WebGlSync = [] +WebGlTexture = [] +WebGlTransformFeedback = [] +WebGlUniformLocation = [] +WebGlVertexArrayObject = [] +WebKitCssMatrix = ["DomMatrix", "DomMatrixReadOnly"] +WebSocket = ["EventTarget"] +WebSocketDict = [] +WebSocketElement = [] +WebglColorBufferFloat = [] +WebglCompressedTextureAstc = [] +WebglCompressedTextureAtc = [] +WebglCompressedTextureEtc = [] +WebglCompressedTextureEtc1 = [] +WebglCompressedTexturePvrtc = [] +WebglCompressedTextureS3tc = [] +WebglCompressedTextureS3tcSrgb = [] +WebglDebugRendererInfo = [] +WebglDebugShaders = [] +WebglDepthTexture = [] +WebglDrawBuffers = [] +WebglLoseContext = [] +WebrtcGlobalStatisticsReport = [] +WheelEvent = ["Event", "MouseEvent", "UiEvent"] +WheelEventInit = [] +WidevineCdmManifest = [] +Window = ["EventTarget"] +WindowClient = ["Client"] +Worker = ["EventTarget"] +WorkerDebuggerGlobalScope = ["EventTarget"] +WorkerGlobalScope = ["EventTarget"] +WorkerLocation = [] +WorkerNavigator = [] +WorkerOptions = [] +WorkerType = [] +Worklet = [] +WorkletGlobalScope = [] +WorkletOptions = [] +WritableStream = [] +WritableStreamDefaultWriter = [] +XPathExpression = [] +XPathNsResolver = [] +XPathResult = [] +XmlDocument = ["Document", "EventTarget", "Node"] +XmlHttpRequest = ["EventTarget", "XmlHttpRequestEventTarget"] +XmlHttpRequestEventTarget = ["EventTarget"] +XmlHttpRequestResponseType = [] +XmlHttpRequestUpload = ["EventTarget", "XmlHttpRequestEventTarget"] +XmlSerializer = [] +Xr = ["EventTarget"] +XrBoundedReferenceSpace = ["EventTarget", "XrReferenceSpace", "XrSpace"] +XrEye = [] +XrFrame = [] +XrHandedness = [] +XrInputSource = [] +XrInputSourceArray = [] +XrInputSourceEvent = ["Event"] +XrInputSourceEventInit = [] +XrInputSourcesChangeEvent = ["Event"] +XrInputSourcesChangeEventInit = [] +XrPose = [] +XrReferenceSpace = ["EventTarget", "XrSpace"] +XrReferenceSpaceEvent = ["Event"] +XrReferenceSpaceEventInit = [] +XrReferenceSpaceType = [] +XrRenderState = [] +XrRenderStateInit = [] +XrRigidTransform = [] +XrSession = ["EventTarget"] +XrSessionEvent = ["Event"] +XrSessionEventInit = [] +XrSessionInit = [] +XrSessionMode = [] +XrSpace = ["EventTarget"] +XrTargetRayMode = [] +XrView = [] +XrViewerPose = ["XrPose"] +XrViewport = [] +XrVisibilityState = [] +XrWebGlLayer = [] +XrWebGlLayerInit = [] +XsltProcessor = [] +console = [] +css = [] diff --git a/build/rust/dummy-web/web-sys/lib.rs b/build/rust/dummy-web/web-sys/lib.rs new file mode 100644 index 0000000000..e0032240a4 --- /dev/null +++ b/build/rust/dummy-web/web-sys/lib.rs @@ -0,0 +1,3 @@ +/* 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/. */ diff --git a/build/rust/goblin/Cargo.toml b/build/rust/goblin/Cargo.toml new file mode 100644 index 0000000000..52e8dfe66d --- /dev/null +++ b/build/rust/goblin/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "goblin" +version = "0.6.999" +edition = "2018" +license = "MIT/Apache-2.0" + +[lib] +path = "lib.rs" + +[dependencies.goblin] +version = "0.7.0" diff --git a/build/rust/goblin/lib.rs b/build/rust/goblin/lib.rs new file mode 100644 index 0000000000..ba9ee61592 --- /dev/null +++ b/build/rust/goblin/lib.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use goblin::*; diff --git a/build/rust/indexmap/Cargo.toml b/build/rust/indexmap/Cargo.toml new file mode 100644 index 0000000000..de45a4f02d --- /dev/null +++ b/build/rust/indexmap/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "indexmap" +version = "2.999.999" +edition = "2021" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +serde = ["indexmap/serde-1"] +std = ["indexmap/std"] + +[dependencies.indexmap] +version = "1.9.3" diff --git a/build/rust/indexmap/lib.rs b/build/rust/indexmap/lib.rs new file mode 100644 index 0000000000..8142a8bd1d --- /dev/null +++ b/build/rust/indexmap/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use indexmap::*; diff --git a/build/rust/memmap2-0.5/Cargo.toml b/build/rust/memmap2-0.5/Cargo.toml new file mode 100644 index 0000000000..331e3a955e --- /dev/null +++ b/build/rust/memmap2-0.5/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "memmap2" +version = "0.5.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.memmap2] +version = "0.8.0" diff --git a/build/rust/memmap2-0.5/lib.rs b/build/rust/memmap2-0.5/lib.rs new file mode 100644 index 0000000000..214110099a --- /dev/null +++ b/build/rust/memmap2-0.5/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use memmap2::*; diff --git a/build/rust/memmap2/Cargo.toml b/build/rust/memmap2/Cargo.toml new file mode 100644 index 0000000000..eb9ed01134 --- /dev/null +++ b/build/rust/memmap2/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "memmap2" +version = "0.8.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.memmap2] +version = "0.9" diff --git a/build/rust/memmap2/lib.rs b/build/rust/memmap2/lib.rs new file mode 100644 index 0000000000..214110099a --- /dev/null +++ b/build/rust/memmap2/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use memmap2::*; diff --git a/build/rust/memoffset/Cargo.toml b/build/rust/memoffset/Cargo.toml new file mode 100644 index 0000000000..24eb01a58b --- /dev/null +++ b/build/rust/memoffset/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "memoffset" +version = "0.8.999" +edition = "2018" +license = "MIT/Apache-2.0" + +[lib] +path = "lib.rs" + +[dependencies.memoffset] +version = "0.9" diff --git a/build/rust/memoffset/lib.rs b/build/rust/memoffset/lib.rs new file mode 100644 index 0000000000..5bc4a399a7 --- /dev/null +++ b/build/rust/memoffset/lib.rs @@ -0,0 +1,11 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use memoffset::*; diff --git a/build/rust/mozbuild/Cargo.toml b/build/rust/mozbuild/Cargo.toml new file mode 100644 index 0000000000..ef9b4c6ccf --- /dev/null +++ b/build/rust/mozbuild/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "mozbuild" +version = "0.1.0" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/mozbuild/build.rs b/build/rust/mozbuild/build.rs new file mode 100644 index 0000000000..e9fb6b91b0 --- /dev/null +++ b/build/rust/mozbuild/build.rs @@ -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/. */ + +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); + if let Some(topobjdir) = out_dir + .ancestors() + .find(|dir| dir.join("config.status").exists()) + { + println!( + "cargo:rustc-env=BUILDCONFIG_RS={}", + topobjdir + .join("build/rust/mozbuild/buildconfig.rs") + .display() + ); + } +} diff --git a/build/rust/mozbuild/generate_buildconfig.py b/build/rust/mozbuild/generate_buildconfig.py new file mode 100644 index 0000000000..2252276319 --- /dev/null +++ b/build/rust/mozbuild/generate_buildconfig.py @@ -0,0 +1,95 @@ +# 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/. + +import string +import textwrap + +import buildconfig + + +def generate_bool(name): + value = buildconfig.substs.get(name) + return f"pub const {name}: bool = {'true' if value else 'false'};\n" + + +def escape_rust_string(value): + """escape the string into a Rust literal""" + # This could be more generous, but we're only escaping paths with it. + unescaped = string.ascii_letters + string.digits + "/$+-_~ " + result = "" + for ch in str(value): + if ch in unescaped: + result += ch + elif ch == "\r": + result += "\\r" + elif ch == "\n": + result += "\\n" + elif ch == "\\": + result += "\\\\" + elif ch == '"': + result += '\\"' + else: + result += "\\u{%x}" % ord(ch) + return '"%s"' % result + + +def generate(output): + # Write out a macro which can be used within `include!`-like methods to + # reference the topobjdir. + output.write( + textwrap.dedent( + f""" + /// Macro used to name a path in the objdir for use with macros like `include!` + #[macro_export] + macro_rules! objdir_path {{ + ($path:literal) => {{ + concat!({escape_rust_string(buildconfig.topobjdir + "/")}, $path) + }} + }} + + /// Macro used to name a path in the srcdir for use with macros like `include!` + #[macro_export] + macro_rules! srcdir_path {{ + ($path:literal) => {{ + concat!({escape_rust_string(buildconfig.topsrcdir + "/")}, $path) + }} + }} + + /// The objdir path for use in build scripts + pub const TOPOBJDIR: &str = {escape_rust_string(buildconfig.topobjdir)}; + /// The srcdir path for use in build scripts + pub const TOPSRCDIR: &str = {escape_rust_string(buildconfig.topsrcdir)}; + + """ + ) + ) + + windows_rs_dir = buildconfig.substs.get("MOZ_WINDOWS_RS_DIR") + if windows_rs_dir: + output.write( + textwrap.dedent( + f""" + /// Macro used to name a path in the srcdir for use with macros like `include!` + #[macro_export] + macro_rules! windows_rs_path {{ + ($path:literal) => {{ + concat!({escape_rust_string(windows_rs_dir + "/")}, $path) + }} + }} + + /// The path to the windows-rs crate, for use in build scripts + pub const WINDOWS_RS_DIR: &str = {escape_rust_string(windows_rs_dir)}; + + """ + ) + ) + + # Finally, write out some useful booleans from the buildconfig. + output.write(generate_bool("MOZ_FOLD_LIBS")) + output.write(generate_bool("NIGHTLY_BUILD")) + output.write(generate_bool("RELEASE_OR_BETA")) + output.write(generate_bool("EARLY_BETA_OR_EARLIER")) + output.write(generate_bool("MOZ_DEV_EDITION")) + output.write(generate_bool("MOZ_ESR")) + output.write(generate_bool("MOZ_DIAGNOSTIC_ASSERT_ENABLED")) diff --git a/build/rust/mozbuild/lib.rs b/build/rust/mozbuild/lib.rs new file mode 100644 index 0000000000..a22b1d9176 --- /dev/null +++ b/build/rust/mozbuild/lib.rs @@ -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/. */ + +use std::path::Path; + +// Path::new is not const at the moment. This is a non-generic version +// of Path::new, similar to libstd's implementation of Path::new. +#[inline(always)] +const fn const_path(s: &'static str) -> &'static std::path::Path { + unsafe { &*(s as *const str as *const std::path::Path) } +} + +pub const TOPOBJDIR: &Path = const_path(config::TOPOBJDIR); + +pub const TOPSRCDIR: &Path = const_path(config::TOPSRCDIR); + +pub mod config { + include!(env!("BUILDCONFIG_RS")); +} diff --git a/build/rust/mozbuild/moz.build b/build/rust/mozbuild/moz.build new file mode 100644 index 0000000000..3cc09a7c5a --- /dev/null +++ b/build/rust/mozbuild/moz.build @@ -0,0 +1,9 @@ +# -*- 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/. + +GeneratedFile( + "buildconfig.rs", script="generate_buildconfig.py", entry_point="generate" +) diff --git a/build/rust/nix/Cargo.toml b/build/rust/nix/Cargo.toml new file mode 100644 index 0000000000..4ecba71164 --- /dev/null +++ b/build/rust/nix/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "nix" +version = "0.26.99" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.nix] +version = "0.27" +default-features = false + +[features] +acct = ["nix/acct"] +aio = ["nix/aio"] +default = ["nix/default"] +dir = ["nix/dir"] +env = ["nix/env"] +event = ["nix/event"] +feature = ["nix/feature"] +fs = ["nix/fs"] +hostname = ["nix/hostname"] +inotify = ["nix/inotify"] +ioctl = ["nix/ioctl"] +kmod = ["nix/kmod"] +mman = ["nix/mman"] +mount = ["nix/mount"] +mqueue = ["nix/mqueue"] +net = ["nix/net"] diff --git a/build/rust/nix/lib.rs b/build/rust/nix/lib.rs new file mode 100644 index 0000000000..d1039ae71a --- /dev/null +++ b/build/rust/nix/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use nix::*; diff --git a/build/rust/oslog/Cargo.toml b/build/rust/oslog/Cargo.toml new file mode 100644 index 0000000000..fa647f9646 --- /dev/null +++ b/build/rust/oslog/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "oslog" +version = "0.1.999" +edition = "2018" +license = "MIT" + +[lib] +path = "lib.rs" + +[dependencies.log] +version = "0.4" +default-features = false + +[features] +logger = [] diff --git a/build/rust/oslog/LICENSE b/build/rust/oslog/LICENSE new file mode 100644 index 0000000000..13b609c25b --- /dev/null +++ b/build/rust/oslog/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Steven Joruk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/build/rust/oslog/lib.rs b/build/rust/oslog/lib.rs new file mode 100644 index 0000000000..4a529e7afa --- /dev/null +++ b/build/rust/oslog/lib.rs @@ -0,0 +1,25 @@ +/* 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/. */ + +pub struct OsLogger; + +use log::{LevelFilter, SetLoggerError}; + +impl OsLogger { + pub fn new(_subsystem: &str) -> Self { + Self + } + + pub fn level_filter(self, _level: LevelFilter) -> Self { + self + } + + pub fn category_level_filter(self, _category: &str, _level: LevelFilter) -> Self { + self + } + + pub fn init(self) -> Result<(), SetLoggerError> { + Ok(()) + } +} diff --git a/build/rust/redox_syscall/Cargo.toml b/build/rust/redox_syscall/Cargo.toml new file mode 100644 index 0000000000..41ba6ba33d --- /dev/null +++ b/build/rust/redox_syscall/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "redox_syscall" +version = "0.4.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/redox_syscall/lib.rs b/build/rust/redox_syscall/lib.rs new file mode 100644 index 0000000000..e0032240a4 --- /dev/null +++ b/build/rust/redox_syscall/lib.rs @@ -0,0 +1,3 @@ +/* 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/. */ diff --git a/build/rust/redox_users/Cargo.toml b/build/rust/redox_users/Cargo.toml new file mode 100644 index 0000000000..9ea9b4a086 --- /dev/null +++ b/build/rust/redox_users/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "redox_users" +version = "0.4.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/redox_users/lib.rs b/build/rust/redox_users/lib.rs new file mode 100644 index 0000000000..e0032240a4 --- /dev/null +++ b/build/rust/redox_users/lib.rs @@ -0,0 +1,3 @@ +/* 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/. */ diff --git a/build/rust/terminal_size/Cargo.toml b/build/rust/terminal_size/Cargo.toml new file mode 100644 index 0000000000..f787ebdd15 --- /dev/null +++ b/build/rust/terminal_size/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "terminal_size" +version = "0.3.999" +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/terminal_size/lib.rs b/build/rust/terminal_size/lib.rs new file mode 100644 index 0000000000..e2e6512604 --- /dev/null +++ b/build/rust/terminal_size/lib.rs @@ -0,0 +1,26 @@ +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Width(pub u16); +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Height(pub u16); + +pub fn terminal_size() -> Option<(Width, Height)> { + Some((Width(80), Height(25))) +} + +#[cfg(unix)] +pub fn terminal_size_using_fd(_fd: std::os::unix::io::RawFd) -> Option<(Width, Height)> { + Some((Width(80), Height(25))) +} + +#[cfg(windows)] +pub fn terminal_size_using_handle( + _handle: std::os::windows::io::RawHandle, +) -> Option<(Width, Height)> { + Some((Width(80), Height(25))) +} diff --git a/build/rust/tinyvec/Cargo.toml b/build/rust/tinyvec/Cargo.toml new file mode 100644 index 0000000000..d40a4db514 --- /dev/null +++ b/build/rust/tinyvec/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "tinyvec" +version = "1.999.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies] +smallvec = "1" + +[features] +alloc = [] +default = [] +std = ["alloc"] diff --git a/build/rust/tinyvec/lib.rs b/build/rust/tinyvec/lib.rs new file mode 100644 index 0000000000..decdb0efdc --- /dev/null +++ b/build/rust/tinyvec/lib.rs @@ -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/. */ + +pub use smallvec::SmallVec as ArrayVec; +pub use smallvec::SmallVec as TinyVec; diff --git a/build/rust/vcpkg/Cargo.toml b/build/rust/vcpkg/Cargo.toml new file mode 100644 index 0000000000..2128be7ad8 --- /dev/null +++ b/build/rust/vcpkg/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "vcpkg" +version = "0.2.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" diff --git a/build/rust/vcpkg/lib.rs b/build/rust/vcpkg/lib.rs new file mode 100644 index 0000000000..630f19f4be --- /dev/null +++ b/build/rust/vcpkg/lib.rs @@ -0,0 +1,23 @@ +/* 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 std::path::PathBuf; + +pub struct Config; + +pub struct Library { + pub include_paths: Vec<PathBuf>, +} + +pub struct Error; + +impl Config { + pub fn new() -> Config { + Config + } + + pub fn probe(&mut self, _: &str) -> Result<Library, Error> { + Err(Error) + } +} diff --git a/build/rust/wasi/Cargo.toml b/build/rust/wasi/Cargo.toml new file mode 100644 index 0000000000..e1f392a961 --- /dev/null +++ b/build/rust/wasi/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.wasi] +version = "0.11" +default-features = false + +[features] +default = ["wasi/default"] +rustc-dep-of-std = ["wasi/rustc-dep-of-std"] +std = ["wasi/std"] diff --git a/build/rust/wasi/lib.rs b/build/rust/wasi/lib.rs new file mode 100644 index 0000000000..1bb1206202 --- /dev/null +++ b/build/rust/wasi/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use wasi::*; diff --git a/build/rust/windows-sys/Cargo.toml b/build/rust/windows-sys/Cargo.toml new file mode 100644 index 0000000000..b668eb5f7f --- /dev/null +++ b/build/rust/windows-sys/Cargo.toml @@ -0,0 +1,232 @@ +[package] +name = "windows-sys" +version = "0.48.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.windows-sys] +version = "0.52" +default-features = false + +[features] +Wdk = ["windows-sys/Wdk"] +Wdk_System = ["windows-sys/Wdk_System"] +Wdk_System_OfflineRegistry = ["windows-sys/Wdk_System_OfflineRegistry"] +Win32 = ["windows-sys/Win32"] +Win32_Data = ["windows-sys/Win32_Data"] +Win32_Data_HtmlHelp = ["windows-sys/Win32_Data_HtmlHelp"] +Win32_Data_RightsManagement = ["windows-sys/Win32_Data_RightsManagement"] +Win32_Devices = ["windows-sys/Win32_Devices"] +Win32_Devices_AllJoyn = ["windows-sys/Win32_Devices_AllJoyn"] +Win32_Devices_BiometricFramework = ["windows-sys/Win32_Devices_BiometricFramework"] +Win32_Devices_Bluetooth = ["windows-sys/Win32_Devices_Bluetooth"] +Win32_Devices_Communication = ["windows-sys/Win32_Devices_Communication"] +Win32_Devices_DeviceAndDriverInstallation = ["windows-sys/Win32_Devices_DeviceAndDriverInstallation"] +Win32_Devices_DeviceQuery = ["windows-sys/Win32_Devices_DeviceQuery"] +Win32_Devices_Display = ["windows-sys/Win32_Devices_Display"] +Win32_Devices_Enumeration = ["windows-sys/Win32_Devices_Enumeration"] +Win32_Devices_Enumeration_Pnp = ["windows-sys/Win32_Devices_Enumeration_Pnp"] +Win32_Devices_Fax = ["windows-sys/Win32_Devices_Fax"] +Win32_Devices_HumanInterfaceDevice = ["windows-sys/Win32_Devices_HumanInterfaceDevice"] +Win32_Devices_PortableDevices = ["windows-sys/Win32_Devices_PortableDevices"] +Win32_Devices_Properties = ["windows-sys/Win32_Devices_Properties"] +Win32_Devices_Pwm = ["windows-sys/Win32_Devices_Pwm"] +Win32_Devices_Sensors = ["windows-sys/Win32_Devices_Sensors"] +Win32_Devices_SerialCommunication = ["windows-sys/Win32_Devices_SerialCommunication"] +Win32_Devices_Tapi = ["windows-sys/Win32_Devices_Tapi"] +Win32_Devices_Usb = ["windows-sys/Win32_Devices_Usb"] +Win32_Devices_WebServicesOnDevices = ["windows-sys/Win32_Devices_WebServicesOnDevices"] +Win32_Foundation = ["windows-sys/Win32_Foundation"] +Win32_Gaming = ["windows-sys/Win32_Gaming"] +Win32_Globalization = ["windows-sys/Win32_Globalization"] +Win32_Graphics = ["windows-sys/Win32_Graphics"] +Win32_Graphics_Dwm = ["windows-sys/Win32_Graphics_Dwm"] +Win32_Graphics_Gdi = ["windows-sys/Win32_Graphics_Gdi"] +Win32_Graphics_Hlsl = ["windows-sys/Win32_Graphics_Hlsl"] +Win32_Graphics_OpenGL = ["windows-sys/Win32_Graphics_OpenGL"] +Win32_Graphics_Printing = ["windows-sys/Win32_Graphics_Printing"] +Win32_Graphics_Printing_PrintTicket = ["windows-sys/Win32_Graphics_Printing_PrintTicket"] +Win32_Management = ["windows-sys/Win32_Management"] +Win32_Management_MobileDeviceManagementRegistration = ["windows-sys/Win32_Management_MobileDeviceManagementRegistration"] +Win32_Media = ["windows-sys/Win32_Media"] +Win32_Media_Audio = ["windows-sys/Win32_Media_Audio"] +Win32_Media_DxMediaObjects = ["windows-sys/Win32_Media_DxMediaObjects"] +Win32_Media_KernelStreaming = ["windows-sys/Win32_Media_KernelStreaming"] +Win32_Media_Multimedia = ["windows-sys/Win32_Media_Multimedia"] +Win32_Media_Streaming = ["windows-sys/Win32_Media_Streaming"] +Win32_Media_WindowsMediaFormat = ["windows-sys/Win32_Media_WindowsMediaFormat"] +Win32_NetworkManagement = ["windows-sys/Win32_NetworkManagement"] +Win32_NetworkManagement_Dhcp = ["windows-sys/Win32_NetworkManagement_Dhcp"] +Win32_NetworkManagement_Dns = ["windows-sys/Win32_NetworkManagement_Dns"] +Win32_NetworkManagement_InternetConnectionWizard = ["windows-sys/Win32_NetworkManagement_InternetConnectionWizard"] +Win32_NetworkManagement_IpHelper = ["windows-sys/Win32_NetworkManagement_IpHelper"] +Win32_NetworkManagement_Multicast = ["windows-sys/Win32_NetworkManagement_Multicast"] +Win32_NetworkManagement_Ndis = ["windows-sys/Win32_NetworkManagement_Ndis"] +Win32_NetworkManagement_NetBios = ["windows-sys/Win32_NetworkManagement_NetBios"] +Win32_NetworkManagement_NetManagement = ["windows-sys/Win32_NetworkManagement_NetManagement"] +Win32_NetworkManagement_NetShell = ["windows-sys/Win32_NetworkManagement_NetShell"] +Win32_NetworkManagement_NetworkDiagnosticsFramework = ["windows-sys/Win32_NetworkManagement_NetworkDiagnosticsFramework"] +Win32_NetworkManagement_P2P = ["windows-sys/Win32_NetworkManagement_P2P"] +Win32_NetworkManagement_QoS = ["windows-sys/Win32_NetworkManagement_QoS"] +Win32_NetworkManagement_Rras = ["windows-sys/Win32_NetworkManagement_Rras"] +Win32_NetworkManagement_Snmp = ["windows-sys/Win32_NetworkManagement_Snmp"] +Win32_NetworkManagement_WNet = ["windows-sys/Win32_NetworkManagement_WNet"] +Win32_NetworkManagement_WebDav = ["windows-sys/Win32_NetworkManagement_WebDav"] +Win32_NetworkManagement_WiFi = ["windows-sys/Win32_NetworkManagement_WiFi"] +Win32_NetworkManagement_WindowsConnectionManager = ["windows-sys/Win32_NetworkManagement_WindowsConnectionManager"] +Win32_NetworkManagement_WindowsFilteringPlatform = ["windows-sys/Win32_NetworkManagement_WindowsFilteringPlatform"] +Win32_NetworkManagement_WindowsFirewall = ["windows-sys/Win32_NetworkManagement_WindowsFirewall"] +Win32_NetworkManagement_WindowsNetworkVirtualization = ["windows-sys/Win32_NetworkManagement_WindowsNetworkVirtualization"] +Win32_Networking = ["windows-sys/Win32_Networking"] +Win32_Networking_ActiveDirectory = ["windows-sys/Win32_Networking_ActiveDirectory"] +Win32_Networking_Clustering = ["windows-sys/Win32_Networking_Clustering"] +Win32_Networking_HttpServer = ["windows-sys/Win32_Networking_HttpServer"] +Win32_Networking_Ldap = ["windows-sys/Win32_Networking_Ldap"] +Win32_Networking_WebSocket = ["windows-sys/Win32_Networking_WebSocket"] +Win32_Networking_WinHttp = ["windows-sys/Win32_Networking_WinHttp"] +Win32_Networking_WinInet = ["windows-sys/Win32_Networking_WinInet"] +Win32_Networking_WinSock = ["windows-sys/Win32_Networking_WinSock"] +Win32_Networking_WindowsWebServices = ["windows-sys/Win32_Networking_WindowsWebServices"] +Win32_Security = ["windows-sys/Win32_Security"] +Win32_Security_AppLocker = ["windows-sys/Win32_Security_AppLocker"] +Win32_Security_Authentication = ["windows-sys/Win32_Security_Authentication"] +Win32_Security_Authentication_Identity = ["windows-sys/Win32_Security_Authentication_Identity"] +Win32_Security_Authorization = ["windows-sys/Win32_Security_Authorization"] +Win32_Security_Credentials = ["windows-sys/Win32_Security_Credentials"] +Win32_Security_Cryptography = ["windows-sys/Win32_Security_Cryptography"] +Win32_Security_Cryptography_Catalog = ["windows-sys/Win32_Security_Cryptography_Catalog"] +Win32_Security_Cryptography_Certificates = ["windows-sys/Win32_Security_Cryptography_Certificates"] +Win32_Security_Cryptography_Sip = ["windows-sys/Win32_Security_Cryptography_Sip"] +Win32_Security_Cryptography_UI = ["windows-sys/Win32_Security_Cryptography_UI"] +Win32_Security_DiagnosticDataQuery = ["windows-sys/Win32_Security_DiagnosticDataQuery"] +Win32_Security_DirectoryServices = ["windows-sys/Win32_Security_DirectoryServices"] +Win32_Security_EnterpriseData = ["windows-sys/Win32_Security_EnterpriseData"] +Win32_Security_ExtensibleAuthenticationProtocol = ["windows-sys/Win32_Security_ExtensibleAuthenticationProtocol"] +Win32_Security_Isolation = ["windows-sys/Win32_Security_Isolation"] +Win32_Security_LicenseProtection = ["windows-sys/Win32_Security_LicenseProtection"] +Win32_Security_NetworkAccessProtection = ["windows-sys/Win32_Security_NetworkAccessProtection"] +Win32_Security_WinTrust = ["windows-sys/Win32_Security_WinTrust"] +Win32_Security_WinWlx = ["windows-sys/Win32_Security_WinWlx"] +Win32_Storage = ["windows-sys/Win32_Storage"] +Win32_Storage_Cabinets = ["windows-sys/Win32_Storage_Cabinets"] +Win32_Storage_CloudFilters = ["windows-sys/Win32_Storage_CloudFilters"] +Win32_Storage_Compression = ["windows-sys/Win32_Storage_Compression"] +Win32_Storage_DistributedFileSystem = ["windows-sys/Win32_Storage_DistributedFileSystem"] +Win32_Storage_FileHistory = ["windows-sys/Win32_Storage_FileHistory"] +Win32_Storage_FileSystem = ["windows-sys/Win32_Storage_FileSystem"] +Win32_Storage_Imapi = ["windows-sys/Win32_Storage_Imapi"] +Win32_Storage_IndexServer = ["windows-sys/Win32_Storage_IndexServer"] +Win32_Storage_InstallableFileSystems = ["windows-sys/Win32_Storage_InstallableFileSystems"] +Win32_Storage_IscsiDisc = ["windows-sys/Win32_Storage_IscsiDisc"] +Win32_Storage_Jet = ["windows-sys/Win32_Storage_Jet"] +Win32_Storage_OfflineFiles = ["windows-sys/Win32_Storage_OfflineFiles"] +Win32_Storage_OperationRecorder = ["windows-sys/Win32_Storage_OperationRecorder"] +Win32_Storage_Packaging = ["windows-sys/Win32_Storage_Packaging"] +Win32_Storage_Packaging_Appx = ["windows-sys/Win32_Storage_Packaging_Appx"] +Win32_Storage_ProjectedFileSystem = ["windows-sys/Win32_Storage_ProjectedFileSystem"] +Win32_Storage_StructuredStorage = ["windows-sys/Win32_Storage_StructuredStorage"] +Win32_Storage_Vhd = ["windows-sys/Win32_Storage_Vhd"] +Win32_Storage_Xps = ["windows-sys/Win32_Storage_Xps"] +Win32_System = ["windows-sys/Win32_System"] +Win32_System_AddressBook = ["windows-sys/Win32_System_AddressBook"] +Win32_System_Antimalware = ["windows-sys/Win32_System_Antimalware"] +Win32_System_ApplicationInstallationAndServicing = ["windows-sys/Win32_System_ApplicationInstallationAndServicing"] +Win32_System_ApplicationVerifier = ["windows-sys/Win32_System_ApplicationVerifier"] +Win32_System_ClrHosting = ["windows-sys/Win32_System_ClrHosting"] +Win32_System_Com = ["windows-sys/Win32_System_Com"] +Win32_System_Com_Marshal = ["windows-sys/Win32_System_Com_Marshal"] +Win32_System_Com_StructuredStorage = ["windows-sys/Win32_System_Com_StructuredStorage"] +Win32_System_Com_Urlmon = ["windows-sys/Win32_System_Com_Urlmon"] +Win32_System_ComponentServices = ["windows-sys/Win32_System_ComponentServices"] +Win32_System_Console = ["windows-sys/Win32_System_Console"] +Win32_System_CorrelationVector = ["windows-sys/Win32_System_CorrelationVector"] +Win32_System_DataExchange = ["windows-sys/Win32_System_DataExchange"] +Win32_System_DeploymentServices = ["windows-sys/Win32_System_DeploymentServices"] +Win32_System_DeveloperLicensing = ["windows-sys/Win32_System_DeveloperLicensing"] +Win32_System_Diagnostics = ["windows-sys/Win32_System_Diagnostics"] +Win32_System_Diagnostics_Ceip = ["windows-sys/Win32_System_Diagnostics_Ceip"] +Win32_System_Diagnostics_Debug = ["windows-sys/Win32_System_Diagnostics_Debug"] +Win32_System_Diagnostics_Debug_Extensions = ["windows-sys/Win32_System_Diagnostics_Debug_Extensions"] +Win32_System_Diagnostics_Etw = ["windows-sys/Win32_System_Diagnostics_Etw"] +Win32_System_Diagnostics_ProcessSnapshotting = ["windows-sys/Win32_System_Diagnostics_ProcessSnapshotting"] +Win32_System_Diagnostics_ToolHelp = ["windows-sys/Win32_System_Diagnostics_ToolHelp"] +Win32_System_DistributedTransactionCoordinator = ["windows-sys/Win32_System_DistributedTransactionCoordinator"] +Win32_System_Environment = ["windows-sys/Win32_System_Environment"] +Win32_System_ErrorReporting = ["windows-sys/Win32_System_ErrorReporting"] +Win32_System_EventCollector = ["windows-sys/Win32_System_EventCollector"] +Win32_System_EventLog = ["windows-sys/Win32_System_EventLog"] +Win32_System_EventNotificationService = ["windows-sys/Win32_System_EventNotificationService"] +Win32_System_GroupPolicy = ["windows-sys/Win32_System_GroupPolicy"] +Win32_System_HostCompute = ["windows-sys/Win32_System_HostCompute"] +Win32_System_HostComputeNetwork = ["windows-sys/Win32_System_HostComputeNetwork"] +Win32_System_HostComputeSystem = ["windows-sys/Win32_System_HostComputeSystem"] +Win32_System_Hypervisor = ["windows-sys/Win32_System_Hypervisor"] +Win32_System_IO = ["windows-sys/Win32_System_IO"] +Win32_System_Iis = ["windows-sys/Win32_System_Iis"] +Win32_System_Ioctl = ["windows-sys/Win32_System_Ioctl"] +Win32_System_JobObjects = ["windows-sys/Win32_System_JobObjects"] +Win32_System_Js = ["windows-sys/Win32_System_Js"] +Win32_System_Kernel = ["windows-sys/Win32_System_Kernel"] +Win32_System_LibraryLoader = ["windows-sys/Win32_System_LibraryLoader"] +Win32_System_Mailslots = ["windows-sys/Win32_System_Mailslots"] +Win32_System_Mapi = ["windows-sys/Win32_System_Mapi"] +Win32_System_Memory = ["windows-sys/Win32_System_Memory"] +Win32_System_Memory_NonVolatile = ["windows-sys/Win32_System_Memory_NonVolatile"] +Win32_System_MessageQueuing = ["windows-sys/Win32_System_MessageQueuing"] +Win32_System_MixedReality = ["windows-sys/Win32_System_MixedReality"] +Win32_System_Ole = ["windows-sys/Win32_System_Ole"] +Win32_System_PasswordManagement = ["windows-sys/Win32_System_PasswordManagement"] +Win32_System_Performance = ["windows-sys/Win32_System_Performance"] +Win32_System_Performance_HardwareCounterProfiling = ["windows-sys/Win32_System_Performance_HardwareCounterProfiling"] +Win32_System_Pipes = ["windows-sys/Win32_System_Pipes"] +Win32_System_Power = ["windows-sys/Win32_System_Power"] +Win32_System_ProcessStatus = ["windows-sys/Win32_System_ProcessStatus"] +Win32_System_Recovery = ["windows-sys/Win32_System_Recovery"] +Win32_System_Registry = ["windows-sys/Win32_System_Registry"] +Win32_System_RemoteDesktop = ["windows-sys/Win32_System_RemoteDesktop"] +Win32_System_RemoteManagement = ["windows-sys/Win32_System_RemoteManagement"] +Win32_System_RestartManager = ["windows-sys/Win32_System_RestartManager"] +Win32_System_Restore = ["windows-sys/Win32_System_Restore"] +Win32_System_Rpc = ["windows-sys/Win32_System_Rpc"] +Win32_System_Search = ["windows-sys/Win32_System_Search"] +Win32_System_Search_Common = ["windows-sys/Win32_System_Search_Common"] +Win32_System_SecurityCenter = ["windows-sys/Win32_System_SecurityCenter"] +Win32_System_Services = ["windows-sys/Win32_System_Services"] +Win32_System_SetupAndMigration = ["windows-sys/Win32_System_SetupAndMigration"] +Win32_System_Shutdown = ["windows-sys/Win32_System_Shutdown"] +Win32_System_StationsAndDesktops = ["windows-sys/Win32_System_StationsAndDesktops"] +Win32_System_SubsystemForLinux = ["windows-sys/Win32_System_SubsystemForLinux"] +Win32_System_SystemInformation = ["windows-sys/Win32_System_SystemInformation"] +Win32_System_SystemServices = ["windows-sys/Win32_System_SystemServices"] +Win32_System_Threading = ["windows-sys/Win32_System_Threading"] +Win32_System_Time = ["windows-sys/Win32_System_Time"] +Win32_System_TpmBaseServices = ["windows-sys/Win32_System_TpmBaseServices"] +Win32_System_UserAccessLogging = ["windows-sys/Win32_System_UserAccessLogging"] +Win32_System_VirtualDosMachines = ["windows-sys/Win32_System_VirtualDosMachines"] +Win32_System_WindowsProgramming = ["windows-sys/Win32_System_WindowsProgramming"] +Win32_System_Wmi = ["windows-sys/Win32_System_Wmi"] +Win32_UI = ["windows-sys/Win32_UI"] +Win32_UI_Accessibility = ["windows-sys/Win32_UI_Accessibility"] +Win32_UI_ColorSystem = ["windows-sys/Win32_UI_ColorSystem"] +Win32_UI_Controls = ["windows-sys/Win32_UI_Controls"] +Win32_UI_Controls_Dialogs = ["windows-sys/Win32_UI_Controls_Dialogs"] +Win32_UI_HiDpi = ["windows-sys/Win32_UI_HiDpi"] +Win32_UI_Input = ["windows-sys/Win32_UI_Input"] +Win32_UI_Input_Ime = ["windows-sys/Win32_UI_Input_Ime"] +Win32_UI_Input_KeyboardAndMouse = ["windows-sys/Win32_UI_Input_KeyboardAndMouse"] +Win32_UI_Input_Pointer = ["windows-sys/Win32_UI_Input_Pointer"] +Win32_UI_Input_Touch = ["windows-sys/Win32_UI_Input_Touch"] +Win32_UI_Input_XboxController = ["windows-sys/Win32_UI_Input_XboxController"] +Win32_UI_InteractionContext = ["windows-sys/Win32_UI_InteractionContext"] +Win32_UI_Magnification = ["windows-sys/Win32_UI_Magnification"] +Win32_UI_Shell = ["windows-sys/Win32_UI_Shell"] +Win32_UI_Shell_PropertiesSystem = ["windows-sys/Win32_UI_Shell_PropertiesSystem"] +Win32_UI_TabletPC = ["windows-sys/Win32_UI_TabletPC"] +Win32_UI_TextServices = ["windows-sys/Win32_UI_TextServices"] +Win32_UI_WindowsAndMessaging = ["windows-sys/Win32_UI_WindowsAndMessaging"] +Win32_Web = ["windows-sys/Win32_Web"] +Win32_Web_InternetExplorer = ["windows-sys/Win32_Web_InternetExplorer"] +default = ["windows-sys/default"] diff --git a/build/rust/windows-sys/lib.rs b/build/rust/windows-sys/lib.rs new file mode 100644 index 0000000000..15c89411fe --- /dev/null +++ b/build/rust/windows-sys/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use windows_sys::*; diff --git a/build/rust/windows-targets-0.48/Cargo.toml b/build/rust/windows-targets-0.48/Cargo.toml new file mode 100644 index 0000000000..2649448d0a --- /dev/null +++ b/build/rust/windows-targets-0.48/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "windows-targets" +version = "0.48.999" +edition = "2018" +license = "MPL-2.0" + +[lib] +path = "lib.rs" + +[dependencies.windows-targets] +version = "0.52" diff --git a/build/rust/windows-targets-0.48/lib.rs b/build/rust/windows-targets-0.48/lib.rs new file mode 100644 index 0000000000..d3fd808887 --- /dev/null +++ b/build/rust/windows-targets-0.48/lib.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub use windows_targets::*; diff --git a/build/rust/windows-targets/Cargo.toml b/build/rust/windows-targets/Cargo.toml new file mode 100644 index 0000000000..5d3f665d7b --- /dev/null +++ b/build/rust/windows-targets/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "windows-targets" +version = "0.52.999" +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +proc-macro = true +path = "lib.rs" + +[dependencies] +syn = { version = "2", features = ["full"] } +quote = "1" diff --git a/build/rust/windows-targets/lib.rs b/build/rust/windows-targets/lib.rs new file mode 100644 index 0000000000..439bc46946 --- /dev/null +++ b/build/rust/windows-targets/lib.rs @@ -0,0 +1,86 @@ +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use proc_macro::TokenStream; +use quote::quote; +use syn::parse::{Parse, ParseStream, Result}; +use syn::{parse_macro_input, Attribute, LitStr, Signature}; + +/* Proc macro equivalent to the following rust macro: + * ``` + * macro_rules! link { + * ($library:literal $abi:literal $($link_name:literal)? $(#[$($doc:tt)*])* fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( + * extern $abi { + * #[link(name = $library)] + * $(#[link_name=$link_name])? + * pub fn $name($($arg: $argty),*) -> $ret; + * } + * ) + * } + * ``` + * with the additional feature of removing ".dll" from the $library literal. + * + * The macro is derived from the equivalent macro in the real windows-targets crate, + * with the difference that it uses #[link] with the name of the library rather than + * a single "windows.$version" library, so as to avoid having to vendor all the fake + * "windows.$version" import libraries. We can do that because we also require MSVC + * to build, so we do have the real import libraries available. + * + * As the library name is there in the original for raw-dylib support, it contains + * a suffixed name, but plain #[link] expects a non-suffixed name, which is why we + * remove the suffix (and why this had to be a proc-macro). + * + * Once raw-dylib is more widely available and tested, we'll be able to use the + * raw-dylib variants directly. + */ + +struct LinkMacroInput { + library: LitStr, + abi: LitStr, + link_name: Option<LitStr>, + function: Signature, +} + +impl Parse for LinkMacroInput { + fn parse(input: ParseStream) -> Result<Self> { + let library: LitStr = input.parse()?; + let abi: LitStr = input.parse()?; + let link_name: Option<LitStr> = input.parse().ok(); + let _doc_comments = Attribute::parse_outer(input)?; + let function: Signature = input.parse()?; + Ok(LinkMacroInput { + library, + abi, + link_name, + function, + }) + } +} + +#[proc_macro] +pub fn link(input: TokenStream) -> TokenStream { + let LinkMacroInput { + library, + abi, + link_name, + function, + } = parse_macro_input!(input as LinkMacroInput); + + let link_name_attr = link_name.map(|lit| quote! { #[link_name = #lit] }); + + let library = library.value(); + let library = library.strip_suffix(".dll").unwrap_or(&library); + + let generated = quote! { + extern #abi { + #[link(name = #library)] + #link_name_attr + pub #function; + } + }; + + TokenStream::from(generated) +} diff --git a/build/rust/windows/Cargo.toml b/build/rust/windows/Cargo.toml new file mode 100644 index 0000000000..491a053d53 --- /dev/null +++ b/build/rust/windows/Cargo.toml @@ -0,0 +1,736 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.56" +name = "windows" +version = "0.52.0" +authors = ["Microsoft"] +description = "Rust for Windows" +documentation = "https://microsoft.github.io/windows-docs-rs/" +readme = "readme.md" +categories = ["os::windows-apis"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +rustdoc-args = [ + "--cfg", + "docsrs", +] +targets = [] + +[dependencies.windows-core] +version = "0.52.0" + +[dependencies.windows-implement] +version = "0.52.0" +optional = true + +[dependencies.windows-interface] +version = "0.52.0" +optional = true + +[dependencies.windows-targets] +version = "0.52.0" + +[features] +AI = [] +AI_MachineLearning = ["AI"] +ApplicationModel = [] +ApplicationModel_Activation = ["ApplicationModel"] +ApplicationModel_AppExtensions = ["ApplicationModel"] +ApplicationModel_AppService = ["ApplicationModel"] +ApplicationModel_Appointments = ["ApplicationModel"] +ApplicationModel_Appointments_AppointmentsProvider = ["ApplicationModel_Appointments"] +ApplicationModel_Appointments_DataProvider = ["ApplicationModel_Appointments"] +ApplicationModel_Background = ["ApplicationModel"] +ApplicationModel_Calls = ["ApplicationModel"] +ApplicationModel_Calls_Background = ["ApplicationModel_Calls"] +ApplicationModel_Calls_Provider = ["ApplicationModel_Calls"] +ApplicationModel_Chat = ["ApplicationModel"] +ApplicationModel_CommunicationBlocking = ["ApplicationModel"] +ApplicationModel_Contacts = ["ApplicationModel"] +ApplicationModel_Contacts_DataProvider = ["ApplicationModel_Contacts"] +ApplicationModel_Contacts_Provider = ["ApplicationModel_Contacts"] +ApplicationModel_ConversationalAgent = ["ApplicationModel"] +ApplicationModel_Core = ["ApplicationModel"] +ApplicationModel_DataTransfer = ["ApplicationModel"] +ApplicationModel_DataTransfer_DragDrop = ["ApplicationModel_DataTransfer"] +ApplicationModel_DataTransfer_DragDrop_Core = ["ApplicationModel_DataTransfer_DragDrop"] +ApplicationModel_DataTransfer_ShareTarget = ["ApplicationModel_DataTransfer"] +ApplicationModel_Email = ["ApplicationModel"] +ApplicationModel_Email_DataProvider = ["ApplicationModel_Email"] +ApplicationModel_ExtendedExecution = ["ApplicationModel"] +ApplicationModel_ExtendedExecution_Foreground = ["ApplicationModel_ExtendedExecution"] +ApplicationModel_Holographic = ["ApplicationModel"] +ApplicationModel_LockScreen = ["ApplicationModel"] +ApplicationModel_Payments = ["ApplicationModel"] +ApplicationModel_Payments_Provider = ["ApplicationModel_Payments"] +ApplicationModel_Preview = ["ApplicationModel"] +ApplicationModel_Preview_Holographic = ["ApplicationModel_Preview"] +ApplicationModel_Preview_InkWorkspace = ["ApplicationModel_Preview"] +ApplicationModel_Preview_Notes = ["ApplicationModel_Preview"] +ApplicationModel_Resources = ["ApplicationModel"] +ApplicationModel_Resources_Core = ["ApplicationModel_Resources"] +ApplicationModel_Resources_Management = ["ApplicationModel_Resources"] +ApplicationModel_Search = ["ApplicationModel"] +ApplicationModel_Search_Core = ["ApplicationModel_Search"] +ApplicationModel_Store = ["ApplicationModel"] +ApplicationModel_Store_LicenseManagement = ["ApplicationModel_Store"] +ApplicationModel_Store_Preview = ["ApplicationModel_Store"] +ApplicationModel_Store_Preview_InstallControl = ["ApplicationModel_Store_Preview"] +ApplicationModel_UserActivities = ["ApplicationModel"] +ApplicationModel_UserActivities_Core = ["ApplicationModel_UserActivities"] +ApplicationModel_UserDataAccounts = ["ApplicationModel"] +ApplicationModel_UserDataAccounts_Provider = ["ApplicationModel_UserDataAccounts"] +ApplicationModel_UserDataAccounts_SystemAccess = ["ApplicationModel_UserDataAccounts"] +ApplicationModel_UserDataTasks = ["ApplicationModel"] +ApplicationModel_UserDataTasks_DataProvider = ["ApplicationModel_UserDataTasks"] +ApplicationModel_VoiceCommands = ["ApplicationModel"] +ApplicationModel_Wallet = ["ApplicationModel"] +ApplicationModel_Wallet_System = ["ApplicationModel_Wallet"] +Data = [] +Data_Html = ["Data"] +Data_Json = ["Data"] +Data_Pdf = ["Data"] +Data_Text = ["Data"] +Data_Xml = ["Data"] +Data_Xml_Dom = ["Data_Xml"] +Data_Xml_Xsl = ["Data_Xml"] +Devices = [] +Devices_Adc = ["Devices"] +Devices_Adc_Provider = ["Devices_Adc"] +Devices_Background = ["Devices"] +Devices_Bluetooth = ["Devices"] +Devices_Bluetooth_Advertisement = ["Devices_Bluetooth"] +Devices_Bluetooth_Background = ["Devices_Bluetooth"] +Devices_Bluetooth_GenericAttributeProfile = ["Devices_Bluetooth"] +Devices_Bluetooth_Rfcomm = ["Devices_Bluetooth"] +Devices_Custom = ["Devices"] +Devices_Display = ["Devices"] +Devices_Display_Core = ["Devices_Display"] +Devices_Enumeration = ["Devices"] +Devices_Enumeration_Pnp = ["Devices_Enumeration"] +Devices_Geolocation = ["Devices"] +Devices_Geolocation_Geofencing = ["Devices_Geolocation"] +Devices_Geolocation_Provider = ["Devices_Geolocation"] +Devices_Gpio = ["Devices"] +Devices_Gpio_Provider = ["Devices_Gpio"] +Devices_Haptics = ["Devices"] +Devices_HumanInterfaceDevice = ["Devices"] +Devices_I2c = ["Devices"] +Devices_I2c_Provider = ["Devices_I2c"] +Devices_Input = ["Devices"] +Devices_Input_Preview = ["Devices_Input"] +Devices_Lights = ["Devices"] +Devices_Lights_Effects = ["Devices_Lights"] +Devices_Midi = ["Devices"] +Devices_PointOfService = ["Devices"] +Devices_PointOfService_Provider = ["Devices_PointOfService"] +Devices_Portable = ["Devices"] +Devices_Power = ["Devices"] +Devices_Printers = ["Devices"] +Devices_Printers_Extensions = ["Devices_Printers"] +Devices_Pwm = ["Devices"] +Devices_Pwm_Provider = ["Devices_Pwm"] +Devices_Radios = ["Devices"] +Devices_Scanners = ["Devices"] +Devices_Sensors = ["Devices"] +Devices_Sensors_Custom = ["Devices_Sensors"] +Devices_SerialCommunication = ["Devices"] +Devices_SmartCards = ["Devices"] +Devices_Sms = ["Devices"] +Devices_Spi = ["Devices"] +Devices_Spi_Provider = ["Devices_Spi"] +Devices_Usb = ["Devices"] +Devices_WiFi = ["Devices"] +Devices_WiFiDirect = ["Devices"] +Devices_WiFiDirect_Services = ["Devices_WiFiDirect"] +Embedded = [] +Embedded_DeviceLockdown = ["Embedded"] +Foundation = [] +Foundation_Collections = ["Foundation"] +Foundation_Diagnostics = ["Foundation"] +Foundation_Metadata = ["Foundation"] +Foundation_Numerics = ["Foundation"] +Gaming = [] +Gaming_Input = ["Gaming"] +Gaming_Input_Custom = ["Gaming_Input"] +Gaming_Input_ForceFeedback = ["Gaming_Input"] +Gaming_Input_Preview = ["Gaming_Input"] +Gaming_Preview = ["Gaming"] +Gaming_Preview_GamesEnumeration = ["Gaming_Preview"] +Gaming_UI = ["Gaming"] +Gaming_XboxLive = ["Gaming"] +Gaming_XboxLive_Storage = ["Gaming_XboxLive"] +Globalization = [] +Globalization_Collation = ["Globalization"] +Globalization_DateTimeFormatting = ["Globalization"] +Globalization_Fonts = ["Globalization"] +Globalization_NumberFormatting = ["Globalization"] +Globalization_PhoneNumberFormatting = ["Globalization"] +Graphics = [] +Graphics_Capture = ["Graphics"] +Graphics_DirectX = ["Graphics"] +Graphics_DirectX_Direct3D11 = ["Graphics_DirectX"] +Graphics_Display = ["Graphics"] +Graphics_Display_Core = ["Graphics_Display"] +Graphics_Effects = ["Graphics"] +Graphics_Holographic = ["Graphics"] +Graphics_Imaging = ["Graphics"] +Graphics_Printing = ["Graphics"] +Graphics_Printing3D = ["Graphics"] +Graphics_Printing_OptionDetails = ["Graphics_Printing"] +Graphics_Printing_PrintSupport = ["Graphics_Printing"] +Graphics_Printing_PrintTicket = ["Graphics_Printing"] +Graphics_Printing_Workflow = ["Graphics_Printing"] +Management = [] +Management_Core = ["Management"] +Management_Deployment = ["Management"] +Management_Deployment_Preview = ["Management_Deployment"] +Management_Policies = ["Management"] +Management_Update = ["Management"] +Management_Workplace = ["Management"] +Media = [] +Media_AppBroadcasting = ["Media"] +Media_AppRecording = ["Media"] +Media_Audio = ["Media"] +Media_Capture = ["Media"] +Media_Capture_Core = ["Media_Capture"] +Media_Capture_Frames = ["Media_Capture"] +Media_Casting = ["Media"] +Media_ClosedCaptioning = ["Media"] +Media_ContentRestrictions = ["Media"] +Media_Control = ["Media"] +Media_Core = ["Media"] +Media_Core_Preview = ["Media_Core"] +Media_Devices = ["Media"] +Media_Devices_Core = ["Media_Devices"] +Media_DialProtocol = ["Media"] +Media_Editing = ["Media"] +Media_Effects = ["Media"] +Media_FaceAnalysis = ["Media"] +Media_Import = ["Media"] +Media_MediaProperties = ["Media"] +Media_Miracast = ["Media"] +Media_Ocr = ["Media"] +Media_PlayTo = ["Media"] +Media_Playback = ["Media"] +Media_Playlists = ["Media"] +Media_Protection = ["Media"] +Media_Protection_PlayReady = ["Media_Protection"] +Media_Render = ["Media"] +Media_SpeechRecognition = ["Media"] +Media_SpeechSynthesis = ["Media"] +Media_Streaming = ["Media"] +Media_Streaming_Adaptive = ["Media_Streaming"] +Media_Transcoding = ["Media"] +Networking = [] +Networking_BackgroundTransfer = ["Networking"] +Networking_Connectivity = ["Networking"] +Networking_NetworkOperators = ["Networking"] +Networking_Proximity = ["Networking"] +Networking_PushNotifications = ["Networking"] +Networking_ServiceDiscovery = ["Networking"] +Networking_ServiceDiscovery_Dnssd = ["Networking_ServiceDiscovery"] +Networking_Sockets = ["Networking"] +Networking_Vpn = ["Networking"] +Networking_XboxLive = ["Networking"] +Perception = [] +Perception_Automation = ["Perception"] +Perception_Automation_Core = ["Perception_Automation"] +Perception_People = ["Perception"] +Perception_Spatial = ["Perception"] +Perception_Spatial_Preview = ["Perception_Spatial"] +Perception_Spatial_Surfaces = ["Perception_Spatial"] +Phone = [] +Phone_ApplicationModel = ["Phone"] +Phone_Devices = ["Phone"] +Phone_Devices_Notification = ["Phone_Devices"] +Phone_Devices_Power = ["Phone_Devices"] +Phone_Management = ["Phone"] +Phone_Management_Deployment = ["Phone_Management"] +Phone_Media = ["Phone"] +Phone_Media_Devices = ["Phone_Media"] +Phone_Notification = ["Phone"] +Phone_Notification_Management = ["Phone_Notification"] +Phone_PersonalInformation = ["Phone"] +Phone_PersonalInformation_Provisioning = ["Phone_PersonalInformation"] +Phone_Speech = ["Phone"] +Phone_Speech_Recognition = ["Phone_Speech"] +Phone_StartScreen = ["Phone"] +Phone_System = ["Phone"] +Phone_System_Power = ["Phone_System"] +Phone_System_Profile = ["Phone_System"] +Phone_System_UserProfile = ["Phone_System"] +Phone_System_UserProfile_GameServices = ["Phone_System_UserProfile"] +Phone_System_UserProfile_GameServices_Core = ["Phone_System_UserProfile_GameServices"] +Phone_UI = ["Phone"] +Phone_UI_Input = ["Phone_UI"] +Security = [] +Security_Authentication = ["Security"] +Security_Authentication_Identity = ["Security_Authentication"] +Security_Authentication_Identity_Core = ["Security_Authentication_Identity"] +Security_Authentication_OnlineId = ["Security_Authentication"] +Security_Authentication_Web = ["Security_Authentication"] +Security_Authentication_Web_Core = ["Security_Authentication_Web"] +Security_Authentication_Web_Provider = ["Security_Authentication_Web"] +Security_Authorization = ["Security"] +Security_Authorization_AppCapabilityAccess = ["Security_Authorization"] +Security_Credentials = ["Security"] +Security_Credentials_UI = ["Security_Credentials"] +Security_Cryptography = ["Security"] +Security_Cryptography_Certificates = ["Security_Cryptography"] +Security_Cryptography_Core = ["Security_Cryptography"] +Security_Cryptography_DataProtection = ["Security_Cryptography"] +Security_DataProtection = ["Security"] +Security_EnterpriseData = ["Security"] +Security_ExchangeActiveSyncProvisioning = ["Security"] +Security_Isolation = ["Security"] +Services = [] +Services_Maps = ["Services"] +Services_Maps_Guidance = ["Services_Maps"] +Services_Maps_LocalSearch = ["Services_Maps"] +Services_Maps_OfflineMaps = ["Services_Maps"] +Services_Store = ["Services"] +Services_TargetedContent = ["Services"] +Storage = [] +Storage_AccessCache = ["Storage"] +Storage_BulkAccess = ["Storage"] +Storage_Compression = ["Storage"] +Storage_FileProperties = ["Storage"] +Storage_Pickers = ["Storage"] +Storage_Pickers_Provider = ["Storage_Pickers"] +Storage_Provider = ["Storage"] +Storage_Search = ["Storage"] +Storage_Streams = ["Storage"] +System = [] +System_Diagnostics = ["System"] +System_Diagnostics_DevicePortal = ["System_Diagnostics"] +System_Diagnostics_Telemetry = ["System_Diagnostics"] +System_Diagnostics_TraceReporting = ["System_Diagnostics"] +System_Display = ["System"] +System_Implementation = ["System"] +System_Implementation_FileExplorer = ["System_Implementation"] +System_Inventory = ["System"] +System_Power = ["System"] +System_Profile = ["System"] +System_Profile_SystemManufacturers = ["System_Profile"] +System_RemoteDesktop = ["System"] +System_RemoteDesktop_Input = ["System_RemoteDesktop"] +System_RemoteSystems = ["System"] +System_Threading = ["System"] +System_Threading_Core = ["System_Threading"] +System_Update = ["System"] +System_UserProfile = ["System"] +UI = [] +UI_Accessibility = ["UI"] +UI_ApplicationSettings = ["UI"] +UI_Composition = ["UI"] +UI_Composition_Core = ["UI_Composition"] +UI_Composition_Desktop = ["UI_Composition"] +UI_Composition_Diagnostics = ["UI_Composition"] +UI_Composition_Effects = ["UI_Composition"] +UI_Composition_Interactions = ["UI_Composition"] +UI_Composition_Scenes = ["UI_Composition"] +UI_Core = ["UI"] +UI_Core_AnimationMetrics = ["UI_Core"] +UI_Core_Preview = ["UI_Core"] +UI_Input = ["UI"] +UI_Input_Core = ["UI_Input"] +UI_Input_Inking = ["UI_Input"] +UI_Input_Inking_Analysis = ["UI_Input_Inking"] +UI_Input_Inking_Core = ["UI_Input_Inking"] +UI_Input_Inking_Preview = ["UI_Input_Inking"] +UI_Input_Preview = ["UI_Input"] +UI_Input_Preview_Injection = ["UI_Input_Preview"] +UI_Input_Spatial = ["UI_Input"] +UI_Notifications = ["UI"] +UI_Notifications_Management = ["UI_Notifications"] +UI_Popups = ["UI"] +UI_Shell = ["UI"] +UI_StartScreen = ["UI"] +UI_Text = ["UI"] +UI_Text_Core = ["UI_Text"] +UI_UIAutomation = ["UI"] +UI_UIAutomation_Core = ["UI_UIAutomation"] +UI_ViewManagement = ["UI"] +UI_ViewManagement_Core = ["UI_ViewManagement"] +UI_WebUI = ["UI"] +UI_WebUI_Core = ["UI_WebUI"] +UI_WindowManagement = ["UI"] +UI_WindowManagement_Preview = ["UI_WindowManagement"] +Wdk = [] +Wdk_Foundation = ["Wdk"] +Wdk_Graphics = ["Wdk"] +Wdk_Graphics_Direct3D = ["Wdk_Graphics"] +Wdk_Storage = ["Wdk"] +Wdk_Storage_FileSystem = ["Wdk_Storage"] +Wdk_Storage_FileSystem_Minifilters = ["Wdk_Storage_FileSystem"] +Wdk_System = ["Wdk"] +Wdk_System_IO = ["Wdk_System"] +Wdk_System_OfflineRegistry = ["Wdk_System"] +Wdk_System_Registry = ["Wdk_System"] +Wdk_System_SystemInformation = ["Wdk_System"] +Wdk_System_SystemServices = ["Wdk_System"] +Wdk_System_Threading = ["Wdk_System"] +Web = [] +Web_AtomPub = ["Web"] +Web_Http = ["Web"] +Web_Http_Diagnostics = ["Web_Http"] +Web_Http_Filters = ["Web_Http"] +Web_Http_Headers = ["Web_Http"] +Web_Syndication = ["Web"] +Web_UI = ["Web"] +Web_UI_Interop = ["Web_UI"] +Win32 = [] +Win32_AI = ["Win32"] +Win32_AI_MachineLearning = ["Win32_AI"] +Win32_AI_MachineLearning_DirectML = ["Win32_AI_MachineLearning"] +Win32_AI_MachineLearning_WinML = ["Win32_AI_MachineLearning"] +Win32_Data = ["Win32"] +Win32_Data_HtmlHelp = ["Win32_Data"] +Win32_Data_RightsManagement = ["Win32_Data"] +Win32_Data_Xml = ["Win32_Data"] +Win32_Data_Xml_MsXml = ["Win32_Data_Xml"] +Win32_Data_Xml_XmlLite = ["Win32_Data_Xml"] +Win32_Devices = ["Win32"] +Win32_Devices_AllJoyn = ["Win32_Devices"] +Win32_Devices_BiometricFramework = ["Win32_Devices"] +Win32_Devices_Bluetooth = ["Win32_Devices"] +Win32_Devices_Communication = ["Win32_Devices"] +Win32_Devices_DeviceAccess = ["Win32_Devices"] +Win32_Devices_DeviceAndDriverInstallation = ["Win32_Devices"] +Win32_Devices_DeviceQuery = ["Win32_Devices"] +Win32_Devices_Display = ["Win32_Devices"] +Win32_Devices_Enumeration = ["Win32_Devices"] +Win32_Devices_Enumeration_Pnp = ["Win32_Devices_Enumeration"] +Win32_Devices_Fax = ["Win32_Devices"] +Win32_Devices_FunctionDiscovery = ["Win32_Devices"] +Win32_Devices_Geolocation = ["Win32_Devices"] +Win32_Devices_HumanInterfaceDevice = ["Win32_Devices"] +Win32_Devices_ImageAcquisition = ["Win32_Devices"] +Win32_Devices_PortableDevices = ["Win32_Devices"] +Win32_Devices_Properties = ["Win32_Devices"] +Win32_Devices_Pwm = ["Win32_Devices"] +Win32_Devices_Sensors = ["Win32_Devices"] +Win32_Devices_SerialCommunication = ["Win32_Devices"] +Win32_Devices_Tapi = ["Win32_Devices"] +Win32_Devices_Usb = ["Win32_Devices"] +Win32_Devices_WebServicesOnDevices = ["Win32_Devices"] +Win32_Foundation = ["Win32"] +Win32_Gaming = ["Win32"] +Win32_Globalization = ["Win32"] +Win32_Graphics = ["Win32"] +Win32_Graphics_CompositionSwapchain = ["Win32_Graphics"] +Win32_Graphics_DXCore = ["Win32_Graphics"] +Win32_Graphics_Direct2D = ["Win32_Graphics"] +Win32_Graphics_Direct2D_Common = ["Win32_Graphics_Direct2D"] +Win32_Graphics_Direct3D = ["Win32_Graphics"] +Win32_Graphics_Direct3D10 = ["Win32_Graphics"] +Win32_Graphics_Direct3D11 = ["Win32_Graphics"] +Win32_Graphics_Direct3D11on12 = ["Win32_Graphics"] +Win32_Graphics_Direct3D12 = ["Win32_Graphics"] +Win32_Graphics_Direct3D9 = ["Win32_Graphics"] +Win32_Graphics_Direct3D9on12 = ["Win32_Graphics"] +Win32_Graphics_Direct3D_Dxc = ["Win32_Graphics_Direct3D"] +Win32_Graphics_Direct3D_Fxc = ["Win32_Graphics_Direct3D"] +Win32_Graphics_DirectComposition = ["Win32_Graphics"] +Win32_Graphics_DirectDraw = ["Win32_Graphics"] +Win32_Graphics_DirectManipulation = ["Win32_Graphics"] +Win32_Graphics_DirectWrite = ["Win32_Graphics"] +Win32_Graphics_Dwm = ["Win32_Graphics"] +Win32_Graphics_Dxgi = ["Win32_Graphics"] +Win32_Graphics_Dxgi_Common = ["Win32_Graphics_Dxgi"] +Win32_Graphics_Gdi = ["Win32_Graphics"] +Win32_Graphics_GdiPlus = ["Win32_Graphics"] +Win32_Graphics_Hlsl = ["Win32_Graphics"] +Win32_Graphics_Imaging = ["Win32_Graphics"] +Win32_Graphics_Imaging_D2D = ["Win32_Graphics_Imaging"] +Win32_Graphics_OpenGL = ["Win32_Graphics"] +Win32_Graphics_Printing = ["Win32_Graphics"] +Win32_Graphics_Printing_PrintTicket = ["Win32_Graphics_Printing"] +Win32_Management = ["Win32"] +Win32_Management_MobileDeviceManagementRegistration = ["Win32_Management"] +Win32_Media = ["Win32"] +Win32_Media_Audio = ["Win32_Media"] +Win32_Media_Audio_Apo = ["Win32_Media_Audio"] +Win32_Media_Audio_DirectMusic = ["Win32_Media_Audio"] +Win32_Media_Audio_DirectSound = ["Win32_Media_Audio"] +Win32_Media_Audio_Endpoints = ["Win32_Media_Audio"] +Win32_Media_Audio_XAudio2 = ["Win32_Media_Audio"] +Win32_Media_DeviceManager = ["Win32_Media"] +Win32_Media_DirectShow = ["Win32_Media"] +Win32_Media_DirectShow_Tv = ["Win32_Media_DirectShow"] +Win32_Media_DirectShow_Xml = ["Win32_Media_DirectShow"] +Win32_Media_DxMediaObjects = ["Win32_Media"] +Win32_Media_KernelStreaming = ["Win32_Media"] +Win32_Media_LibrarySharingServices = ["Win32_Media"] +Win32_Media_MediaFoundation = ["Win32_Media"] +Win32_Media_MediaPlayer = ["Win32_Media"] +Win32_Media_Multimedia = ["Win32_Media"] +Win32_Media_PictureAcquisition = ["Win32_Media"] +Win32_Media_Speech = ["Win32_Media"] +Win32_Media_Streaming = ["Win32_Media"] +Win32_Media_WindowsMediaFormat = ["Win32_Media"] +Win32_NetworkManagement = ["Win32"] +Win32_NetworkManagement_Dhcp = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Dns = ["Win32_NetworkManagement"] +Win32_NetworkManagement_InternetConnectionWizard = ["Win32_NetworkManagement"] +Win32_NetworkManagement_IpHelper = ["Win32_NetworkManagement"] +Win32_NetworkManagement_MobileBroadband = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Multicast = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Ndis = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetBios = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetManagement = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetShell = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetworkDiagnosticsFramework = ["Win32_NetworkManagement"] +Win32_NetworkManagement_NetworkPolicyServer = ["Win32_NetworkManagement"] +Win32_NetworkManagement_P2P = ["Win32_NetworkManagement"] +Win32_NetworkManagement_QoS = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Rras = ["Win32_NetworkManagement"] +Win32_NetworkManagement_Snmp = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WNet = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WebDav = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WiFi = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsConnectNow = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsConnectionManager = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsFilteringPlatform = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsFirewall = ["Win32_NetworkManagement"] +Win32_NetworkManagement_WindowsNetworkVirtualization = ["Win32_NetworkManagement"] +Win32_Networking = ["Win32"] +Win32_Networking_ActiveDirectory = ["Win32_Networking"] +Win32_Networking_BackgroundIntelligentTransferService = ["Win32_Networking"] +Win32_Networking_Clustering = ["Win32_Networking"] +Win32_Networking_HttpServer = ["Win32_Networking"] +Win32_Networking_Ldap = ["Win32_Networking"] +Win32_Networking_NetworkListManager = ["Win32_Networking"] +Win32_Networking_RemoteDifferentialCompression = ["Win32_Networking"] +Win32_Networking_WebSocket = ["Win32_Networking"] +Win32_Networking_WinHttp = ["Win32_Networking"] +Win32_Networking_WinInet = ["Win32_Networking"] +Win32_Networking_WinSock = ["Win32_Networking"] +Win32_Networking_WindowsWebServices = ["Win32_Networking"] +Win32_Security = ["Win32"] +Win32_Security_AppLocker = ["Win32_Security"] +Win32_Security_Authentication = ["Win32_Security"] +Win32_Security_Authentication_Identity = ["Win32_Security_Authentication"] +Win32_Security_Authentication_Identity_Provider = ["Win32_Security_Authentication_Identity"] +Win32_Security_Authorization = ["Win32_Security"] +Win32_Security_Authorization_UI = ["Win32_Security_Authorization"] +Win32_Security_ConfigurationSnapin = ["Win32_Security"] +Win32_Security_Credentials = ["Win32_Security"] +Win32_Security_Cryptography = ["Win32_Security"] +Win32_Security_Cryptography_Catalog = ["Win32_Security_Cryptography"] +Win32_Security_Cryptography_Certificates = ["Win32_Security_Cryptography"] +Win32_Security_Cryptography_Sip = ["Win32_Security_Cryptography"] +Win32_Security_Cryptography_UI = ["Win32_Security_Cryptography"] +Win32_Security_DiagnosticDataQuery = ["Win32_Security"] +Win32_Security_DirectoryServices = ["Win32_Security"] +Win32_Security_EnterpriseData = ["Win32_Security"] +Win32_Security_ExtensibleAuthenticationProtocol = ["Win32_Security"] +Win32_Security_Isolation = ["Win32_Security"] +Win32_Security_LicenseProtection = ["Win32_Security"] +Win32_Security_NetworkAccessProtection = ["Win32_Security"] +Win32_Security_Tpm = ["Win32_Security"] +Win32_Security_WinTrust = ["Win32_Security"] +Win32_Security_WinWlx = ["Win32_Security"] +Win32_Storage = ["Win32"] +Win32_Storage_Cabinets = ["Win32_Storage"] +Win32_Storage_CloudFilters = ["Win32_Storage"] +Win32_Storage_Compression = ["Win32_Storage"] +Win32_Storage_DataDeduplication = ["Win32_Storage"] +Win32_Storage_DistributedFileSystem = ["Win32_Storage"] +Win32_Storage_EnhancedStorage = ["Win32_Storage"] +Win32_Storage_FileHistory = ["Win32_Storage"] +Win32_Storage_FileServerResourceManager = ["Win32_Storage"] +Win32_Storage_FileSystem = ["Win32_Storage"] +Win32_Storage_Imapi = ["Win32_Storage"] +Win32_Storage_IndexServer = ["Win32_Storage"] +Win32_Storage_InstallableFileSystems = ["Win32_Storage"] +Win32_Storage_IscsiDisc = ["Win32_Storage"] +Win32_Storage_Jet = ["Win32_Storage"] +Win32_Storage_Nvme = ["Win32_Storage"] +Win32_Storage_OfflineFiles = ["Win32_Storage"] +Win32_Storage_OperationRecorder = ["Win32_Storage"] +Win32_Storage_Packaging = ["Win32_Storage"] +Win32_Storage_Packaging_Appx = ["Win32_Storage_Packaging"] +Win32_Storage_Packaging_Opc = ["Win32_Storage_Packaging"] +Win32_Storage_ProjectedFileSystem = ["Win32_Storage"] +Win32_Storage_StructuredStorage = ["Win32_Storage"] +Win32_Storage_Vhd = ["Win32_Storage"] +Win32_Storage_VirtualDiskService = ["Win32_Storage"] +Win32_Storage_Vss = ["Win32_Storage"] +Win32_Storage_Xps = ["Win32_Storage"] +Win32_Storage_Xps_Printing = ["Win32_Storage_Xps"] +Win32_System = ["Win32"] +Win32_System_AddressBook = ["Win32_System"] +Win32_System_Antimalware = ["Win32_System"] +Win32_System_ApplicationInstallationAndServicing = ["Win32_System"] +Win32_System_ApplicationVerifier = ["Win32_System"] +Win32_System_AssessmentTool = ["Win32_System"] +Win32_System_ClrHosting = ["Win32_System"] +Win32_System_Com = ["Win32_System"] +Win32_System_Com_CallObj = ["Win32_System_Com"] +Win32_System_Com_ChannelCredentials = ["Win32_System_Com"] +Win32_System_Com_Events = ["Win32_System_Com"] +Win32_System_Com_Marshal = ["Win32_System_Com"] +Win32_System_Com_StructuredStorage = ["Win32_System_Com"] +Win32_System_Com_UI = ["Win32_System_Com"] +Win32_System_Com_Urlmon = ["Win32_System_Com"] +Win32_System_ComponentServices = ["Win32_System"] +Win32_System_Console = ["Win32_System"] +Win32_System_Contacts = ["Win32_System"] +Win32_System_CorrelationVector = ["Win32_System"] +Win32_System_DataExchange = ["Win32_System"] +Win32_System_DeploymentServices = ["Win32_System"] +Win32_System_DesktopSharing = ["Win32_System"] +Win32_System_DeveloperLicensing = ["Win32_System"] +Win32_System_Diagnostics = ["Win32_System"] +Win32_System_Diagnostics_Ceip = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_ClrProfiling = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_Debug = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_Debug_ActiveScript = ["Win32_System_Diagnostics_Debug"] +Win32_System_Diagnostics_Debug_Extensions = ["Win32_System_Diagnostics_Debug"] +Win32_System_Diagnostics_Etw = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_ProcessSnapshotting = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics_ToolHelp = ["Win32_System_Diagnostics"] +Win32_System_DistributedTransactionCoordinator = ["Win32_System"] +Win32_System_Environment = ["Win32_System"] +Win32_System_ErrorReporting = ["Win32_System"] +Win32_System_EventCollector = ["Win32_System"] +Win32_System_EventLog = ["Win32_System"] +Win32_System_EventNotificationService = ["Win32_System"] +Win32_System_GroupPolicy = ["Win32_System"] +Win32_System_HostCompute = ["Win32_System"] +Win32_System_HostComputeNetwork = ["Win32_System"] +Win32_System_HostComputeSystem = ["Win32_System"] +Win32_System_Hypervisor = ["Win32_System"] +Win32_System_IO = ["Win32_System"] +Win32_System_Iis = ["Win32_System"] +Win32_System_Ioctl = ["Win32_System"] +Win32_System_JobObjects = ["Win32_System"] +Win32_System_Js = ["Win32_System"] +Win32_System_Kernel = ["Win32_System"] +Win32_System_LibraryLoader = ["Win32_System"] +Win32_System_Mailslots = ["Win32_System"] +Win32_System_Mapi = ["Win32_System"] +Win32_System_Memory = ["Win32_System"] +Win32_System_Memory_NonVolatile = ["Win32_System_Memory"] +Win32_System_MessageQueuing = ["Win32_System"] +Win32_System_MixedReality = ["Win32_System"] +Win32_System_Mmc = ["Win32_System"] +Win32_System_Ole = ["Win32_System"] +Win32_System_ParentalControls = ["Win32_System"] +Win32_System_PasswordManagement = ["Win32_System"] +Win32_System_Performance = ["Win32_System"] +Win32_System_Performance_HardwareCounterProfiling = ["Win32_System_Performance"] +Win32_System_Pipes = ["Win32_System"] +Win32_System_Power = ["Win32_System"] +Win32_System_ProcessStatus = ["Win32_System"] +Win32_System_RealTimeCommunications = ["Win32_System"] +Win32_System_Recovery = ["Win32_System"] +Win32_System_Registry = ["Win32_System"] +Win32_System_RemoteAssistance = ["Win32_System"] +Win32_System_RemoteDesktop = ["Win32_System"] +Win32_System_RemoteManagement = ["Win32_System"] +Win32_System_RestartManager = ["Win32_System"] +Win32_System_Restore = ["Win32_System"] +Win32_System_Rpc = ["Win32_System"] +Win32_System_Search = ["Win32_System"] +Win32_System_Search_Common = ["Win32_System_Search"] +Win32_System_SecurityCenter = ["Win32_System"] +Win32_System_ServerBackup = ["Win32_System"] +Win32_System_Services = ["Win32_System"] +Win32_System_SettingsManagementInfrastructure = ["Win32_System"] +Win32_System_SetupAndMigration = ["Win32_System"] +Win32_System_Shutdown = ["Win32_System"] +Win32_System_SideShow = ["Win32_System"] +Win32_System_StationsAndDesktops = ["Win32_System"] +Win32_System_SubsystemForLinux = ["Win32_System"] +Win32_System_SystemInformation = ["Win32_System"] +Win32_System_SystemServices = ["Win32_System"] +Win32_System_TaskScheduler = ["Win32_System"] +Win32_System_Threading = ["Win32_System"] +Win32_System_Time = ["Win32_System"] +Win32_System_TpmBaseServices = ["Win32_System"] +Win32_System_TransactionServer = ["Win32_System"] +Win32_System_UpdateAgent = ["Win32_System"] +Win32_System_UpdateAssessment = ["Win32_System"] +Win32_System_UserAccessLogging = ["Win32_System"] +Win32_System_Variant = ["Win32_System"] +Win32_System_VirtualDosMachines = ["Win32_System"] +Win32_System_WinRT = ["Win32_System"] +Win32_System_WinRT_AllJoyn = ["Win32_System_WinRT"] +Win32_System_WinRT_Composition = ["Win32_System_WinRT"] +Win32_System_WinRT_CoreInputView = ["Win32_System_WinRT"] +Win32_System_WinRT_Direct3D11 = ["Win32_System_WinRT"] +Win32_System_WinRT_Display = ["Win32_System_WinRT"] +Win32_System_WinRT_Graphics = ["Win32_System_WinRT"] +Win32_System_WinRT_Graphics_Capture = ["Win32_System_WinRT_Graphics"] +Win32_System_WinRT_Graphics_Direct2D = ["Win32_System_WinRT_Graphics"] +Win32_System_WinRT_Graphics_Imaging = ["Win32_System_WinRT_Graphics"] +Win32_System_WinRT_Holographic = ["Win32_System_WinRT"] +Win32_System_WinRT_Isolation = ["Win32_System_WinRT"] +Win32_System_WinRT_ML = ["Win32_System_WinRT"] +Win32_System_WinRT_Media = ["Win32_System_WinRT"] +Win32_System_WinRT_Metadata = ["Win32_System_WinRT"] +Win32_System_WinRT_Pdf = ["Win32_System_WinRT"] +Win32_System_WinRT_Printing = ["Win32_System_WinRT"] +Win32_System_WinRT_Shell = ["Win32_System_WinRT"] +Win32_System_WinRT_Storage = ["Win32_System_WinRT"] +Win32_System_WindowsProgramming = ["Win32_System"] +Win32_System_WindowsSync = ["Win32_System"] +Win32_System_Wmi = ["Win32_System"] +Win32_UI = ["Win32"] +Win32_UI_Accessibility = ["Win32_UI"] +Win32_UI_Animation = ["Win32_UI"] +Win32_UI_ColorSystem = ["Win32_UI"] +Win32_UI_Controls = ["Win32_UI"] +Win32_UI_Controls_Dialogs = ["Win32_UI_Controls"] +Win32_UI_Controls_RichEdit = ["Win32_UI_Controls"] +Win32_UI_HiDpi = ["Win32_UI"] +Win32_UI_Input = ["Win32_UI"] +Win32_UI_Input_Ime = ["Win32_UI_Input"] +Win32_UI_Input_Ink = ["Win32_UI_Input"] +Win32_UI_Input_KeyboardAndMouse = ["Win32_UI_Input"] +Win32_UI_Input_Pointer = ["Win32_UI_Input"] +Win32_UI_Input_Radial = ["Win32_UI_Input"] +Win32_UI_Input_Touch = ["Win32_UI_Input"] +Win32_UI_Input_XboxController = ["Win32_UI_Input"] +Win32_UI_InteractionContext = ["Win32_UI"] +Win32_UI_LegacyWindowsEnvironmentFeatures = ["Win32_UI"] +Win32_UI_Magnification = ["Win32_UI"] +Win32_UI_Notifications = ["Win32_UI"] +Win32_UI_Ribbon = ["Win32_UI"] +Win32_UI_Shell = ["Win32_UI"] +Win32_UI_Shell_Common = ["Win32_UI_Shell"] +Win32_UI_Shell_PropertiesSystem = ["Win32_UI_Shell"] +Win32_UI_TabletPC = ["Win32_UI"] +Win32_UI_TextServices = ["Win32_UI"] +Win32_UI_WindowsAndMessaging = ["Win32_UI"] +Win32_UI_Wpf = ["Win32_UI"] +Win32_Web = ["Win32"] +Win32_Web_InternetExplorer = ["Win32_Web"] +default = [] +deprecated = [] +docs = [] +implement = [ + "windows-implement", + "windows-interface", + "windows-core/implement", +] + +[dependencies.mozbuild] +version = "0.1" diff --git a/build/rust/windows/src/lib.rs b/build/rust/windows/src/lib.rs new file mode 100644 index 0000000000..9c5c49d089 --- /dev/null +++ b/build/rust/windows/src/lib.rs @@ -0,0 +1,24 @@ +#![allow(warnings)] +#![cfg_attr(docsrs, doc = "This is a stub. The latest API documentation is here: <https://microsoft.github.io/windows-docs-rs/>")] +#![cfg_attr(docsrs, doc = "")] +/*! +Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs> +*/ + +#![doc(html_no_source)] +#![allow(non_snake_case, clashing_extern_declarations, non_upper_case_globals, non_camel_case_types, clippy::all)] +#![cfg_attr(not(feature = "docs"), doc(hidden))] + +extern crate self as windows; + +pub mod core { + pub use windows_core::*; + + #[cfg(feature = "implement")] + pub use windows_implement::implement; + + #[cfg(feature = "implement")] + pub use windows_interface::interface; +} + +include!(mozbuild::windows_rs_path!("src/Windows/mod.rs")); diff --git a/build/sanitizers/asan_blacklist_win.txt b/build/sanitizers/asan_blacklist_win.txt new file mode 100644 index 0000000000..3bc19ba437 --- /dev/null +++ b/build/sanitizers/asan_blacklist_win.txt @@ -0,0 +1,28 @@ +# This is originally copied from Chromium tools/memory/asan/blacklist_win.txt.
+# The rules in this file are only applied at compile time. If you can modify the
+# source in question, consider function attributes to disable instrumentation.
+
+# Bug 1200740 - ASan crash due to child process function interceptions
+# Sandbox executes some of its code before the ASan RTL gets initialized and
+# maps shadow memory. As a result, instrumented code tries to access unavailable
+# shadow memory and faults.
+fun:*TargetNtSetInformationThread*
+fun:*TargetNtOpenThreadToken*
+fun:*TargetNtOpenThreadTokenEx*
+fun:*TargetNtMapViewOfSection*
+fun:*AutoProtectMemory*sandbox*
+fun:*EatResolverThunk*sandbox*
+fun:*InterceptionAgent*sandbox*
+fun:*ResolverThunk*sandbox*
+fun:*Target*SandboxFactory*sandbox*
+fun:*ProcessState*sandbox*
+src:*pe_image.h
+src:*pe_image.cc
+src:*resolver_32.cc
+src:*resolver_64.cc
+src:*filesystem_interception.cc
+src:*process_thread_interception.cc
+src:*registry_interception.cc
+src:*sandbox_nt_util.cc
+src:*sync_interception.cc
+src:*interceptors_64.cc
diff --git a/build/sanitizers/ubsan_enum_blacklist.txt b/build/sanitizers/ubsan_enum_blacklist.txt new file mode 100644 index 0000000000..1be9d23d4a --- /dev/null +++ b/build/sanitizers/ubsan_enum_blacklist.txt @@ -0,0 +1,17 @@ +# All entries in this file are to suppress issues reported by enum. +# Blacklists for other reasons should go in separate blacklist files. + +[enum] + +# bug 1404151 +src:*/lul/LulDwarfExt.h +src:*/lul/LulDwarf.cpp + +# bug 1405142 +src:*/widget/gtk/* + +# bug 1619468 +src:*/security/manager/ssl/nsSiteSecurityService.cpp + +# bug 1619484 +src:*/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.cc diff --git a/build/sanitizers/ubsan_function_blacklist.txt b/build/sanitizers/ubsan_function_blacklist.txt new file mode 100644 index 0000000000..58c8f33be4 --- /dev/null +++ b/build/sanitizers/ubsan_function_blacklist.txt @@ -0,0 +1,9 @@ +[function] +# Disable function sanitizer for all C files (new feature in clang 17) until we +# we can narrow this down. See bug 1841935. +src:*.c + +# RLBox allows automatic handling of differing machine models between the appplication and sandbox. +# To do this, RLBox carefully changes the types of function pointers to the sandbox with ones suitable for the applicaton. +# Unfortunately, this triggers the ubsan's check for calling functions with incorrect types. So disabling this. +fun:*impl_invoke_with_func_ptr* diff --git a/build/sanitizers/ubsan_object_size_blacklist.txt b/build/sanitizers/ubsan_object_size_blacklist.txt new file mode 100644 index 0000000000..e61b4eb1ec --- /dev/null +++ b/build/sanitizers/ubsan_object_size_blacklist.txt @@ -0,0 +1,7 @@ +# All entries in this file are to suppress issues reported by object-size. +# Blacklists for other reasons should go in separate blacklist files. + +[object-size] + +# bug 1577584 +src:*/gfx/harfbuzz/src/* diff --git a/build/sanitizers/ubsan_pointer_overflow_blacklist.txt b/build/sanitizers/ubsan_pointer_overflow_blacklist.txt new file mode 100644 index 0000000000..43b07ddae9 --- /dev/null +++ b/build/sanitizers/ubsan_pointer_overflow_blacklist.txt @@ -0,0 +1,30 @@ +# All entries in this file are to suppress issues reported by pointer-overflow. +# Blacklists for other reasons should go in separate blacklist files. + +[pointer-overflow] + +# cppunittest +src:*/mfbt/tests/TestArrayUtils.cpp +# gtest ImageDecodeToSurface.WebP +src:*/media/libwebp/src/dec/idec_dec.c +# gtest ImageDecoders.WebPLargeMultiChunk +src:*/media/libwebp/src/utils/bit_reader_utils.c +# gtest MediaDataDecoder.VP9 +src:*/media/ffvpx/libavcodec/avpacket.c +src:*/media/ffvpx/libavutil/imgutils.c +# gtest VP8VideoTrackEncoder.FrameEncode +src:*/media/libvpx/libvpx/vp8/encoder/encodeframe.c +# gtest ImageDecoders.AVIFSingleChunk +src:*/third_party/aom/av1/common/quant_common.c +# crashtest +src:*/parser/expat/lib/xmlparse.c +src:*/mfbt/lz4/lz4.c +src:*/media/libogg/src/ogg_framing.c +# mochitest gl2c dom/canvas/test/webgl-conf/generated/test_2_conformance2__reading__read-pixels-pack-parameters.html +src:*/dom/canvas/WebGLContextGL.cpp +# reftest J1 +src:*/js/src/builtin/TypedObject.cpp +# jittest Jit6 +src:*/js/src/jit/x86-shared/Assembler-x86-shared.h +# https://gitlab.freedesktop.org/mesa/mesa/-/issues/4477 +fun:remove_line_continuations diff --git a/build/sanitizers/ubsan_signed_overflow_blacklist.txt b/build/sanitizers/ubsan_signed_overflow_blacklist.txt new file mode 100644 index 0000000000..694eaa4737 --- /dev/null +++ b/build/sanitizers/ubsan_signed_overflow_blacklist.txt @@ -0,0 +1,257 @@ +# This file contains an extensive compile-time blacklist for silencing highly +# frequent signed integer overflows in our codebase, found by the use of +# -fsanitize=signed-integer-overflow. C/C++ say signed integer overflow is +# undefined behavior, so instances of this need to be fixed. But not all code +# has been properly written to not overflow, and overflow-checking can have +# significant compile time and runtime costs, so we will sometimes disable +# signed overflow checking. +# +# The rules in this file are applied at compile time; changes to this list +# usually require a full rebuild to apply. If you can modify the source in +# question to exempt specific functions using MOZ_NO_SANITIZE_SIGNED_OVERFLOW, +# do that instead. +# +# The extensive number of entries below is for two reasons. +# +# First, compiler instrumentation for signed integer overflows has a cost, at +# compile time and at runtime. In performance-critical code proven to have no +# signed overflow, it makes sense to turn off overflow detection to avoid both +# costs. (Indeed, -fsanitize=signed-integer-overflow is unusably slow without +# this.) +# +# Second, many entries here are overly aggressive to get the build into a state +# that allows any testing to happen at all. Some of the entries here are for +# issues that are highly frequent in our test suites -- over 500 times per run. +# Aggressive entries now let us start using this mode, without having to first +# fix wide swaths of existing code. +# +# Entries should be removed 1) as issues are fixed; and 2) as blacklist entries +# can be moved out of this centralized file, into source-level blacklist +# attributes on individual functions. + +# All entries in this file are to suppress signed-integer-overflow problems. +# Blacklists for other reasons should go in separate blacklist files. +[signed-integer-overflow] + +# Overflows in the C++ std headers aren't necessarily bugs, because code inside +# a language implementation can depend on compiler-specific behavior where C/C++ +# leave the behavior undefined. +src:*bits/basic_string.h + +# Assume everything running through CheckedInt.h is ok. Signed overflows here +# should generally have been guarded by safe overflow checks, so it's likely +# safe to exempt it from overflow checking. (This should eventually be verified +# and functions individually tagged safe so this entry can be removed.) +src:*/CheckedInt.h + +# Exclude bignum +src:*/mfbt/double-conversion/source/bignum.cc + +# Exclude anything within gtests +src:*/gtest/* + +# Atomics can overflow, but without a full stack we can't trace these back +# to what is actually causing the overflow. Ignoring these for now, as it will +# be too much effort to determine every single source here. +src:*/mfbt/Atomics.h + +# No reason to instrument certain parts of NSS that explicitely deal with +# arithmetics and crypto. +src:*/security/nss/lib/freebl/mpi/* +src:*/security/nss/lib/freebl/ecl/* + +# nsTArray_base<Alloc, Copy>::ShiftData performs overflows +fun:*nsTArray_base*ShiftData* + +### Frequent 0 - 1 overflows +# +# We have several code patterns in our codebase that cause these overflows, +# but they are typically all harmless and could be filtered easily at runtime. +# However, some of them are so frequent that suppressing them at compile-time +# makes sense to increase runtime performance. +# +src:*/netwerk/base/nsSocketTransportService2.cpp +src:*/nsCharTraits.h +# Code in xpcom/base/CycleCollectedJSContext.cpp +fun:*CycleCollectedJSContext*ProcessMetastableStateQueue* +# Code in layout/painting/nsDisplayList.cpp +fun:*nsDisplayOpacity*ShouldFlattenAway* +# Code in modules/libpref/Preferences.cpp +fun:*pref_InitInitialObjects* +# Code in netwerk/base/nsIOService.cpp +fun:*nsIOService*GetCachedProtocolHandler* +# Code in layout/xul/nsXULPopupManager.cpp +fun:*nsXULPopupManager*AdjustPopupsOnWindowChange* +# Code in dom/base/nsDocument.cpp +fun:*1nsDocument@@* +# Code in gfx/layers/ipc/CompositorBridgeChild.cpp +fun:*CompositorBridgeChild*Destroy* +# Code in gfx/layers/ipc/ImageBridgeChild.cpp +fun:*ImageBridgeChild*ShutdownStep1* +# Code in dom/base/nsGlobalWindow.cpp +fun:*nsGlobalWindow*ClearControllers* +# Code in layout/style/AnimationCollection.cpp +fun:*AnimationCollection*PropertyDtor* +# Code in layout/style/nsStyleSet.cpp +fun:*nsStyleSet*AddImportantRules* +fun:*nsStyleSet*CounterStyleRuleForName* + + +### Misc overflows + +# Hot function in protobuf producing overflows +fun:*CodedInputStream*ReadTagWithCutoff* + + +# SQLite3 is full of overflows :/ +src:*/third_party/sqlite3/src/sqlite3.c + +# zlib has some overflows, we can't deal with them right now +src:*/modules/zlib/src/* + +# Our LZ4 implementation uses overflows. By listing it here we might +# miss some unintended overflows in that implementation, but we can't +# check for it right now. +src:*/mfbt/lz4.c + +# Apparently this overflows a lot, because it contains some allocators +# that keep overflowing, not sure why. Disabling by function didn't seem +# to work here for operator new. +src:*/xpcom/ds/nsArrayEnumerator.cpp + +# Memory usage reporting code in gfx/thebes/gfxASurface.cpp +# We probably don't care about the frequent overflows there. +fun:*SurfaceMemoryReporter*AdjustUsedMemory* + +# Frequent overflower in gfx/thebes/gfxFontEntry.cpp +fun:*WeightDistance* + +# Another frequent overflower +fun:*nsTObserverArray_base*AdjustIterators* + +# Overflows in Skia +fun:*SkPathRef*makeSpace* +fun:*SkPathRef*resetToSize* + +# Expat Parser has some overflows +fun:*nsExpatDriver*ConsumeToken* + +# Frequent overflowers in harfbuzz +fun:*hb_in_range* +fun:*OT*collect_glyphs* + +# These look like harmless layouting-related overflows +src:*/gfx/cairo/libpixman/src/pixman-region.c + +# Code in ipc/chromium/src/base/file_path.cc where a function returns -1 +# being cast to unsigned and then overflowed. +fun:*FilePath*Append* +fun:*FilePath*StripTrailingSeparatorsInternal* + +# Code in dom/base/nsJSEnvironment.cpp +fun:*FireForgetSkippable* + +# Code in gfx/thebes/gfxSkipChars.h +fun:*gfxSkipCharsIterator*AdvanceSkipped* + +# Code in gfx/thebes/gfxScriptItemizer.cpp +fun:*gfxScriptItemizer*fixup* +fun:*gfxScriptItemizer*push* + +# Code in dom/base/nsDocument.cpp +fun:*nsDocument*BlockOnload* + +# Code in layout/base/nsCSSFrameConstructor.cpp +fun:*nsCSSFrameConstructor*FrameConstructionItemList*AdjustCountsForItem* + +# Code in nsprpub/lib/ds/plarena.c doing ptrdiffs +fun:*PL_ArenaRelease* + +# This file contains a bunch of arithmetic operations on timestamps that +# apparently are allowed to overflow. +src:*/src/widget/SystemTimeConverter.h + +# Code in dom/media/flac/FlacDemuxer.cpp purposely uses overflowing arithmetics +fun:*Frame*FindNext* + +# Code in netwerk/base/nsStandardURL.cpp, +# these methods return signed but the subtraction is first performed unsigned +fun:*nsStandardURL*ReplaceSegment* + +# Code in netwerk/protocol/http/nsHttpChannel.cpp +# same as previous with the previous entry. +fun:*nsHttpChannel*ReportNetVSCacheTelemetry* + +# Code in layout/tables/nsCellMap.cpp +# again subtraction then cast to signed. +fun:*nsTableCellMap*GetColInfoAt* + +# Code in layout/generic/nsTextFrame.cpp +# again subtraction then cast to signed. +fun:*nsTextFrame*CharacterDataChanged* + +# Not sure what is going on in this file, but it doesn't look +# related to what we are looking for. +src:*/xpcom/base/CountingAllocatorBase.h + +# Code in dom/base/nsDOMNavigationTiming.cpp +# Timestamp related, probably expecting the overflow +fun:*nsDOMNavigationTiming*TimeStampToDOM* + +# Several unsigned arithmetic operations with -1 +src:*/hal/HalWakeLock.cpp + +# Code in layout/generic/nsGfxScrollFrame.cpp that produces +# somewhat frequent signed integer overflows. Probably harmless +# because it's layout code. +fun:*ClampAndAlignWithPixels* + +# Likely benign overflow in mozglue/misc/TimeStamp_posix.cpp +fun:*ClockResolutionNs* + +# This header has all sorts of operators that do post-operation +# overflow and underflow checking, triggering frequent reports +src:*/mozglue/misc/TimeStamp.h + +# +# Various hashing functions, both regular and cryptographic ones +# +src:*/dom/canvas/MurmurHash3.cpp +src:*/gfx/skia/skia/include/private/SkChecksum.h +src:*/intl/icu/source/common/unifiedcache.h +src:*/mfbt/SHA1.cpp +src:*/modules/zlib/src/adler32.c +src:*/netwerk/cache2/CacheHashUtils.cpp +src:*/netwerk/sctp/src/netinet/sctp_sha1.c +src:*/netwerk/srtp/src/crypto/hash/sha1.c +src:*/netwerk/sctp/src/netinet/sctp_sha1.c +src:*/nsprpub/lib/ds/plhash.c +src:*/security/manager/ssl/md4.c +src:*/security/nss/lib/dbm/src/h_func.c +src:*/security/nss/lib/freebl/sha512.c +src:*/security/nss/lib/freebl/md5.c +src:*/xpcom/ds/PLDHashTable.cpp + +# Hash/Cache function in Skia +fun:*GradientShaderCache*Build32bitCache* + +# Hashing functions in Cairo +fun:*_hash_matrix_fnv* +fun:*_hash_mix_bits* +fun:*_cairo_hash_string* +fun:*_cairo_hash_bytes* + +# intl code hashing functions +fun:*ustr_hash*CharsN* +fun:*hashEntry* + +# harfbuzz hash/digest functions +fun:*hb_set_digest_lowest_bits_t* + +# Hash function in gfx +fun:*gfxFontStyle*Hash* + +# expat uses a CHAR_HASH macro in several places that causes +# a high amount of overflows. We should try finding a better +# way to disable this rather than blacklisting the whole thing. +src:*/parser/expat/* diff --git a/build/sanitizers/ubsan_unsigned_overflow_blacklist.txt b/build/sanitizers/ubsan_unsigned_overflow_blacklist.txt new file mode 100644 index 0000000000..46bb4f6f12 --- /dev/null +++ b/build/sanitizers/ubsan_unsigned_overflow_blacklist.txt @@ -0,0 +1,264 @@ +# This file contains an extensive compile-time blacklist for silencing highly +# frequent *un*signed integer overflows in our codebase, found by the use of +# -fsanitize=unsigned-integer-overflow. Such overflows are not necessarily +# bugs -- unsigned integer overflow has well-defined semantics in C/C++. But +# overflow may still be *unexpected* and incorrectly handled, so we try to +# annotate those places where unsigned overflow is correct and desired. +# +# The rules in this file are applied at compile time; changes to this list +# usually require a full rebuild to apply. If you can modify the source in +# question to exempt specific functions using MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW, +# do that instead. +# +# The extensive number of entries below is for two reasons. +# +# First, compiler instrumentation for unsigned integer overflows has a cost, at +# compile time and at runtime. In places where code expects and depends upon +# overflow behavior -- and especially in performance-critical code -- it makes +# sense to turn off overflow detection to avoid both costs. (Indeed, +# -fsanitize=signed-integer-overflow is unusably slow without this.) +# +# Second, many entries here are overly aggressive to get the build into a state +# that allows any testing to happen at all. Some of the entries here are for +# issues that are highly frequent in our test suites -- over 500 times per run. +# Aggressive entries now let us start using this mode, without having to first +# fix wide swaths of existing code. +# +# Entries should be removed 1) as issues are fixed; and 2) as blacklist entries +# can be moved out of this centralized file, into source-level blacklist +# attributes on individual functions. + +# All entries in this file are to suppress unsigned-integer-overflow problems. +# Blacklists for other reasons should go in separate blacklist files. +[unsigned-integer-overflow] + +# Overflows in the C++ std headers aren't necessarily bugs, because code inside +# a language implementation can depend on compiler-specific behavior where C/C++ +# leave the behavior undefined. +src:*bits/basic_string.h + +# Assume everything running through CheckedInt.h is ok. The CheckedInt class +# casts signed integers to unsigned first and then does a post-overflow +# check causing lots of unsigned integer overflow messages. +src:*/CheckedInt.h + +# Exclude bignum +src:*/mfbt/double-conversion/source/bignum.cc + +# Exclude anything within gtests +src:*/gtest/* + +# The JS engine has a lot of code doing all sorts of overflows. This code +# is pretty well tested though and excluding it here will allow us to go +# for other, less tested code. Ideally, we would include the JS engine here +# at some point. +src:*/js/src/* +src:*/js/public/* +src:*/js/*.h +src:*/jsfriendapi.h + +# Atomics can overflow, but without a full stack we can't trace these back +# to what is actually causing the overflow. Ignoring these for now, as it will +# be too much effort to determine every single source here. +src:*/mfbt/Atomics.h + +# No reason to instrument certain parts of NSS that explicitely deal with +# arithmetics and crypto. +src:*/security/nss/lib/freebl/mpi/* +src:*/security/nss/lib/freebl/ecl/* + +# nsTArray_base<Alloc, Copy>::ShiftData performs overflows +fun:*nsTArray_base*ShiftData* + +### Frequent 0 - 1 overflows +# +# We have several code patterns in our codebase that cause these overflows, +# but they are typically all harmless and could be filtered easily at runtime. +# However, some of them are so frequent that suppressing them at compile-time +# makes sense to increase runtime performance. +# +src:*/netwerk/base/nsSocketTransportService2.cpp +src:*/nsCharTraits.h +# Code in xpcom/base/CycleCollectedJSContext.cpp +fun:*CycleCollectedJSContext*ProcessMetastableStateQueue* +# Code in layout/painting/nsDisplayList.cpp +fun:*nsDisplayOpacity*ShouldFlattenAway* +# Code in modules/libpref/Preferences.cpp +fun:*pref_InitInitialObjects* +# Code in netwerk/base/nsIOService.cpp +fun:*nsIOService*GetCachedProtocolHandler* +# Code in layout/xul/nsXULPopupManager.cpp +fun:*nsXULPopupManager*AdjustPopupsOnWindowChange* +# Code in dom/base/nsDocument.cpp +fun:*1nsDocument@@* +# Code in gfx/layers/ipc/CompositorBridgeChild.cpp +fun:*CompositorBridgeChild*Destroy* +# Code in gfx/layers/ipc/ImageBridgeChild.cpp +fun:*ImageBridgeChild*ShutdownStep1* +# Code in dom/base/nsGlobalWindow.cpp +fun:*nsGlobalWindow*ClearControllers* +# Code in layout/style/AnimationCollection.cpp +fun:*AnimationCollection*PropertyDtor* +# Code in layout/style/nsStyleSet.cpp +fun:*nsStyleSet*AddImportantRules* +fun:*nsStyleSet*CounterStyleRuleForName* + + +### Misc overflows + +# Hot function in protobuf producing overflows +fun:*CodedInputStream*ReadTagWithCutoff* + + +# SQLite3 is full of overflows :/ +src:*/third_party/sqlite3/src/sqlite3.c + +# zlib has some overflows, we can't deal with them right now +src:*/modules/zlib/src/* + +# Our LZ4 implementation uses overflows. By listing it here we might +# miss some unintended overflows in that implementation, but we can't +# check for it right now. +src:*/mfbt/lz4/* + +# Apparently this overflows a lot, because it contains some allocators +# that keep overflowing, not sure why. Disabling by function didn't seem +# to work here for operator new. +src:*/xpcom/ds/nsArrayEnumerator.cpp + +# Memory usage reporting code in gfx/thebes/gfxASurface.cpp +# We probably don't care about the frequent overflows there. +fun:*SurfaceMemoryReporter*AdjustUsedMemory* + +# Frequent overflower in gfx/thebes/gfxFontEntry.cpp +fun:*WeightDistance* + +# Another frequent overflower +fun:*nsTObserverArray_base*AdjustIterators* + +# Overflows in Skia +fun:*SkPathRef*makeSpace* +fun:*SkPathRef*resetToSize* + +# Expat Parser has some overflows +fun:*nsExpatDriver*ConsumeToken* + +# Frequent overflowers in harfbuzz +fun:*hb_in_range* +fun:*OT*collect_glyphs* + +# These look like harmless layouting-related overflows +src:*/gfx/cairo/libpixman/src/pixman-region.c + +# Code in ipc/chromium/src/base/file_path.cc where a function returns -1 +# being cast to unsigned and then overflowed. +fun:*FilePath*Append* +fun:*FilePath*StripTrailingSeparatorsInternal* + +# Code in dom/base/nsJSEnvironment.cpp +fun:*FireForgetSkippable* + +# Code in gfx/thebes/gfxSkipChars.h +fun:*gfxSkipCharsIterator*AdvanceSkipped* + +# Code in gfx/thebes/gfxScriptItemizer.cpp +fun:*gfxScriptItemizer*fixup* +fun:*gfxScriptItemizer*push* + +# Code in dom/base/nsDocument.cpp +fun:*nsDocument*BlockOnload* + +# Code in layout/base/nsCSSFrameConstructor.cpp +fun:*nsCSSFrameConstructor*FrameConstructionItemList*AdjustCountsForItem* + +# Code in nsprpub/lib/ds/plarena.c doing ptrdiffs +fun:*PL_ArenaRelease* + +# This file contains a bunch of arithmetic operations on timestamps that +# apparently are allowed to overflow. +src:*/src/widget/SystemTimeConverter.h + +# Code in dom/media/flac/FlacDemuxer.cpp purposely uses overflowing arithmetics +fun:*Frame*FindNext* + +# Code in netwerk/base/nsStandardURL.cpp, +# these methods return signed but the subtraction is first performed unsigned +fun:*nsStandardURL*ReplaceSegment* + +# Code in netwerk/protocol/http/nsHttpChannel.cpp +# same as previous with the previous entry. +fun:*nsHttpChannel*ReportNetVSCacheTelemetry* + +# Code in layout/tables/nsCellMap.cpp +# again subtraction then cast to signed. +fun:*nsTableCellMap*GetColInfoAt* + +# Code in layout/generic/nsTextFrame.cpp +# again subtraction then cast to signed. +fun:*nsTextFrame*CharacterDataChanged* + +# Not sure what is going on in this file, but it doesn't look +# related to what we are looking for. +src:*/xpcom/base/CountingAllocatorBase.h + +# Code in dom/base/nsDOMNavigationTiming.cpp +# Timestamp related, probably expecting the overflow +fun:*nsDOMNavigationTiming*TimeStampToDOM* + +# Several unsigned arithmetic operations with -1 +src:*/hal/HalWakeLock.cpp + +# Code in layout/generic/nsGfxScrollFrame.cpp that produces +# somewhat frequent signed integer overflows. Probably harmless +# because it's layout code. +fun:*ClampAndAlignWithPixels* + +# Likely benign overflow in mozglue/misc/TimeStamp_posix.cpp +fun:*ClockResolutionNs* + +# This header has all sorts of operators that do post-operation +# overflow and underflow checking, triggering frequent reports +src:*/mozglue/misc/TimeStamp.h + +# +# Various hashing functions, both regular and cryptographic ones +# +src:*/dom/canvas/MurmurHash3.cpp +src:*/gfx/skia/skia/include/private/SkChecksum.h +src:*/intl/icu/source/common/unifiedcache.h +src:*/mfbt/SHA1.cpp +src:*/modules/zlib/src/adler32.c +src:*/netwerk/cache2/CacheHashUtils.cpp +src:*/netwerk/sctp/src/netinet/sctp_sha1.c +src:*/netwerk/srtp/src/crypto/hash/sha1.c +src:*/netwerk/sctp/src/netinet/sctp_sha1.c +src:*/nsprpub/lib/ds/plhash.c +src:*/security/manager/ssl/md4.c +src:*/security/nss/lib/dbm/src/h_func.c +src:*/security/nss/lib/freebl/sha512.c +src:*/security/nss/lib/freebl/md5.c +src:*/xpcom/ds/PLDHashTable.cpp + +# Hash/Cache function in Skia +fun:*GradientShaderCache*Build32bitCache* + +# Hashing functions in Cairo +fun:*_hash_matrix_fnv* +fun:*_hash_mix_bits* +fun:*_cairo_hash_string* +fun:*_cairo_hash_bytes* + +# intl code hashing functions +fun:*ustr_hash*CharsN* +fun:*hashEntry* + +# harfbuzz hash/digest functions +fun:*hb_set_digest_lowest_bits_t* + +# Hash function in gfx +fun:*gfxFontStyle*Hash* + +# expat uses a CHAR_HASH macro in several places that causes +# a high amount of overflows. We should try finding a better +# way to disable this rather than blacklisting the whole thing. +src:*/parser/expat/* diff --git a/build/sparse-profiles/docker-image b/build/sparse-profiles/docker-image new file mode 100644 index 0000000000..9fb1329530 --- /dev/null +++ b/build/sparse-profiles/docker-image @@ -0,0 +1,26 @@ +%include build/sparse-profiles/mach + +[include] +path:taskcluster/ + +# Required for loading taskgraph.parameters. +path:browser/config/version_display.txt +path:browser/config/version.txt + +# Result from `grep -hr %include taskcluster/docker | grep -v " taskcluster/" | sort -u` +path:python/mozbuild/mozbuild/action/tooltool.py +path:testing/mozharness/external_tools/performance-artifact-schema.json +path:testing/mozharness/external_tools/robustcheckout.py +path:tools/lint/spell/codespell_requirements.txt +path:tools/lint/eslint/eslint-plugin-mozilla/manifest.tt +path:tools/lint/eslint/manifest.tt +path:tools/lint/python/flake8_requirements.txt +path:tools/lint/python/pylint_requirements.txt +path:tools/lint/python/black_requirements.txt +path:tools/lint/tox/tox_requirements.txt + +# Required for the webrender docker image +path:gfx/wr/ci-scripts/docker-image/setup.sh + +# for the system-symbol images +path:tools/crashreporter/system-symbols/ diff --git a/build/sparse-profiles/github-sync b/build/sparse-profiles/github-sync new file mode 100644 index 0000000000..72f265b3a1 --- /dev/null +++ b/build/sparse-profiles/github-sync @@ -0,0 +1,7 @@ +%include build/sparse-profiles/mach +%include build/sparse-profiles/taskgraph + +[include] +path:gfx/wr/ +path:taskcluster/scripts/misc/ +path:tools/github-sync/ diff --git a/build/sparse-profiles/mach b/build/sparse-profiles/mach new file mode 100644 index 0000000000..118b79ff8c --- /dev/null +++ b/build/sparse-profiles/mach @@ -0,0 +1,19 @@ +[include] +# Various mach commands call config.guess to resolve the default objdir name. +path:build/autoconf/config.guess +path:build/autoconf/config.sub +path:build/moz.configure/checks.configure +path:build/moz.configure/init.configure +path:build/moz.configure/util.configure +# Used for bootstrapping the mach driver. +path:build/mach_initialize.py +path:build/psutil_requirements.txt +path:build/zstandard_requirements.txt +path:mach +# Various dependencies. There is room to trim fat, especially in +# third_party/python. +path:python/ +path:testing/mozbase/ +path:third_party/python/ +# certifi is needed for Sentry +path:testing/web-platform/tests/tools/third_party/certifi diff --git a/build/sparse-profiles/mozharness b/build/sparse-profiles/mozharness new file mode 100644 index 0000000000..c2a49d412b --- /dev/null +++ b/build/sparse-profiles/mozharness @@ -0,0 +1,4 @@ +%include build/sparse-profiles/mach + +[include] +path:testing/mozharness diff --git a/build/sparse-profiles/perftest b/build/sparse-profiles/perftest new file mode 100644 index 0000000000..abb4d922ab --- /dev/null +++ b/build/sparse-profiles/perftest @@ -0,0 +1,8 @@ +%include build/sparse-profiles/docker-image + +[include] +path:tools/lint/eslint/ +path:testing/performance +path:testing/condprofile +path:python/mozbuild/mozbuild/action/tooltool.py +glob:**/perftest_*.js diff --git a/build/sparse-profiles/profile-generate b/build/sparse-profiles/profile-generate new file mode 100644 index 0000000000..be1fa53372 --- /dev/null +++ b/build/sparse-profiles/profile-generate @@ -0,0 +1,9 @@ +%include build/sparse-profiles/mach + +[include] +path:build/ +path:testing/talos/talos +path:testing/profiles/ +path:third_party/webkit/ +path:tools/quitter/ +path:taskcluster/scripts/misc diff --git a/build/sparse-profiles/push-to-try b/build/sparse-profiles/push-to-try new file mode 100644 index 0000000000..ff8fd73579 --- /dev/null +++ b/build/sparse-profiles/push-to-try @@ -0,0 +1,5 @@ +%include build/sparse-profiles/taskgraph + +[include] +path:tools/tryselect/ +path:try_task_config.json diff --git a/build/sparse-profiles/sphinx-docs b/build/sparse-profiles/sphinx-docs new file mode 100644 index 0000000000..491d18b080 --- /dev/null +++ b/build/sparse-profiles/sphinx-docs @@ -0,0 +1,56 @@ +%include build/sparse-profiles/mach + +[include] +# List of dependencies for the command +path:python/sites/docs.txt + +# Code for generating docs. +glob:docs/** +glob:tools/moztreedocs/** + +# For icons +glob:browser/branding/nightly/** + +# Potential docs sources +glob:**/*.rst +glob:**/*.md +glob:**/*.mjs +glob:**/*.js +glob:**/*.jsm +glob:**/*.json + +# Potential included images. We don't glob all paths in order to avoid importing +# images unrelated to documentation (like branding or test images) +glob:**/docs/**.jpg +glob:**/docs/**.png +glob:**/docs/**.svg +glob:**/docs/**.gif +glob:**/devtools/**.gif +glob:**/devtools-user/**.gif +glob:**/Debugger/**.png +glob:**/Debugger/**.svg + +# Include everything found in the perfdocs generated folder +glob:testing/perfdocs/generated/** + +# Python API docs. +glob:**/*.py +# Referenced by some python files. +path:taskcluster/ci/docker-image/kind.yml + +# Included in ipc docs +path:ipc/ipdl/test/ipdl/ok/PMyManaged.ipdl +path:ipc/ipdl/test/ipdl/ok/PMyManager.ipdl +path:ipc/ipdl/test/ipdl/ok/MyTypes.ipdlh + +# moz.build files are read to discover location of docs. +glob:**/moz.build + +# package*.json files are needed for node_modules +glob:**/package*.json + +# Read to set the version of the docs. +path:config/milestone.txt + +# mots configuration +path:mots.yaml diff --git a/build/sparse-profiles/startup-test b/build/sparse-profiles/startup-test new file mode 100644 index 0000000000..fd73995d86 --- /dev/null +++ b/build/sparse-profiles/startup-test @@ -0,0 +1,6 @@ +%include build/sparse-profiles/mozharness + +[include] +# for fetch-content +path:taskcluster/scripts/misc/ + diff --git a/build/sparse-profiles/taskgraph b/build/sparse-profiles/taskgraph new file mode 100644 index 0000000000..e2974b80e5 --- /dev/null +++ b/build/sparse-profiles/taskgraph @@ -0,0 +1,94 @@ +%include build/sparse-profiles/mach + +# In order to decide which docker images to build, we need all the +# files that docker images depend on as well +%include build/sparse-profiles/docker-image + +[include] +# These files are read as part of generating the taskgraph. +path:browser/locales/l10n-changesets.json +path:browser/locales/l10n-onchange-changesets.json +path:mobile/locales/l10n-changesets.json +path:mobile/locales/l10n-onchange-changesets.json +path:browser/locales/shipped-locales +path:browser/config/version_display.txt +path:browser/config/version.txt +path:browser/config/whats_new_page.yml +path:browser/installer/attribution.yml + +# Lots of random files in here are read. Just pull in the whole thing. +path:build/ + +# TODO remove once bug 1402010 is resolved and test manifests aren't +# processed in Files() reading mode in moz.build files. +path:layout/tools/reftest/ +path:testing/web-platform/tests/tools/ + +# The main meat of this profile. +path:taskcluster/ + +# Various files in these directories are read by taskgraph. Just pull +# them all in. +path:testing/config/tooltool-manifests/ +path:testing/mozharness/ +path:tools/lint/ + +# for new-style try pushes +path:try_task_config.json + +# Moz.build files are read in filesystem mode +glob:**/moz.build +glob:**/*.mozbuild + +# Moz.configure files could trigger changes +glob:**/*.configure + +# Tooltool manifests also need to be opened. Assume they +# are all somewhere in "tooltool-manifests" directories. +glob:**/tooltool-manifests/** + +# For test chunking +glob:**/*.ini +glob:**/*.list +glob:**/*.toml +path:testing/mozbase/manifestparser +path:testing/runtimes +path:testing/web-platform/tests/ +path:testing/web-platform/mozilla/tests/ +glob:testing/web-platform/*.py + +# For scheduling android-gradle-dependencies. +path:mobile/android/config/ +glob:**/*.gradle + +# for action-task building +path:.taskcluster.yml +path:.cron.yml + +# for the wrench-deps toolchain task +path:gfx/wr/Cargo.lock +path:gfx/wr/ci-scripts/ + +# for the mar-tools toolchain task +path:mfbt/ +path:modules/libmar/ +path:other-licenses/bsdiff/ +path:other-licenses/nsis/Contrib/CityHash/cityhash/ +path:toolkit/mozapps/update/updater + +# for the minidump-stackwalk toolchain task +path:toolkit/crashreporter +path:tools/crashreporter/ +path:mfbt +path:config/external/zlib +path:build/moz.configure + +# for the browsertime toolchain task +path:tools/browsertime/mach_commands.py +path:tools/browsertime/package.json +path:tools/browsertime/package-lock.json + +# for the geckodriver toolchain task +path:testing/geckodriver +path:testing/mozbase/rust +path:testing/webdriver diff --git a/build/sparse-profiles/toolchain-build b/build/sparse-profiles/toolchain-build new file mode 100644 index 0000000000..fe542dd219 --- /dev/null +++ b/build/sparse-profiles/toolchain-build @@ -0,0 +1,9 @@ +# Profile needed to build toolchain tasks. + +# This is probably a little wider than we need it to be. But it is +# still relatively small and it keeps this profile simple. +%include build/sparse-profiles/taskgraph + +[include] +# Needed by build-clang.py. +path:tools/rewriting/
\ No newline at end of file diff --git a/build/sparse-profiles/tps b/build/sparse-profiles/tps new file mode 100644 index 0000000000..fe9b238f90 --- /dev/null +++ b/build/sparse-profiles/tps @@ -0,0 +1,5 @@ +%include build/sparse-profiles/mach + +[include] +path:services/sync/tps/ +path:testing/tps/ diff --git a/build/sparse-profiles/update-verify b/build/sparse-profiles/update-verify new file mode 100644 index 0000000000..83589d1f3b --- /dev/null +++ b/build/sparse-profiles/update-verify @@ -0,0 +1,4 @@ +%include build/sparse-profiles/mach + +[include] +path:tools/update-verify/ diff --git a/build/sparse-profiles/upload-generated-sources b/build/sparse-profiles/upload-generated-sources new file mode 100644 index 0000000000..3e39d32b66 --- /dev/null +++ b/build/sparse-profiles/upload-generated-sources @@ -0,0 +1,4 @@ +%include build/sparse-profiles/mach + +[include] +path:build/upload_generated_sources.py diff --git a/build/sparse-profiles/upload-symbols b/build/sparse-profiles/upload-symbols new file mode 100644 index 0000000000..1b46f04f99 --- /dev/null +++ b/build/sparse-profiles/upload-symbols @@ -0,0 +1,4 @@ +%include build/sparse-profiles/mach + +[include] +path:toolkit/crashreporter/tools/upload_symbols.py diff --git a/build/sparse-profiles/webrender b/build/sparse-profiles/webrender new file mode 100644 index 0000000000..3ed69aa3b1 --- /dev/null +++ b/build/sparse-profiles/webrender @@ -0,0 +1,7 @@ +%include build/sparse-profiles/mach +%include build/sparse-profiles/taskgraph + +[include] +path:gfx/wr/ +path:taskcluster/scripts/misc/ +path:xpcom/rust/ diff --git a/build/templates.mozbuild b/build/templates.mozbuild new file mode 100644 index 0000000000..811b96bb7e --- /dev/null +++ b/build/templates.mozbuild @@ -0,0 +1,237 @@ +# -*- 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 Binary(): + """Generic template for target binaries. Meant to be used by other + templates.""" + + # Add -llog by default, since we use it all over the place. + if CONFIG["OS_TARGET"] == "Android": + OS_LIBS += ["log"] + + +@template +def Program(name): + """Template for program executables.""" + PROGRAM = name + + Binary() + + +@template +def SimplePrograms(names, ext=".cpp"): + """Template for simple program executables. + + Those have a single source with the same base name as the executable. + """ + SIMPLE_PROGRAMS += names + SOURCES += ["%s%s" % (name, ext) for name in names] + + Binary() + + +@template +def CppUnitTests(names, ext=".cpp"): + """Template for C++ unit tests. + + Those have a single source with the same base name as the executable. + """ + COMPILE_FLAGS["EXTRA_INCLUDES"] = [ + "-I%s/dist/include" % TOPOBJDIR, + "-I%s/dist/include/testing" % TOPOBJDIR, + ] + CPP_UNIT_TESTS += names + SOURCES += ["%s%s" % (name, ext) for name in names] + + Binary() + + +@template +def Library(name): + """Template for libraries.""" + LIBRARY_NAME = name + + +@template +def AllowCompilerWarnings(): + COMPILE_FLAGS["WARNINGS_AS_ERRORS"] = [] + WASM_FLAGS["WARNINGS_AS_ERRORS"] = [] + + +@template +def DisableCompilerWarnings(): + # Keep the -Wno-* flags to disable warnings that may be enabled through other means. + def filter(flags): + return [f for f in flags or [] if f.startswith("-Wno-")] + + COMPILE_FLAGS["WARNINGS_CFLAGS"] = filter(CONFIG["WARNINGS_CFLAGS"]) + COMPILE_FLAGS["WARNINGS_CXXFLAGS"] = filter(CONFIG["WARNINGS_CXXFLAGS"]) + HOST_COMPILE_FLAGS["WARNINGS_CFLAGS"] = filter(CONFIG["WARNINGS_HOST_CFLAGS"]) + HOST_COMPILE_FLAGS["WARNINGS_CXXFLAGS"] = filter(CONFIG["WARNINGS_HOST_CXXFLAGS"]) + + +@template +def RustLibrary(name, features=None, output_category=None, is_gkrust=False): + """Template for Rust libraries.""" + Library(name) + + IS_RUST_LIBRARY = True + # Some Rust build scripts compile C/C++ sources, don't error on warnings for them. + AllowCompilerWarnings() + + # And furthermore, don't even show warnings for them, so they don't regress + # the Compiler Warnings build metric + # <https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Automated_Performance_Testing_and_Sheriffing/Build_Metrics#compiler_warnings>. + DisableCompilerWarnings() + + if features: + RUST_LIBRARY_FEATURES = features + + if output_category: + RUST_LIBRARY_OUTPUT_CATEGORY = output_category + + if is_gkrust: + IS_GKRUST = True + + +@template +def SharedLibrary(name, output_category=None): + """Template for shared libraries.""" + Library(name) + + FORCE_SHARED_LIB = True + + if output_category: + SHARED_LIBRARY_OUTPUT_CATEGORY = output_category + + Binary() + + +@template +def Framework(name, output_category=None): + """Template for OSX Frameworks.""" + SharedLibrary(name, output_category) + + IS_FRAMEWORK = True + + +@template +def HostProgram(name): + """Template for build tools executables.""" + HOST_PROGRAM = name + + +@template +def HostSimplePrograms(names, ext=".cpp"): + """Template for simple build tools executables. + + Those have a single source with the same base name as the executable. + """ + HOST_SIMPLE_PROGRAMS += names + HOST_SOURCES += ["%s%s" % (name.replace("host_", ""), ext) for name in names] + + +@template +def HostSharedLibrary(name): + """Template for build tools libraries.""" + if name != "clang-plugin": + error( + "Please make sure host shared library support is complete " + "before using for something else than the clang plugin" + ) + + HOST_LIBRARY_NAME = name + + FORCE_SHARED_LIB = True + + +@template +def HostLibrary(name): + """Template for build tools libraries.""" + HOST_LIBRARY_NAME = name + + +@template +def HostRustLibrary(name, features=None): + """Template for host Rust libraries.""" + HostLibrary(name) + + IS_RUST_LIBRARY = True + # Some Rust build scripts compile C/C++ sources, don't error on warnings for them. + AllowCompilerWarnings() + + if features: + HOST_RUST_LIBRARY_FEATURES = features + + +@template +def DisableStlWrapping(): + COMPILE_FLAGS["STL"] = [] + + +@template +def NoVisibilityFlags(): + COMPILE_FLAGS["VISIBILITY"] = [] + + +@template +def ForceInclude(*headers): + """Force includes a set of header files in C++ compilations""" + if CONFIG["CC_TYPE"] == "clang-cl": + include_flag = "-FI" + else: + include_flag = "-include" + for header in headers: + CXXFLAGS += [include_flag, header] + + +@template +def GeneratedFile(name, *names, **kwargs): + """Add one or more GENERATED_FILES with the given attributes. + + You must pass in at least one generated file (the "name" argument). Other + names can be included as positional arguments after "name".""" + script = kwargs.pop("script", None) + entry_point = kwargs.pop("entry_point", None) + inputs = kwargs.pop("inputs", []) + flags = kwargs.pop("flags", []) + force = kwargs.pop("force", False) + if kwargs: + error("Unrecognized argument(s) to GeneratedFile: %s" % ", ".join(kwargs)) + if entry_point and not script: + error("entry_point cannot be provided if script is not provided") + if script and ":" in script: + error( + "script should not include a `:`. If you want to provide an " + "alternative entry point for your script, use the entry_point " + "parameter." + ) + + key = (name,) + names if names else name + GENERATED_FILES += [key] + generated_file = GENERATED_FILES[key] + if script and not entry_point: + generated_file.script = script + if script and entry_point: + generated_file.script = script + ":" + entry_point + generated_file.inputs = inputs + generated_file.flags = flags + generated_file.force = force + + +@template +def CbindgenHeader(name, inputs): + """Add one GENERATED_FILES by running RunCbindgen.py""" + + inputs = ["!/config/cbindgen-metadata.json"] + inputs + GeneratedFile( + name, script="/build/RunCbindgen.py", entry_point="generate", inputs=inputs + ) + + +include("gecko_templates.mozbuild") diff --git a/build/tests/cram/cram.toml b/build/tests/cram/cram.toml new file mode 100644 index 0000000000..99a5883548 --- /dev/null +++ b/build/tests/cram/cram.toml @@ -0,0 +1 @@ +["test_configure_help.t"] diff --git a/build/tests/cram/test_configure_help.t b/build/tests/cram/test_configure_help.t new file mode 100644 index 0000000000..f606991260 --- /dev/null +++ b/build/tests/cram/test_configure_help.t @@ -0,0 +1,14 @@ +configure --help works + + $ cd $TESTDIR/../../.. + + $ touch $TMP/mozconfig + $ export MOZCONFIG=$TMP/mozconfig + $ ./configure --help 2>& 1 | head -n 7 + Adding configure options from */tmp/mozconfig (glob) + checking for vcs source checkout... hg + checking for vcs source checkout... hg + Usage: configure.py [options] + + Options: [defaults in brackets after descriptions] + --help print this message diff --git a/build/unix/aix.exp b/build/unix/aix.exp new file mode 100644 index 0000000000..20f7cb4313 --- /dev/null +++ b/build/unix/aix.exp @@ -0,0 +1,5 @@ +# 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/. + +NSGetModule diff --git a/build/unix/build-binutils/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F.key b/build/unix/build-binutils/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F.key new file mode 100644 index 0000000000..a76485a9fc --- /dev/null +++ b/build/unix/build-binutils/3A24BC1E8FB409FA9F14371813FCEF89DD9E3C4F.key @@ -0,0 +1,51 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFm/2cUBEADkvRqMWfAryJ52T4J/640Av5cam9ojdFih9MjcX7QWFxIzJfTF +Yq2z+nb4omdfZosdCJL2zGcn6C0AxpHNvxR9HMDkEyFHKrjDh4xWU+pH4z9azQEq +Jh331X7UzbZldqQo16VkuVavgsTJaHcXm+nGIBTcUbl2oiTtHhmuaYxx6JTMcFjC +7vyO5mLBw78wt52HBYweJ0NjHBvvH/JxbAAULSPRUC61K0exlO49VFbFETQNG1hZ +TKEji95fPbre7PpXQ0ewQShUgttEE/J3UA4jYaF9lOcZgUzbA27xTV//KomP0D30 +yr4e4EJEJYYNKa3hofTEHDXeeNgM25tprhBUMdbVRZpf2Keuk2uDVwc+EiOVri48 +rb1NU+60sOXvoGO6Ks81+mhAGmrBrlgLhAp8K1HPHI4MG4gHnrMqX2rEGUGRPFjC +3qqVVlPm8H05PnosNqDLQ1Pf7C0pVgsCx6hKQB7Y1qBui7aoj9zeFaQgpYef+CEE +RIKEcWwrjaOJwK3pi9HFdxS0NNWYZj8HPzz/AsgTTQdsbulPlVq2SsctmOnL42CZ +OCTppGYwl53CG/EqVY+UQBzFzJBaY8TJRFFYVEy5/HH4H11rMoZwqIkk71EOGU3X +6mWlANRikR3M4GhVITRzuaV69Fed+OeXcCmP94ASLfuhBR2uynmcHpBKpwARAQAB +tDtOaWNrIENsaWZ0b24gKENoaWVmIEJpbnV0aWxzIE1haW50YWluZXIpIDxuaWNr +Y0ByZWRoYXQuY29tPokCOAQTAQIAIgUCWb/ZxQIbAwYLCQgHAwIGFQgCCQoLBBYC +AwECHgECF4AACgkQE/zvid2ePE9cOxAA3cX1bdDaTFttTqukdPXLCtD2aNwJos4v +B4LYPSgugLkYaHIQH9d1NQPhS0TlUeovnFNESLaVsoihv0YmBUCyL4jE52FRoTjE +6fUhYkFNqIWN2HYwkVrSap2UUJFquRVoVbPkbSup8P+D8eydBbdxsY6f+5E8Rtz5 +ibVnPZTib7CyqnFokJITWjzGdIP0Gn+JWVa6jtHTImWx1MtqiuVRDapUhrIoUIjf +98HQn9/N5ylEFYQTw7tzaJNWeGUoGYS8+8n/0sNbuYQUU/zwMVY9wpJcrXaas6yZ +XGpF/tua59t9LFCct+07YAUSWyaBXqBW3PKQz7QP+oE8yje91XrhOQam04eJhPIB +LO88g6/UrdKaY7evBB8bJ76Zpn1yqsYOXwAxifD0gDcRTQcB2s5MYXYmizn2GoUm +1MnCJeAfQCi/YMobR+c8xEEkRU83Tnnw3pmAbRU6OcPihEFuK/+SOMKIuV1QWmjk +bAr4g9XeXvaN+TRJ9Hl/k1k/sj+uOfyGIaFzM/fpaLmFk8vHeej4i2/C6cL4mnah +wYBDHAfHO65ZUIBAssdA6AeJ+PGsYeYhqs6zkpaA2b0wT4f9s7BPSqi0Veky8bUY +YY7WpjzDcHnj1gEeIU55EhOQ42dnEfv7WrIAXanOP8SjhgqAUkb3R88azZCpEMTH +iCE4bFxzOmi5Ag0EWb/ZxQEQALaJE/3u23rTvPLkitaTJFqKkwPVylzkwmKdvd2q +eEFk1qys2J3tACTMyYVnYTSXy5EJH2zJyhUfLnhLp8jJZF4oU5QehOaJPcMmzI/C +ZS1AmH+jnm6pukdZAowTzJyt4IKSapr+7mxcxX1YQ2XewMnFYpLkAA2dHaChLSU/ +EHJXe3+O4DgEURTFMa3SRN/J4GNMBacKXnMSSYylI5DcIOZ/v0IGa5MAXHrP1Hwm +1rBmloIcgmzexczBf+IcWgCLThyFPffv+2pfLK1XaS82OzBC7fS01pB/eDOkjQuK +y16sKZX6Rt57vud40uE5a0lpyItC2P7u7QWL4yT5pMF+oS8bm3YWgEntV380RyZp +qgJGZTZLNq2T4ZgfiaueEV4JzOnG2/QRGjOUrNQaYzKy5V127CTnRg4BYF/uLEmi +zLcI3O3U1+mEz6h48wkAojO1B6AZ8Lm+JuxOW5ouGcrkTEuIG56GcDwMWS/Pw/vN +sDyNmOCjy9eEKWJgmMmLaq59HpfTd8IOeaYyuAQHAsYt/zzKy0giMgjhCQtuc99E +4nQE9KZ44DKsnqRabK9s3zYE3PIkCFIEZcUiJXSXWWOIdJ43j+YyFHU5hqXfECM6 +rzKGBeBUGTzyWcOX6YwRM4LzQDVJwYG8cVfth+v4/ImcXR43D4WVxxBEAjKag02b ++1yfABEBAAGJAh8EGAECAAkFAlm/2cUCGwwACgkQE/zvid2ePE/dqQ/6ApUwgsZz +tps0MOdRddjPwz44pWXS5MG45irMQXELGQyxkrafc8lwHeABYstoK8dpopTcJGE3 +dZGL3JNz1YWxQ5AV4uyqBn5N8RubcA8NzR6DQP+OGPIwzMketvVC/cbbKDZqf0uT +Dy3jP65OFhSkTEIynYv1Mb4JJl3Sq+haUbfWLAV5nboSuHmiZE6Bz2+TjdoVkNwH +Bfpqxu6MlWka+P98SUcmY8iVhPy9QC1XFOGdFDFf1kYgHW27mFwds35NQhNARgft +AVz9FZXruW6tFIIfisjr3rVjD9R8VgL7l5vMr9ylOFpepnI6+wd2X1566HW7F1Zw +1DIrY2NHL7kL5635bHrJY4n7o/n7Elk/Ca/MAqzdIZxz6orfXeImsqZ6ODn4Y47P +ToS3Tr3bMNN9N6tmOPQZkJGHDBExbhAi/Jp8fpWxMmpVCUl6c85cOBCR4s8tZsvG +YOjR3CvqKrX4bb8GElrhOvAJa6DdmZXc7AyoVMaTvhpq3gJYKmC64oqt7zwIHwaC +xTbP6C6oUp9ENRV7nHnXN3BlvIgCo4QEs6HkDzkmgYlCEOKBiDyVMSkPDZdsspa+ +K4GlU2Swi/BDJMjtDxyo+K0M81LXXxOeRfEIfPtZ3ddxBKPva1uSsuz+pbN9d1JY +8Ko5T/h16susi2ReUyNJEJaSnjO5z13TQ1U= +=93P0 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-binutils/build-binutils.sh b/build/unix/build-binutils/build-binutils.sh new file mode 100755 index 0000000000..338a9dd29a --- /dev/null +++ b/build/unix/build-binutils/build-binutils.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +set -x + +make_flags="-j$(nproc) MAKEINFO=true" + +root_dir="$1" + +cd $root_dir/binutils-source + +patch -p1 <<'EOF' +From 4476cc67e657d6b26cd453c555a611f1ab956660 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" <hjl.tools@gmail.com> +Date: Thu, 30 Aug 2018 09:21:57 -0700 +Subject: [PATCH] ld: Lookup section in output with the same name + +When there are more than one input sections with the same section name, +SECNAME, linker picks the first one to define __start_SECNAME and +__stop_SECNAME symbols. When the first input section is removed by +comdat group, we need to check if there is still an output section +with section name SECNAME. + + PR ld/23591 + * ldlang.c (undef_start_stop): Lookup section in output with + the same name. +--- + ld/ldlang.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/ld/ldlang.c b/ld/ldlang.c +index 8878ccd..d644b56 100644 +--- a/ld/ldlang.c ++++ b/ld/ldlang.c +@@ -6097,6 +6097,24 @@ undef_start_stop (struct bfd_link_hash_entry *h) + || strcmp (h->u.def.section->name, + h->u.def.section->output_section->name) != 0) + { ++ asection *sec = bfd_get_section_by_name (link_info.output_bfd, ++ h->u.def.section->name); ++ if (sec != NULL) ++ { ++ /* When there are more than one input sections with the same ++ section name, SECNAME, linker picks the first one to define ++ __start_SECNAME and __stop_SECNAME symbols. When the first ++ input section is removed by comdat group, we need to check ++ if there is still an output section with section name ++ SECNAME. */ ++ asection *i; ++ for (i = sec->map_head.s; i != NULL; i = i->map_head.s) ++ if (strcmp (h->u.def.section->name, i->name) == 0) ++ { ++ h->u.def.section = i; ++ return; ++ } ++ } + h->type = bfd_link_hash_undefined; + h->u.undef.abfd = NULL; + } +-- +2.17.1 +EOF + +cd .. + +TARGETS="aarch64-linux-gnu arm-linux-gnueabi i686-w64-mingw32" + +gcc_major=8 +if [ -d $MOZ_FETCHES_DIR/sysroot ]; then + # Don't silently use a non-existing directory for C++ headers. + [ -d $MOZ_FETCHES_DIR/sysroot/usr/include/c++/$gcc_major ] || exit 1 + export CFLAGS="-g -O2 --sysroot=$MOZ_FETCHES_DIR/sysroot" + export CXXFLAGS="$CFLAGS -isystem $MOZ_FETCHES_DIR/sysroot/usr/include/c++/$gcc_major -isystem $MOZ_FETCHES_DIR/sysroot/usr/include/x86_64-linux-gnu/c++/$gcc_major" + export LDFLAGS="-L$MOZ_FETCHES_DIR/sysroot/lib/x86_64-linux-gnu -L$MOZ_FETCHES_DIR/sysroot/usr/lib/x86_64-linux-gnu -L$MOZ_FETCHES_DIR/sysroot/usr/lib/gcc/x86_64-linux-gnu/8" +fi + + +# Build target-specific GNU as ; build them first so that the few documentation +# files they install are overwritten by the full binutils build. + +for target in $TARGETS; do + + mkdir binutils-$target + cd binutils-$target + + ../binutils-source/configure --prefix /tools/binutils/ --disable-gold --disable-ld --disable-binutils --disable-gprof --disable-nls --target=$target $EXTRA_CONFIGURE_FLAGS || exit 1 + make $make_flags || exit 1 + make install $make_flags DESTDIR=$root_dir || exit 1 + + cd .. +done + +# Build binutils +mkdir binutils-objdir +cd binutils-objdir + +# --enable-targets builds extra target support in ld. +# Enabling aarch64 support brings in arm support, so we don't need to specify that too. +../binutils-source/configure --prefix /tools/binutils/ --enable-gold --enable-plugins --disable-nls --enable-targets="$TARGETS" $EXTRA_CONFIGURE_FLAGS || exit 1 +make $make_flags || exit 1 +make install $make_flags DESTDIR=$root_dir || exit 1 + +cd .. + +# Make a package of the built binutils +cd $root_dir/tools +tar caf $root_dir/binutils.tar.zst binutils/ diff --git a/build/unix/build-gcc/07F3DBBECC1A39605078094D980C197698C3739D.key b/build/unix/build-gcc/07F3DBBECC1A39605078094D980C197698C3739D.key new file mode 100644 index 0000000000..d78c28c2e6 --- /dev/null +++ b/build/unix/build-gcc/07F3DBBECC1A39605078094D980C197698C3739D.key @@ -0,0 +1,53 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDpu6yARBACaqhVMzAymKhrUcY1uR1pjYxM5LSuYq6mmCPTNwlGRV5RqQL0p +uXrYlfofu8xsKiVuUKk+Dx5aJT6SDxMNkfogPGMgHK8iCaHiMrw4nTtvrJDaoxDo +k0k62fBa8pGv7N7G0FqfkpBS/x+SDNcgWGgsJugFgqetAiaHIVD4A2tRawCgt72R +OX0StnDnwQFxovV0pIy5ka8D/14GxPLs4qTGWWA6B8mycT67/isaAshq9eJKxZVq +M+0rjSRmhMO0/Ajl4PjzjJXA3PH0H8dTyYSkERjEKQ0McjVLmiTM9SYBtCdkra8Q +Fc+zTPqwjX3AayK5DocfHJ2GRhBXNb2DCdznX4A9zFCssb3FLYE/ZCDqwvrQWH6i +dobAA/0ftbhPLtpZnpgGq1InjDzsvEqHEEt97k/iiQxsRH0/52vLD6ZQaENOlDVt +WulDu3gI+TjI1YgGQq8B7VzW6wRR5JW3Gx9emjP3oTVjTz0bmyuaICyetldfu+yZ +A92SU7Wm4NiMMORB+KkMDfveEWT/XW35mMTJdjpgkQH9KgrEI7QkVmluY2VudCBM +ZWZldnJlIDx2aW5jZW50QHZpbmMxNy5uZXQ+iGIEExECACIFAksWVb0CGyMGCwkI +BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEJgMGXaYw3OdKBwAn1gsYIqfmX7cFPVP +bRrQo44e7rZFAJ0RqZAd7PDqT0WectbqGWuaugerf4hlBBMRAgAlAhsjBgsJCAcD +AgYVCAIJCgsEFgIDAQIeAQIXgAUCS/PnRQIZAQAKCRCYDBl2mMNznXR7AJ9gDnrA +LCJfyqRjfVBP6aF4JfzxbQCfTXAAEbnlEhBECqgYF/S8ZjNJD8WIVgQTEQIAFgQL +CgQDAxUDAgMWAgECF4AFAkvz5lEACgkQmAwZdpjDc50eRwCgsQeoNoSgrDpFmfIy +gsU7a5qhqR0AoLQWp2fHpmlNhYua+A8HVxBjoyKJiFYEExECABYFAjpu6yAECwoE +AwMVAwIDFgIBAheAAAoJEJgMGXaYw3OdSgQAnRfkXJVySd9AhQYiMX0iIDqfiGRj +AJ4pLPdp4VvVBPloIt4SN2E559kNRIhZBBMRAgAZBAsKBAMDFQMCAxYCAQIXgAUC +SCGibQIZAQAKCRCYDBl2mMNznduQAJoCD5vaJOLGEO605eNKXTXRt2ygvwCfSNHR +RgaYU+5YIWf3zteNWBxC0K6IYgQTEQIAIgIbIwYLCQgHAwIGFQgCCQoLBBYCAwEC +HgECF4AFAkvz50AACgkQmAwZdpjDc534tACggJHDY3pXzW1T8vDLeysKNIVBkukA +nj6WfWlDjvVSGkZDfcJyhvBXDzsZiGIEExECACIFAksWVd8CGyMGCwkIBwMCBhUI +AgkKCwQWAgMBAh4BAheAAAoJEJgMGXaYw3Od6mYAn0JipNlCsSpyet3FelnGFWS0 +2eDzAJ9SFzy6w0IgIdJJdO0Y6/BAzq+jsIhgBBMRAgAgBQJIIaFtAhsjBgsJCAcD +AgQVAggDBBYCAwECHgECF4AACgkQmAwZdpjDc53gqACffa9gv0J/e9JEt6IFLkYY +fRmbt/YAnirKbsByzSvS0csLhOFx/uOA+qB5iGAEExECACACGyMGCwkIBwMCBBUC +CAMEFgIDAQIeAQIXgAUCSCGiaAAKCRCYDBl2mMNznfLyAKCqhRZQegYMDYoJ9Po+ +5RxOHteSlwCfVARE7QYuaEPWdRGE3hEI6l1rhRqIYAQTEQIAIAUCSCGenwIbIwYL +CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJgMGXaYw3OdNQYAn2/gJ1CdC6tTo1O3 +cc4GD+MG9227AJsEi9hD8xkIJqS9J/7KCpy6Cm+h9IhgBBMRAgAgBQJIIaGEAhsj +BgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQmAwZdpjDc52c8gCeNpU/yisNGveb +z10ifoz6d03XvyAAn3hNIG8aCemLdPgmHGdhATqTJcGmiGAEExECACAFAkghnsAC +GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCYDBl2mMNznbGYAJ42N2JMtPSn +kVn4qVPHUc7WOU3YCACdFgBS10cg1wzkTF40k8PKy5IKnVOIYAQTEQIAIAUCSCGh +oAIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJgMGXaYw3OdvAwAn3Lux4sL ++FNQGaFKviI+4GG+1BlIAKCGu8WiBKIsUjxC98SjMVG+4xN16rkCDQQ6butMEAgA +gUyl/BQ0OA7B/GSDdx6J/wjS/S4QDx7ZehgigOhJAA74e1rUqeFykb1sqxxkKnCy +AOSqHu2BQXqk7G7ozor5bU8eE6Rki7H6Vf734TprsQgYqPrztgcVxL2InRHcMw8I +GMZZKhWbSzKST6XaEg7Yxy7pkvNhl29bc9scWNjOCxkUt6L9wtp2UEZQf5bL41k1 +A7B1/dGOAe+DOX64x2lNYAlry3f7WV7Yq99YgcFy+V+o2wW5OBb/404x8DIm7bKT +zBiOO1QNNe8vGJAEf1lAhldPE03T9aNNXr0tHytLcDsQbHkbnsJELtY6C2AQiAKy +thMo1OVC+y0+Kr3JMFfumwADBQf8CiymrdhZGEZYsgJfpih+eaoBVgnlY6lHx1bQ +Ovfol4x7B+szlNtHjA+r3PV9uPsrxa6J5qT31iPPHgwu1utTJ8tQov9OpXvEB/2J +8DV8lYzTMpAB/GKoDUFZEGc4q+BQAvTfYYv+6WKoFjRL6iKt+Qb6WyonjG6ViPeb +IURoMP6eE7wPFCVwK8xWHvB32jdf+ni9a2XuE9bLkF8pHcC2pz0gi7vIk88FPo8E +ypKTL5MjC0/7+nYK9K45PZwmWNO0m5BooyP6ddGP0xJq8gisZuSWAFW3I+SW5DyP +nvxpOXCzSj0vCHuHvDbdsUArdNWUTpxw5k3XvAIxPLMBsFK3qIhGBBgRAgAGBQI6 +butMAAoJEJgMGXaYw3OdiYYAn2SsLZg3Cj2Rg7ZziZ01NE5QpP5CAKCLyZeqvx28 +Lt44/DBv052TOb47tw== +=ERlK +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/13975A70E63C361C73AE69EF6EEB81F8981C74C7.key b/build/unix/build-gcc/13975A70E63C361C73AE69EF6EEB81F8981C74C7.key new file mode 100644 index 0000000000..53591cf752 --- /dev/null +++ b/build/unix/build-gcc/13975A70E63C361C73AE69EF6EEB81F8981C74C7.key @@ -0,0 +1,82 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDs4dV0RBACZII57dgbfnCC7RTrJ1yc0F1ofEZJJ/x4tAtSHMDNj2zTnLR25 +5AHmxN85namwJdn7ixXSZv1FMPCeTs6jDk98YuA9r5uuCNPqCNZsuQtREpN7h+wO +IeRrhvg9/F11mty/5NthXNh8P2ELnkWXSHu6DvTQyGppAtxueOL0CjRrpwCggVYu +vxui5mqNq9+lILbMi2Zm3UkD/0T/0HupthZFXbuzY/h/nyqzoPOxnSAAAx6N7SiE +2w9OQ1w3K8WOFoPH9P0cnIQ+KnMSGQV4C2WY/d8YtShnKkXRYZVvlK+aiwmvf1kU +yNyUqaA/GhW5FWN26zFQc3G5Y9TDjgBqjd6SequZztK5M5cknJGJn+otpdQtA1Dx +2KEABACSYjdRNT3OvQJ7OSz4x4C58JKz/P69WsNZxqYVo66P7PGxM7V2GykFPbG7 +agyEMWP1alvUK551IamVtXN+mD7h3uwi5Er0cFBBfV8bSLjmhSchVpyQpiMe2iAr +IFeWox7IUp3zoT35/CP4xMu5l8pza61U5+hK3G7ud5ZQzVvh8bQrUmljaGFyZCBH +dWVudGhlciAoV29yaykgPHJndWVudGhlckBzdXNlLmRlPohfBBMRAgAfBQJDJvJg +AhsDBwsJCAcDAgEDFQIDAxYCAQIeAQIXgAAKCRBu64H4mBx0x0IPAJ9OiDKdHqdX +2ETKcxD78PcKDCcg6gCfWuJ6TizPW0n5vV16NMKl74j528aIYgQTEQIAIgIbAwIe +AQIXgAUCVmLemAYLCQgHAwIGFQgCCQoLBBYCAwEACgkQbuuB+JgcdMdosgCeLZi7 +4DbKYbK6Sinww8ldLc0eRbgAnjcppbTLIHxcr6Lngb44v4fh8jm5iF8EExECAB8F +AkMm8uECGwMHCwkIBwMCAQMVAgMDFgIBAh4BAheAAAoJEG7rgfiYHHTHTcoAn0/u +FvF25feqywtGPSpL6gQ+VQZiAJ42Q8zMLMqHxd5g0e3L7mrag7EgVIhiBBMRAgAi +AhsDAh4BAheABQJWYt6YBgsJCAcDAgYVCAIJCgsEFgIDAQAKCRBu64H4mBx0x14N +AJ9lFQUMIHywsroHrCpGbAKxvcQrowCeNIbpm2Ct0SNJBKZ8BwhX/1bfrsyIXwQT +EQIAHwUCQybzCQIbAwcLCQgHAwIBAxUCAwMWAgECHgECF4AACgkQbuuB+JgcdMeg +1gCff0P5UUkRXbj/0n0ron/Xh3ji0isAnRZOtUOA2ILSNd9PNCLea9jstf6hiGIE +ExECACICGwMCHgECF4AFAlZi3pgGCwkIBwMCBhUIAgkKCwQWAgMBAAoJEG7rgfiY +HHTH1PAAnj/1LWl3pxLYweV1ZClR0i44GJQcAJoCM0+92pI3VIsSMfkYaUVmOjVz +f4hfBBMRAgAfBQJDJvKmAhsDBwsJCAcDAgEDFQIDAxYCAQIeAQIXgAAKCRBu64H4 +mBx0xyAgAJwN2SASDJN9Y2H9iMjRSCkEftC7PgCeOTjpR3vyDnM7QL8bjwEiR5l7 +l3qIYgQTEQIAIgIbAwcLCQgHAwIBAxUCAwMWAgECHgECF4AFAkm3jjkCGQEACgkQ +buuB+JgcdMcXrACfVTEyxl0EqQN+FpmssqVUXMuGIPkAnjuh0lk4rlWnFHuRPKFP +aLNcn7TbiGUEExECACUCGwMCHgECF4ACGQEFAlZi3pMGCwkIBwMCBhUIAgkKCwQW +AgMBAAoJEG7rgfiYHHTHIBIAn20wZDYF0KrfbJNzK4/VwAEAzN+wAJ9Dpbhtq4sR +oH3cbadBsD2mXXthOohXBBMRAgAXBQI7OHVdBQsHCgMEAxUDAgMWAgECF4AACgkQ +buuB+JgcdMexIACfUdyOhJRqUp4ENf5WMF7zbVVLryoAn2cNiUWC2u4za4NDyde6 ++JGW3yo4iFoEMBECABoFAkm3je4THSBBY2NvdW50IGRpc2FibGVkLgAKCRBu64H4 +mBx0xw8pAJ9f38BHfCYcFBFrzasWJ50aYiq9agCeJc39ixXix4rnOa8vzBvSqILU +3J2IXwQTEQIAHwUCPvYc2wIbAwcLCQgHAwIBAxUCAwMWAgECHgECF4AACgkQbuuB ++JgcdMcsEACfQPXptVqB3lVdH8NmJq9988UjdugAnjc51tLV7wP/omMaG6zxqOBe +bByGiFcEExECABcFAjs4dV0FCwcKAwQDFQMCAxYCAQIXgAAKCRBu64H4mBx0x7Eg +AJ9R3I6ElGpSngQ1/lYwXvNtVUuvKgCfZw2JRYLa7jNrg0PJ17r4kZbfKjiIVwQT +EQIAFwULBwoDBAMVAwIDFgIBAheABQJJt44zAAoJEG7rgfiYHHTHt1oAmwfqV/fy +BQtuo6iVwyrLTrv6SH8WAJ9+vQxODP5nLEVv0VDkPe9YDmnHIohaBBMRAgAaBQsH +CgMEAxUDAgMWAgECF4AFAkMm92MCGQEACgkQbuuB+JgcdMf9FgCffJBUSQIPBPWC +zQvDLdCCQKj1gS0AnjY8bbEU+8j9MJdoyti8VQqc063IiFoEMBECABoFAkm3jboT +HSBBY2NvdW50IGRpc2FibGVkLgAKCRBu64H4mBx0x3w4AJ9uJb1MnaB4XL2W4/ur +kpvbRPiNrgCfRnEpymRfBRjuqSZpLr6t2548MFaIWgQwEQIAGgUCSbeOjRMdIEFj +Y291bnQgZGlzYWJsZWQuAAoJEG7rgfiYHHTHsjkAn3kJ+cwIuWjR07f/1L87hC1x +MGmAAJ45JUNoUgl45+JYUVamI+Sno02roLkBCwRDJvHRAQgA+McP+S2zoZBu2xX7 +r5pmB8IroxVl7Xgw5cUbrQWacc/NfKaivO7sPFJA6QqIpTj2ZSSVMhDUSsYivycL +OOZUeabsIfnd3Lz86SU+Cl5wEsZI/1aKpDxMnE1SINZADSvYdZUCyLzo34Td725s +3hVIrjJ3okxHUynYqDJLYsrY+NGj6jua6U4VoACjGaLyBYhVHqy/l2SHeD/r8N8q +DfZTwJaMWnkhcqaTIw9Ifl45kvh4F/HghrVwVxZ8Mll2xhD4QH5q7MerKv8NLmif +hpLvZYCmlaTAfUy799ic4RjfvIXgbBg9v8zkujPbBMzF2N9+XMIx19DnoK4yV9zz +gx5P8wAGKYhJBBgRAgAJBQJDJvHRAhsCAAoJEG7rgfiYHHTH8bQAn3wHFhPW+umo +2VjoxvBftJ3dKzXnAJ0Q6iW7EvhZeCIUE4Wcs5AYavoaXIkBZwQYEQIACQIbAgUC +SXscKQEpwF0gBBkBAgAGBQJDJvHRAAoJEDqwCZb8JqZBuHQIAOoXgUMEyxCHz6+S +EW9c5NC+1eRAy5B52vJoIYdxL97n8nTFvm4vJsyecXKH20jLxyP2xzv3J5NO5dJA +smBTTZeHoQviiwal7klZa8VtjhLI2TJHdRyleDOQfzRyuwcXmLHALHLs9MSNDjzJ +PT2GKDh6IMdDV9LijHQXlpRDiraaThs21TpYcQ//yXoErBJQL3+V8VCYyeTtJ4hC +pPCAL1NqA9mEJDP+01kGj63cROVFx89nZ2MIZEmbmZswb+nATLUv1+t2inMFiTnr +ISm4D3seOYgO+3fhhsA6U9g9IKy+eHNl2hWtG/+oFwbE2F1gDvPCIYOWuNF/tGDU +pPyLO+gJEG7rgfiYHHTHVYMAlROqNeZ/TalCmF9ijupqU65WvW0AnRRSCD49emCs +/SWngtDxJuTG8FGFuQELBEMm8fwBCAC3KLX691TOFiizmWZTOeRNREUEZYy89I6c +HrYjYyrRkBrOHJGNvoS5JO4Zy6wlc9bNGWxQU92bJCMiqE8n1mRRIs6J4gExThWq +BZzsZlcrs/gu6HxPFCvPlg62emPkd6//KPrcAIMshvNKGLMFK15n5Nkv5ofv/xcr +/fqjisISnk4fr1GI9wJQUQdCTEXu9o92erIfzb8m1Q7FJbXNhyv7tcekdr5Q20jr +ZDgxX3H1aLq8EG8nrNlJqulWLtWIh/k9Uwa5ZvmcDVhKES1BUqdCefqkGpFQXiIt +zKu6cgs8anXeG1RRqFoOvipZQ/lUqYQtP0iK05NHQFfp7cTaHo2fAAYpiEYEGBEC +AAYFAjs4dV4ACgkQbuuB+JgcdMeqzACfeHjT2PFYdy88PHNVGw5se9PqGPYAnArp +X32fDdu/xhuqjqHrNkwyO/YoiEkEGBECAAkFAkMm8dECGwIACgkQbuuB+JgcdMfx +tACffAcWE9b66ajZWOjG8F+0nd0rNecAnRDqJbsS+Fl4IhQThZyzkBhq+hpciEkE +GBECAAkFAkMm8fwCGwwACgkQbuuB+JgcdMcy4QCdFw3ipNDVX3Z77ZHMmbYhhtUm +M8EAnA1jqzeVutwLtlzYT+Tl/HDB6dJOuQENBDs4dV4QBACXdavIYhl+L248s1mU +i9EUESu9QovNzuf79zUZpRUzFdwX8hq56BuWHjU6hXYpzPWwXHnYwsNINNXUPAOf +h83PA/sNg572HgQGkx48bUNLstDQugPrzau97LoK/DD54WYEFd2ISoJe8+5bh3dY +yc6xCovkGJJAf4aLAissU3vKPwADBQP+P0U7OJ/UYt2hIbx+wSL/9rGrSxcj421F +Q6u+auRMIbejmtk4k3DP4oFCk/jkt3Oiw7hX+Q9W4nlTgSmsQ9Gp6N9JNb6gr4GC +bSZ8iaDDsm9p2Q15d8l3BiJ263IXWOOuhV2qmtKMABqhmBKLazDTcIXHVaR0v4YJ +xzA3ohWXk4iIRgQYEQIABgUCOzh1XgAKCRBu64H4mBx0x6rMAJ94eNPY8Vh3Lzw8 +c1UbDmx70+oY9gCcCulffZ8N27/GG6qOoes2TDI79iiISQQYEQIACQUCQybx0QIb +AgAKCRBu64H4mBx0x/G0AJ98BxYT1vrpqNlY6MbwX7Sd3Ss15wCdEOoluxL4WXgi +FBOFnLOQGGr6Glw= +=XJ6e +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/33C235A34C46AA3FFB293709A328C3A2C3C45C06.key b/build/unix/build-gcc/33C235A34C46AA3FFB293709A328C3A2C3C45C06.key new file mode 100644 index 0000000000..f183ce9e49 --- /dev/null +++ b/build/unix/build-gcc/33C235A34C46AA3FFB293709A328C3A2C3C45C06.key @@ -0,0 +1,33 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBECGYZsRBAC9VE8N8vHAG87MTC2wbtnmbSD8Wc2xYCaLofZAH+vXyio3Dnwx +jQLlj7IgwRWNAVq13uL0wn0WAsGop5Cs7nA/JD4MEBBNSdnvq1bMYitch2PTtAU+ +h6HaI9JXBDUh4AKZz2rllKgbigMHlgIugxnKTAMJIhS63lCTHWEDlnycJwCgqSX9 +hDs9eBC5coearGDhc0BDvTsD/A05YkZkQBgsYD6cjWFwNLJIcaHORKlLLZ9gRJO5 +LVcKaCEgYSWAM7dadJeqIFi9RkXdv+cWozxTgrGlY4T7/PakIBB7wWj2Zl72mW5a +NHT2vAemB8IFV1saiFXZM+qDhCHbV4yKSmNOQHY1VnSCUrgINiM0qlTz08yjUazK +fm2BBACDF3ZfUQNeHC9zwfsgCzKnqOm7FSlwOyI0f+j83B5PH2+KuzuyEqYoxGp+ +2d1zTxvbOeBBaX8T1M4n5d9ixiFMhgbTzuyit3nn6cp5j2L0IAS9pw0kaWpPMhpQ +zydNgnaBxHs1Y+cP4iM/4FWFCvfjUdR7xULdEzkgGxevu8pNEbQgSmFrdWIgSmVs +aW5layA8amFrdWJAcmVkaGF0LmNvbT6IZAQTEQIAJAIbAwYLCQgHAwIDFQIDAxYC +AQIeAQIXgAUCSe3VIgUJEs109wAKCRCjKMOiw8RcBqANAJ0VlFMTtevlkEM+ym4k +yE3YOrGZ+wCeP7lZGc2jVLHJfrOKxXsTM5YPWhqIZAQTEQIAJAIbAwYLCQgHAwID +FQIDAxYCAQIeAQIXgAUCTI3tMgUJHtOOlwAKCRCjKMOiw8RcBjySAJ9ApMXF3+gW +Ir0zpMxvWb53/oxsHgCaAl6V5JS9GJUnrPiHKdR+sMFPkd6IZAQTEQIAJAUCQIZh +mwIbAwUJCWYBgAYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRCjKMOiw8RcBrC+AJ9d +mQcWoZHFGoinHck309KD0m2FegCeMBjr/M6Ec1myCYMUhtpl5DI7zY25Ag0EQIZh +ohAIALrI1X59CM30/Ufg+O9FFRRyM8GefACfItrIvp6jx+0ZMY+/ZbYnlMzI7Gz4 +xNXc+83Zsz7zE5xogNcq9LILdhB7Ta1ZRkRttM8AdfyakRQTjzCPtxSPgSao/Dcu +CL09BZdaeeqMAxLmw9DnY3xmZqQtCau8PlgIiClq2db9Wy0bpQ+DDfQV4MlX6eoI +33TG9Moy59QQUG5reQ2JNkQZRebPxJAPiAgHoF/Q+XO1pLeCccIN7SApe7yVd/4A +sS3Y9lZj2JvEvutLojsRGL0E/CAwH8cJqPAt65qbOgQzCILhcc9aYZ234g9n7Kpx +Ck1h2QMtXfsmaA7GsrXo1Ddfra8ABA0H/0sa4SCQhWQ14tOFkN15xzuaqGOxUD+O +uAsgRdKaFdIhZnj0MRmvOfBSP7hONw7fE0m9DVq9NDPqFcMeyCuBNIMpGIuN6CAK +/G0K2UgzoCxMXUEYGncFfVnOoNURV9u2lGq7ZMNJmuzt0BhxXtUYRlH3WRPqPyGv +s/OrIqvgN+Kf9+i0kQSObWz6CeYnBKzCc++MPkVhYj8KR5Y6n3zPZpnOfmO3c0rY +C+KiNoMwchlZmiOh7zgcTybv4zuOU7bppEidreIq2/o4nBNTao/5uzYdDX9FBpDT +hhU9ErdO8Vd7Vf2I1/WQdt6dHUXPLfkwI8+ODE/4R/Oz8opFC5L22kSITwQYEQIA +DwIbDAUCTI3tTQUJHtOOqwAKCRCjKMOiw8RcBrBvAKCTFx5FOuuxM2VoQka8iBGj +f1vcugCdHV/JIhOwETTqOQEbkw3y9ng2+4U= +=K9Jj +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/343C2FF0FBEE5EC2EDBEF399F3599FF828C67298.key b/build/unix/build-gcc/343C2FF0FBEE5EC2EDBEF399F3599FF828C67298.key new file mode 100644 index 0000000000..548a560202 --- /dev/null +++ b/build/unix/build-gcc/343C2FF0FBEE5EC2EDBEF399F3599FF828C67298.key @@ -0,0 +1,35 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQFNBFDrIWMBCgCyyYoTAD/aL6Yl90eSJ1xuFpODTcwyRZsNSUZKSmKwnqXo9LgS +2B00yVZ2nO2OrSmWPiYikTciitv04bAqFaggSstx6hlni6n3h2PL0jXpf9EI6qOO +oKwi2IVtbBnJAhWpfRcAce6WEqvnav6KjuBM3lr8/5GzDV8tm6+X/G/paTnBqTB9 +pBxrH7smB+iRjDt/6ykWkbYLd6uBKzIkAp4HqAZb/aZMvxI28PeWGjZJQYq2nVPf +LroM6Ub/sNlXpv/bmHJusFQjUL368njhZD1+aVLCUfBCCDzvZc3EYt3wBkbmuCiA +xOb9ramHgiVkNENtzXR+sbQHtKRQv/jllY1qxROM2/rWmL+HohdxL5E0VPple2bg +U/zqX0Hg2byb8FbpzPJO5PnBD+1PME3Uirsly4N7XT80OvhXlYe4t+9X0QARAQAB +tCROaWVscyBNw7ZsbGVyIDxuaXNzZUBseXNhdG9yLmxpdS5zZT6JAX4EEwECACgF +AlDrIWMCGwMFCRLMAwAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPNZn/go +xnKYqm0J/A4b6TE5qPWiWj0kriUBSmpys3qUz93gR6Ft7w2f478KJuzbSadvyn0u +PcnP26AGTOQq75RhtgCJgdYbvRocTjlMh9jOX584Hx8hi/QSrpCSYMnj6dQKbu0Y +QIFjZx8gPeYvzG8t34FCNEzZ09RQZqy/ukRyN99LkwEuP4FWq486b7dpgv7GC+SH +lZcMco6VW8FLOT7KMalH06cmdhFPrFSYAIHDu3CsYhC8knIQV99Xzno/KeSkEwkq +tYDOdz0x4HWdOwHrl2S2X6Ex1q3QRXcq84EYQwHz2WEGaPR7Vd76P5J1wiHN6rwO +4exfgsRyTvc6NDQPTFqmoCzwuPviYk6JNnHr9E5TkLT7lAnESEhMLyyIG/7Uwpgu +5C71IMaTpOpf8DEU9NU/zuxgHoMaKBZaeYKs0S26s1zwGOlQX0T9uQFNBFDrIWMB +CgDKlONI+5Bqcu69+72fmLZPizzEUsIRA2Y0w2RE7+uJ5Es9/YTp5PnWANpPT7GS +8JJnc6NJJeh6GkMkGGwq5Op7CDsjW9pQZ0vAW90XjnyniDa9W0W+m5+X/LPOzh+n +is9Zcf17P91tprLCLi+TOOb35xt396pZ+S+PwuV0dLiIYdVYV3e6LNCV0LjhEqp5 +3TRwTrLTNPQVnt0DPYTh/Kn1x6d5zOS0MK4QybKN1WJU6nYIQRXyWKkixjbs++jc +gV/juck96Ve0blvn6DfqfpG8YzbmqRCufLo683LtlBUZ0c+znrD1nouqX2Eb/Cyl +G8Q8ZUHXimCJ+g6RfH9kOmtVH/208u/nDofVL/Q0dvAXfU5MX49c7XYy7B2rTlk+ +4nuNeaHM0aU2Y14+SQy+sR6zydu7eGLdqjzV0CX/ekgrjQARAQABiQFlBBgBAgAP +BQJQ6yFjAhsMBQkSzAMAAAoJEPNZn/goxnKYGUcJ/j+L0/uzfwCR1aTBZ6FBT9Od +NyatVjmz20ahskF3BySmkT1R06K08YOGJ//LPajj0eKqU8WKgxMc7pWi5SG+yMFn +2db5HnJDGiSmSjCXW/BzsSt1786LtO0m0ehatj9kl6JrxQNXazOkRJ2ww13P6/91 +RBaV6R08BmFTrUco2P6w+djCF4NlnkOLa7fM6QtNZM+yB+EzaPjSBFjZG52BVWZk +cXEVN0cEjPuznuQOmx8Dny7lQikp49NumrbamaxZEilx2Bi9gSbovNaKBuncKi9X +boiEiNbAarGxP40Qvlk2AuXWvq+fiBnU1e1nU2oV7/7nAWH7kj/Vr/JxcBeOpsND +GkW7Yrd3mkJCrhG+jMs1V2qNb9Uhr5ZLOA40sIz2PHfDrR+gc8THm2p5OvCWEAeu +kYJ22XTUIt6XoPO0ERYD +=MH4q +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/5ED46A6721D365587791E2AA783FCD8E58BCAFBA.key b/build/unix/build-gcc/5ED46A6721D365587791E2AA783FCD8E58BCAFBA.key new file mode 100644 index 0000000000..7cc6ba735c --- /dev/null +++ b/build/unix/build-gcc/5ED46A6721D365587791E2AA783FCD8E58BCAFBA.key @@ -0,0 +1,38 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDuVqKgRBAD5Mcvdc41W5lpeZvYplEuyEBXwmxnUryE2KaCG1C06sGyqgiec +VPXPbgIPKOUt4veMycVoqU4U4ZNuIeCGPfUvkGKLKvy5lK3iexC1Qvat+9ek2+yX +9zFlTo9QyT4kjn+xaZQYVctL370gUNV4eoiWDdrTjIvBfQCb+bf87eHv0QCg/7xt +wnq3uMpQHX+k2LGD2QDEjUcEALalUPPX99ZDjBN75CFUtbE43a73+jtNOLJFqGo3 +ne/lB8DqVwavrgQQxQqjg2xBVvagNpu2Cpmz3HlWoaqEb5vwxjRjhF5WRE+4s4es +9536lQ6pd5tZK4tHMOjvICkSg2BLUsc8XzBreLv3GEdpHP6EeezgAVQyWMpZkCdn +Xk8FA/9gRmro4+X0KJilw1EShYzudEAi02xQbr9hGiA84pQ4hYkdnLLeRscChwxM +VmoiEuJ51ZzIPlcSifzvlQBHIyYCl0KJeVMECXyjLddWkQM32ZZmQvG02mL2XYmF +/UG+/0vd6b2ISmtns6WrULGPNtagHhul+8j7zUfedsWuqpwbm7QmTWFyayBBZGxl +ciA8bWFkbGVyQGFsdW1uaS5jYWx0ZWNoLmVkdT6IRgQQEQIABgUCPIx/xAAKCRDZ +on0lAZZxp+ETAJ0bn8ntrka3vrFPtI6pRwOlueDEgQCfdFqvNgLv1QTYZJQZ5rUn +oM+F+aGIRgQQEQIABgUCQ5GdzQAKCRAvWOuZeViwlP1AAJ4lI6tis2lruhG8DsQ0 +xtWvb2OCfACfb5B/CYDjmRInrAgbVEla3EiO9sKIWAQQEQIAGAUCO5WoqAgLAwkI +BwIBCgIZAQUbAwAAAAAKCRB4P82OWLyvunKOAJ9kOC1uyoYYiXp2SMdcPMj5J+8J +XQCeKBP9Orx0bXK6luyWnCS5LJhevTyJARwEEAECAAYFAlDH6cIACgkQdxZ3RMno +5CguZAf/dxDbnY+rad6GJ1fYVyB9PfboyXLY/vksmupE9rbYmuLP85Rq1hdN56aZ +Qwjm7EPQi6htFANKOPkjOhutSD4X530Dj6Y7To8t85lW3351OP07EfZGilolIugU +6IMZNaUHVF1T0I68frkNTrmRx0PcOJacWB6fkBdoNtd5NLASgI+cszgLsD6THJZk +58RUDINY6fGBYFZkl2/dBbkLaj3DFr+ed6Oe99d546nfSz+zsm454W2M+Wf/yplK +O8Sd641h1eRGD/vihsOO+4gRgS+tQNzwb+eivON0PMvsGAEPEQ+aPVQ/U/UIQSYA ++cYz2jGSXhVppatEpq5U3aJLbcZKOrkCDQQ7laipEAgA9kJXtwh/CBdyorrWqULz +Bej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHT +UPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq +01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O +9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcK +ctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TIL +OwACAgf/aMWYoBCocATXsfSUAJb69OPUXWjevZiCf6n+7Id3L5X5um55L5sEBr8+ +8m5SIuHUippgNFJdu2xyulbb1MeegtTttEWymF9sM8cWfeTjXPOd7+ZQumiOXwk/ +g0qqjTrq7EYW5PlMjO2FbH/Ix9SHKVS9a0eGUUl+PBv3fkEZBJ4HhweqcSfLyKU/ +CHysN03Z36gtdu1BJlzHy8BPxWzP4vtPEi57Q1dFDY/+OrdlBnwKTpne6y0rAbi/ +wk6FxDGQ86vdapLI51kTxvkYx8+qZXqE4CG5fWbAFDQVTNZIWJNgYMX7Kgl8Fvw+ +7zCqJsv/KbuonIEb5hNViflVTWlBAIhMBBgRAgAMBQI7laipBRsMAAAAAAoJEHg/ +zY5YvK+6T88An1VSVGbeKbIL+k8HaPUsWB7qs5RhAKDdtkn0xqOr+0pE5eilEc61 +pMCmSQ== +=5shY +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/7F74F97C103468EE5D750B583AB00996FC26A641.key b/build/unix/build-gcc/7F74F97C103468EE5D750B583AB00996FC26A641.key new file mode 100644 index 0000000000..6f23744afe --- /dev/null +++ b/build/unix/build-gcc/7F74F97C103468EE5D750B583AB00996FC26A641.key @@ -0,0 +1,54 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDs4dV0RBACZII57dgbfnCC7RTrJ1yc0F1ofEZJJ/x4tAtSHMDNj2zTnLR25 +5AHmxN85namwJdn7ixXSZv1FMPCeTs6jDk98YuA9r5uuCNPqCNZsuQtREpN7h+wO +IeRrhvg9/F11mty/5NthXNh8P2ELnkWXSHu6DvTQyGppAtxueOL0CjRrpwCggVYu +vxui5mqNq9+lILbMi2Zm3UkD/0T/0HupthZFXbuzY/h/nyqzoPOxnSAAAx6N7SiE +2w9OQ1w3K8WOFoPH9P0cnIQ+KnMSGQV4C2WY/d8YtShnKkXRYZVvlK+aiwmvf1kU +yNyUqaA/GhW5FWN26zFQc3G5Y9TDjgBqjd6SequZztK5M5cknJGJn+otpdQtA1Dx +2KEABACSYjdRNT3OvQJ7OSz4x4C58JKz/P69WsNZxqYVo66P7PGxM7V2GykFPbG7 +agyEMWP1alvUK551IamVtXN+mD7h3uwi5Er0cFBBfV8bSLjmhSchVpyQpiMe2iAr +IFeWox7IUp3zoT35/CP4xMu5l8pza61U5+hK3G7ud5ZQzVvh8bQtUmljaGFyZCBH +dWVudGhlciA8cmljaGFyZC5ndWVudGhlckBnbWFpbC5jb20+iGUEExECACUCGwMC +HgECF4ACGQEFAlZi3pMGCwkIBwMCBhUIAgkKCwQWAgMBAAoJEG7rgfiYHHTHIBIA +n20wZDYF0KrfbJNzK4/VwAEAzN+wAJ9Dpbhtq4sRoH3cbadBsD2mXXthOohiBBMR +AgAiAhsDAh4BAheABQJWYt6YBgsJCAcDAgYVCAIJCgsEFgIDAQAKCRBu64H4mBx0 +x2iyAJ4tmLvgNsphsrpKKfDDyV0tzR5FuACeNymltMsgfFyvoueBvji/h+HyObmI +YgQTEQIAIgIbAwIeAQIXgAUCVmLemAYLCQgHAwIGFQgCCQoLBBYCAwEACgkQbuuB ++JgcdMdeDQCfZRUFDCB8sLK6B6wqRmwCsb3EK6MAnjSG6ZtgrdEjSQSmfAcIV/9W +367MiGIEExECACICGwMCHgECF4AFAlZi3pgGCwkIBwMCBhUIAgkKCwQWAgMBAAoJ +EG7rgfiYHHTH1PAAnj/1LWl3pxLYweV1ZClR0i44GJQcAJoCM0+92pI3VIsSMfkY +aUVmOjVzf4haBDARAgAaBQJJt43uEx0gQWNjb3VudCBkaXNhYmxlZC4ACgkQbuuB ++JgcdMcPKQCfX9/AR3wmHBQRa82rFiedGmIqvWoAniXN/YsV4seK5zmvL8wb0qiC +1NydiFoEMBECABoFAkm3jo0THSBBY2NvdW50IGRpc2FibGVkLgAKCRBu64H4mBx0 +x7I5AJ95CfnMCLlo0dO3/9S/O4QtcTBpgACeOSVDaFIJeOfiWFFWpiPkp6NNq6C5 +AQsEQybx0QEIAPjHD/kts6GQbtsV+6+aZgfCK6MVZe14MOXFG60FmnHPzXymorzu +7DxSQOkKiKU49mUklTIQ1ErGIr8nCzjmVHmm7CH53dy8/OklPgpecBLGSP9WiqQ8 +TJxNUiDWQA0r2HWVAsi86N+E3e9ubN4VSK4yd6JMR1Mp2KgyS2LK2PjRo+o7mulO +FaAAoxmi8gWIVR6sv5dkh3g/6/DfKg32U8CWjFp5IXKmkyMPSH5eOZL4eBfx4Ia1 +cFcWfDJZdsYQ+EB+auzHqyr/DS5on4aS72WAppWkwH1Mu/fYnOEY37yF4GwYPb/M +5Loz2wTMxdjfflzCMdfQ56CuMlfc84MeT/MABimJAWcEGBECAAkCGwIFAkl7HCkB +KcBdIAQZAQIABgUCQybx0QAKCRA6sAmW/CamQbh0CADqF4FDBMsQh8+vkhFvXOTQ +vtXkQMuQedryaCGHcS/e5/J0xb5uLybMnnFyh9tIy8cj9sc79yeTTuXSQLJgU02X +h6EL4osGpe5JWWvFbY4SyNkyR3UcpXgzkH80crsHF5ixwCxy7PTEjQ48yT09hig4 +eiDHQ1fS4ox0F5aUQ4q2mk4bNtU6WHEP/8l6BKwSUC9/lfFQmMnk7SeIQqTwgC9T +agPZhCQz/tNZBo+t3ETlRcfPZ2djCGRJm5mbMG/pwEy1L9frdopzBYk56yEpuA97 +HjmIDvt34YbAOlPYPSCsvnhzZdoVrRv/qBcGxNhdYA7zwiGDlrjRf7Rg1KT8izvo +CRBu64H4mBx0x1WDAJUTqjXmf02pQphfYo7qalOuVr1tAJ0UUgg+PXpgrP0lp4LQ +8SbkxvBRhbkBCwRDJvH8AQgAtyi1+vdUzhYos5lmUznkTURFBGWMvPSOnB62I2Mq +0ZAazhyRjb6EuSTuGcusJXPWzRlsUFPdmyQjIqhPJ9ZkUSLOieIBMU4VqgWc7GZX +K7P4Luh8TxQrz5YOtnpj5Hev/yj63ACDLIbzShizBSteZ+TZL+aH7/8XK/36o4rC +Ep5OH69RiPcCUFEHQkxF7vaPdnqyH82/JtUOxSW1zYcr+7XHpHa+UNtI62Q4MV9x +9Wi6vBBvJ6zZSarpVi7ViIf5PVMGuWb5nA1YShEtQVKnQnn6pBqRUF4iLcyrunIL +PGp13htUUahaDr4qWUP5VKmELT9IitOTR0BX6e3E2h6NnwAGKYhJBBgRAgAJBQJD +JvH8AhsMAAoJEG7rgfiYHHTHMuEAnRcN4qTQ1V92e+2RzJm2IYbVJjPBAJwNY6s3 +lbrcC7Zc2E/k5fxwwenSTrkBDQQ7OHVeEAQAl3WryGIZfi9uPLNZlIvRFBErvUKL +zc7n+/c1GaUVMxXcF/Iauegblh41OoV2Kcz1sFx52MLDSDTV1DwDn4fNzwP7DYOe +9h4EBpMePG1DS7LQ0LoD682rvey6Cvww+eFmBBXdiEqCXvPuW4d3WMnOsQqL5BiS +QH+GiwIrLFN7yj8AAwUD/j9FOzif1GLdoSG8fsEi//axq0sXI+NtRUOrvmrkTCG3 +o5rZOJNwz+KBQpP45LdzosO4V/kPVuJ5U4EprEPRqejfSTW+oK+Bgm0mfImgw7Jv +adkNeXfJdwYidutyF1jjroVdqprSjAAaoZgSi2sw03CFx1WkdL+GCccwN6IVl5OI +iEYEGBECAAYFAjs4dV4ACgkQbuuB+JgcdMeqzACfeHjT2PFYdy88PHNVGw5se9Pq +GPYAnArpX32fDdu/xhuqjqHrNkwyO/Yo +=TzkT +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/AD17A21EF8AED8F1CC02DBD9F7D5C9BF765C61E3.key b/build/unix/build-gcc/AD17A21EF8AED8F1CC02DBD9F7D5C9BF765C61E3.key new file mode 100644 index 0000000000..95a04ebe6a --- /dev/null +++ b/build/unix/build-gcc/AD17A21EF8AED8F1CC02DBD9F7D5C9BF765C61E3.key @@ -0,0 +1,57 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQMuBEvtHBoRCACUnk4CbRKM5SsykvTko30oeZqmzDF4bS/usOEcZBjtpudsZBC4 +Po7zfIQAvRyCyEsXtBHCM9KhUNgIbfToDfb9quXvH0KR5D/lcHL3eOHfFPX+Yr34 +ouHj/+2yFQNNrsmEmteOFJVM+zX1KBx2I8XQWDNbnMbEbPj/DdCvsk7+3uoQCepG +bFD07pk7iFb1ny6DXgvM4fItJbY5z7+IQSJCv9blRNy55oCkOdGm1FE4Q/SPgbT4 +quZoec2IxGlFGt9ThUDpuYPcdejyjaC5eFDozhqXwMDh17yBDS53XF6lV02Djs7L +e6QbUJv4B3rqvOGV+eLfRxFuy6X6XEOh8FgrAQCzj7dNslwWI9nTwp5GCr7IO7jz +Ynmw+keMcaOUu0Gd2wf/f/uonF/RVy+Gp+PGHnPhi20xaKZ9unf3l3KWELTpizI9 +Of4R+N9AOpVR4Bf1MgkCV4VH8cpOUQOxQQUEYOpYYYH0EeuDlBItVgvcdG40bnQA +PUwWdqbHUh1cXjD0kGQLv8B2+O31GfnjDQhnNJ5C9KdhKf2sLRkNJtMLU5XsPFMF +qoAW7I0cak2XCuHokiOdJq3bhOX4FdxRGlFPOXNOQA53nYRb0kHv4gfKBHwPJbPT +T3MFgoqO23q+om2cFqwVRTVLW4Cg+Ki5dvFkJrufE/NNaCRuSlj3G2WF5K3OOZct +O7xsDsp5wPMQu1tkuwoZcnp+EmvI8QQkPl722eWf3wf7BFjLCIqi1ivu0GVVMLOM +DMGRZeSkjVrLj1xw5BbWsQ8jOAGvnrqC5zpQoMQLzYyPGb6KzXX8Df1kbQEys7M/ +FoLVIhSE/Elr4e5epNW+8zpmLSW61PlDNraHYHcCxf9RY9aZrxtzEXxdCpPZ+bk3 +8sh4kvAv6XUsmweAu2RRY97u5KNyWkIEhhJJcd96cK6FNc9GeOLCiXQPJqK1ORSj +bCBX8HL1U1r8iOo7Hh+Y25flZ0vRSE/6Fsw1X+seTakelh8EWQtIr+i+oClHgmrT +su9NhhQFFvAUFNdN0K1TcADhfj5nPTImet1x9oAUsU//lOXBFWYhs9sitE879uQs +d7QeQW5kcmVhcyBFbmdlIDxhbmRyZWFzQGVuZ2UuZnI+iIAEExEIACgCGwMGCwkI +BwMCBhUIAgkKCwQWAgMBAh4BAheABQJVWjYMBQkLTk1nAAoJEPfVyb92XGHjOqEB +AJsOI48xKPLh09bAzvzSOqS7H/KR6zWIfvLvu1gDhZVrAP92LZoj7qcgnZ15tY2Y +yqHYHk87zl3vRlMLJXizEz64xIiABBMRCAAoAhsDBgsJCAcDAgYVCAIJCgsEFgID +AQIeAQIXgAUCVqUDRgUJDJkamgAKCRD31cm/dlxh42vPAPoDs4RuOS7YWYM7gKiC +3oNVTTIDKz9foDlOIXUhlWf6dwD/S1ofL5UNLLubCdK3UYNHNj+8r4ynz3YezHaR +MDCTtGmIgAQTEQgAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAldHXPUF +CQ07dFMACgkQ99XJv3ZcYeOc7wD/eE9W2sl2zI6h1LXTA6tVharyhP8cOAtzuuw7 +auZaE3wA/jaKo0HYrSnhrg8bF2zMnf9LQQdPdW99jZNVFIMcnOrniIAEExEIACgF +AlIWO54CGwMFCQlmAYAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPfVyb92 +XGHj9VkBAJe2uRxafZnUWpkTMD2CGg2EQgIP0R4bH3lykKtNKiZ/AQChGBkQWref +Z4eGsXhO205DYKq8TXKmAxuSVYv3UahXXIiABBMRCAAoAhsDBgsJCAcDAgYVCAIJ +CgsEFgIDAQIeAQIXgAUCVVo2GgUJC05NZwAKCRD31cm/dlxh4yb4AP9PxhxI7yE/ +PiCa9hmrl5rvilMGXNBzA80re3+G8un6EgD7BQPdd9hBlC98uC6WtYtB9xFgny3M +mNPpcUM7NHDjdYKIgAQTEQgAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AF +AlalAz0FCQyZGpoACgkQ99XJv3ZcYeMR7gEAlSYGcUywSjjXJ+kjz6n3wddHZFGl +q3Z4zmdVeIJctv8A/R0qGx73rFDNN1aEB36RZmjf6s3OKEtZ+sFNPEXOWwpAiIAE +ExEIACgCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJXR10BBQkNO3RTAAoJ +EPfVyb92XGHjgN4BAKeBkmxrmrSPU9HUDlE7L/ecR7rUlF2Go4ibuDvOWp0BAP9X +wXSHKxDlL2lh/IeiZSqIW09GXBItfQACaeoJz4s4oYiABBMRCAAoBQJL7RwaAhsD +BQkJZgGABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRD31cm/dlxh4zhsAQCf +pbJqrGh6rGBAW1L3jCHNeYt9ughb6wxtlwFclThG/QD/bccAIkDT1lem8Bhf66d5 +sYEx+d27d2rvyBNblP3Urwa5Ag0ES+0cGhAIAI7fBR4UWKVQ8t5A0hPXbOhQkxyt +ztcIRo8rpGGMq//STIa4gBZjuyomkOGss8bElWFYeco09+OqGimD4fDEHXVpD/ev +IYiLq9U2sAUHZaKQAM3vE5LBfWa6zeuQwQj0/t9+cDyNCLTEjPsFQ5AdWyXxxO2c +XetgOHbKwtyjEEsjbJNms6ysjsmXzQGkDRCarGpWrqhAE+jweykpJLoCpCI8AmTv +1/dA5AOcDfsNlTDJnKwWsIaEnvscE4YMwcbCxwHUbhlzzEs8uS7Bk1LaQKQFUcvQ +Bt1nFiHD3uTHZLX5RjL2VTRArQFWN3PefAW1T5Ws+Fs+JwBy/VeKbuBud5sAAwYH +/167fa00yFiCtloWPJ/Xv7Marh/CIpAG0GOuPIJ4IqdEl/ZZ76A0KalUbrSL+fj1 +Eq/0auiNi9CbtlKI8lebn0AkKRYZe9j6JwIHJGomn1hgFhPGMKUToE4iUXmv+ZWN +BbH4iJz87xcrmtV9mLHiVZHGMwMBv5VVSnBoGcxcHHYnC3iAP8h+yaFt4pVIxQXR +NNfbXsUFvZaW2Tgat8knupmxOZfJfdesIf+n1X36OvhsZgFw6rHTSf2mAfkiBl47 +uYbB8v8BR2nDXbtpNlg2ssPbmPIfOE0Ft7pZ5VN1YiNY60w+Sbh5wD0A4mr7OZ/t +2NP0yxDMCLYN3jY5R+P/e4OIZwQYEQgADwIbDAUCV0dd7gUJDTt1RgAKCRD31cm/ +dlxh4xPFAQCXDeJBh1YPVkD8rgFlmMIEtorkzK0tHfCap6j1cG4iFAD/SCXCufA7 +8GOBvibrC/azKvoBKLY1/stpKCrecZdRFkk= +=SDN9 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/D3A93CAD751C2AF4F8C7AD516C35B99309B5FA62.key b/build/unix/build-gcc/D3A93CAD751C2AF4F8C7AD516C35B99309B5FA62.key new file mode 100644 index 0000000000..21cd94ec1d --- /dev/null +++ b/build/unix/build-gcc/D3A93CAD751C2AF4F8C7AD516C35B99309B5FA62.key @@ -0,0 +1,62 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBF7Ps4YBEAC5i0PA1CA3te8UeAxWm8zH5KRyoXyD+IuVHar9fPR13J/IkUgO +0f4kebDaGQGjyPoBuLHWtshQwSjDP9059eMbfne6fhe3UxqRjfknWxr83S0pSrDI +xgdIsxMQT6dxm1YYpp+pK6PRs/tHMtXHtSJc4HwkW187nx7c7lfKXmwVoqUuEjvW +irKyJRVNw68WZjYLmmIsRIIZcUMOE2lItPkejerHZobOuTkuXslgkWH3zeKCK8JD +em9npzxIkLgrl8Ub0HxWdkAc6o+gj3Ih0QthvC8P7gxNuTJyf8SVaZFla+ky/t7Z +kLmIhSBLzNSosscOtz9sdI4seXsOGgWeGRORp/+zF5ISnD3kFg3OtIudW8p4J7oA +OICWkPIuEOXPCz5VIUmaY2Eswh76YgW7u60JMv/v0Agpjy23hovvG6HArMO8Letr +Y5CWC+G9wp/xTo3TeyQ9mrYcKMjvrZzCos+SFaGF0lcExWpk610XQf+8/1FlhJ4U +SiQCy78o1pW8dOpLWvWe7y9YtRm3DTgYDCDpcMzYVZPrp2oPg5h4nW5sfhPJ01yu +gwTLDo/AILMQSkr1IVbfMkP7Mxtev51nRjxL7JCMB4bHx+uyNs56LCqdLctrF6Aa +HrS7yaP3ym3BsHrH3TqAaTGW7rs/hrZ6MaWbU4bBxL49z4GyXWRJqglePwARAQAB +tCBKYWt1YiBKZWxpbmVrIDxqYWt1YkByZWRoYXQuY29tPokCOAQTAQIAIgUCXs+z +hgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQbDW5kwm1+mJqRxAAtvq9 +NevjleUPVMJhz3X5pprhCNM/8LGSbhE284tDYv0inT9huKaMeaw/hQvSSoniac87 +zb0S5JDWYHEZ6PhOs7ZASuSwtBp3SdGtjQTMJMSuAHvEjSvBR+0EkCu+85oJxwDS +wMMNEy1xubsyqhETD6DF/wudDr5r8IpB0A4vzFmaFv5wdbdnywd/sQzU9Fnl7GyX +/1Wgd94dIiznr7fdxJtsdphw4WzoJf5EYTdozs+biVhnz+NJuniTjg8IKoEOl7oY +Nrmqwfijw7FqgcbuXb9UAsxaVLFHZl3GVhXAmbQoz4io3PVw5BR+p+zeWvndeONu +jndE8QN3PyFb/WHyWRnCv7goUb5uLZU4aDqf34PP8fral3HBaaaXB53NybvJVjEU +nMzvjpVQj4J0yFzy+NlFwJb3oT03EDNkEK+SQrKHv4xz/atgXbfFYZ8oynCkypmt +aw/udPuLpy2dBY6wTAhSvdzkiD9swgbgX2idNLXfoeU1AaiKd+mez3X51Arf49pn +nL5wDCBkT2BUwX41ntIGgrNMcMNFbfNt99kUNaZ15oWI9Ia3DyWMxvgmDg4Ev8m8 +pGHH3Hq3eueyPySdJh+I8x+ipyIpFW+7AYS49L4LI7A7jFs8Nas22Qi6RoTFV3ep +0qkEL4Lgrh8ooxhhSLOmsfyJDiXAHiz5sVUZ4wWJAjgEEwECACIFAl7PvJYCGwMG +CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGw1uZMJtfpirV0P/jBD7DrOCdCt +AgS4F9uUM9MtR4uBvp+8dVuaGX37fMr8W5rDE+wYzBiYeIzc3UJ3QG2Nuh+VN7OT +rZS9cNpDKre2+/6PQT4y/p3SI7o4JEqzoecWlITwWy2hpoYmEs47y7F6L0RpeNQ/ +sJ3hQydx+X6JxXe/IB+ftpOWpO5oGIDrdBoU3hBTcQYL9TjDMWSfmoiIgKTBVbXO +Ktsy1sc0TcjHk1ACoSj08+Q8+Swq56cd/dXuIMfaU6mNuJgA1UUaw7T+2HYLDAz9 +J10ak28kbHP9MHFHZff3M1Ub80gAwmaJ96u4G+2q9yX6/+QhXTf9gEF8PyBKpBd6 +Uk/dNLPtVjGYTjkPxQ7fyehE7KunC9uPOze0AEnhnxe3HM1TikFNbbAYaZNlqsXt +HPCp7ATfCpautoNarO7CfFer77OuECzoLHpDNXqesPZ+/WeZsURtik2MoNN0to3h +CZJQBptcBQ4CAy+5LlWKZURU0Cxu2GkSNSM0YuiQnmKReLZbzX4Rrr7c1/AAx5Ps +mG55LIF4sSygbWPvY6kBL7XEhvMa6x3B4+pELNCJUUSgp4aW3oL3u05DQWVJDgZd +t+XPP2DTiEgFtZbOS6sXdqpPY5/fC+69HU9spcmEdaVCJeIOICy+sDfFTOTv0Tcq +XD7TIZko4pKA97L4lzekQENFcni9/YHkuQINBF7Ps4YBEAC4rhogalczpaUmgnMD +kRGpv7WFgpv96PQBKCoWfFTTsB8vW0Ge0J7ctOGevOjRqupDnNK1ycTuXUnqogOD +n4ZpKYoXg9xoBCmrlXAjdRA7Z9GG9Pv5SVgah4lwGvoWhFDbEZGXWywGggWOmht0 +vGPYUm9Xam3nfUKA3QuQ5Y6pUyVM0W0C93xQZbGHo7VkzVlBz/TnXlEyM3Twn9oh +DTKPj2GRty8cnMEDM2tEw85rlUi0WwWMS42MM41aIiO0WL1fmhbNh2UoLQND9gZg +vqY5Xnkn1nh4jQGcTx+krXm/EzDi/wMnS6zHBp45XkRHKNWFDS/IaNs1AL9Ifkt2 +8xoW+4LZDsVc7uhtRB6H5Uwq8HbAH3gPFggWTPii6iyXJ/OXoR+/zdGQcv2OQbu+ +iYrWDvwyb6gEeo0okdnyQUC4khAt0jr4VsCRGHsTViN3kqQ2L8XY0N97Rc+kE1B5 +3on7NWgcpejB9FsUQ2LKSLNXO1+mn6iFq1VLF5o4fyE9fIRjhHVQ2fJLStVNmnUD +99jpmXUOYo/OmHcsqa/XMByve+lXbbUSzSrOyhJRXpqZB7XXu7nvl8pa83jGEI9T +JrcOG2i/I8YOAB5pNOlN1RGk+z0CCaYWTMCzHrN4ZOHuO29wvGnggAGANbH5muKw +lPIU26wKEleaoQwg20WYgIRdAQARAQABiQIfBBgBAgAJBQJez7OGAhsMAAoJEGw1 +uZMJtfpiKzcP/izcvGB0oVTvhLkHomtxNHFbuv6gsjP1HYwn2kmB/TcEJXR1G3ne +9CGO9jKmH5PrKk6B7BmggKEnnwkkS7BC0O7ADLH6r8DW/HYmzjeqvSbuSRElMLuL +cZlZS5ZFxZcsYJP303gU0/PcE+2WF40lWu+VkQw8CaPASydTe9ulMVQ3FJuheBm/ +npWjItI1RgpSlRv2Ry4FkZXyuPHadWtgj66r0QHhr56skMuKulLVdRXMGJcc5dxt +rmwfGI5UINRRuwqEn4Bz2RWfnz7Qr1t5FI3kzmZQ0PFDRLMr1LcC/p7SgqSsMUXQ +BS1m31YJdR0bXCtHl0H/jXqZ+fpUYDUX1JcxSJ2FJJ9EBBSUEIAJncbkFS7rS84H +IcUfeDAa+nNfI4bvveaqCiHzaXkmjqcQ2cfVqpzArAZp7PmCpnWhWo+TLpMz1yEM +cOqPRM/gID2PVUZiA72iv9ASa4Fv3XhRnBddrTB82kOPiLe3onQ3s2J+glqr0QF+ +OcKVuYoOxlF5uV6fDEqvR1B6b8UhEg2qPfekIH0epRSe2CMvnEHAkucpx3CZKZyx +nUtBvFMzeImE/swLJzsmzaxExcRT7EwHXbvXPrDo0VB1BfK/ZBkGd3isQqd6zXxC +1FU48hr9sjqbp/mdcRwHiyKuTBKuDwcSic/+06T28Z+qcFGkqy3SQZF6 +=3+NJ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/DA23579A74D4AD9AF9D3F945CEFAC8EAAF17519D.key b/build/unix/build-gcc/DA23579A74D4AD9AF9D3F945CEFAC8EAAF17519D.key new file mode 100644 index 0000000000..1b658e615b --- /dev/null +++ b/build/unix/build-gcc/DA23579A74D4AD9AF9D3F945CEFAC8EAAF17519D.key @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFY4SBYBEAC11sh4AMhIhiLxj76FXsluVJIU4nZjVmexar+/5WMlVvMX+Dxk +lUbKDCBOUMtPFsAXMpcxOGwscCr3WMuI8WszTjKDs3mdQ37o/pzXMbRhY0oZV29Z +EhNLds14qhMLlQiDEm5lJ5bOsLevHJ9hR4wvwY6UR881xsiXsNU+iNMRP0cWeRjQ +84pSCLOt9i+D8rdllVob871gN/tjY4Ll13Tg7qmtFE1YEFJaLb2yik0bO7gPkig/ +ADmKMBhOtgAHU9i+gmtP+x+agk7cbXkR06Pd9VBkd9nYlFXbR+zcE15AqauEF1Y2 +V9RbW/Ewt4Fmgr+QQnJhiSMO2BUTS2Q0CC3LznB9QOdEriUmeXGJdim0OJiwYDDX +4CNRk+2CAePbrZnGv+YXgeNPHvFa0Baj73HP8Ptok+OeyWIenRPHG3Ni+O5p1n5k +QK0bHqIwChMtAJvzdoC77XIJhbCtStmvo2FdSA8YcG4stlz+Wk1ZtNMen83ZEscS +OXEVpxcPGlbmWmkWj8DF5zbB1dRdh4T6LLM4nZViBu7oGD76z3c/x2zc7l3pyVHx +Cw70a+r+6LvUwnvCiApCBS72uDc4zZtnkNUQHlXHkz9wEeYUtUB0wkCYWPZy7BZy +0aFfKWK4Jg7uGx/mdHRCJ35MdXWxeQ4yPUE+tF951s167ANr1+ayt87pQwARAQAB +tChBbGV4YW5kcmUgSnVsbGlhcmQgPGp1bGxpYXJkQHdpbmVocS5vcmc+iQI3BBMB +AgAhAhsDAh4BAheABQJWOEvIBQsJCAcDBRUKCQgLBRYCAwEAAAoJEM76yOqvF1Gd +UqkQAJw6ot97efCon6qMA7ctJTqhOvnPSxf430aZgaTuNBEfY3RPeWC+k11cTvKV +dny9xwC+N8U2Jfdd0iXqlwUdM4ThOKZCXGOykCHJmrYGPqWsjGKUO7EoMwJB00qi +nOJdgj7zWLb6MuuKx2eavGYVLCFG4sQ8fjX0+sxuD+Cl++UyS9+t/C3ijeXTxaZn +qSLFKUFzyngXIUhFxMLkUdh397WeTaBtUTyLT0lwOKTllxIyC/+t2e9QcfgdLE/q +wKmRjihNq6I5JOQfO8JynUoR8WzKQaCX5VL6ZPaQa8ZzUdS/h0WlMlQuD5mrcDBa +ZQjqPEIL6/oExk1a7yeQFKNKisq94rVF0Ly1o7w+n+7X4lT9T9zhiPKVXvlxHB0h +SeJm4j/qDq1DSiGVfIR2CChObyeHAZhQZMMr/Ni9XtqzHsd2qhcP1ZYvbQZ2UK/N +Lv398VY/f+kXApFMDQLj1jGA8aXbkE8ChIAiZAAzVMg2wJ2x5/7bImbICsvGSwfx +awlsHzc7CR0Pj2Kdgr7UtsDk+cBRQMEqAIGWiCOKnBD8eoNGaiCoLHI/3ce4dJ/y +pXFtJSkJa8wpK4+xdckAvtPQZgOV5gLCJqNqEF+8aIjsTwwu7dcIXG2qLHD5C5tq +viuZtOYO7UdQbIHuYY5Xy8/W7hQRfIaq1NfKf9qJx4hrCWLviEYEEBECAAYFAlY4 +S3QACgkQ9ebp7rlGHdcg6ACfXNdYTmPe1Ej0rd+eO+yuDF/kwccAoItuIMi7EXu0 +FR4Ui8cBaZI3hweFuQINBFY4SBYBEAD7ZonYuSKxToJ4plL22rv4wPPbqACcLbIG +5t3s/Gb3/twOtaCgOEFhzNv+8K87jX6iSHJYeGhu7e2eRxeGHkrqliNJoHUi9Ddu +ygHqhoNmSHNSqI36/TU5yCRArKS3wwq7cafGnncdVOLBYfj497IxGK8fANhDf7TV +vqUGIb06gkpWbrwmUWgV8pk7MHgL93T5Ph+KSgdEbOSePFwQb9piyp9vWNmZnqK2 +9TFNtTULGtQa0y8ZCNSSEh4YP/DxDraq1OJ2Gh3WHSQ4f2hfGXJMzr4cyIrOJHQ8 +mby6xHmvldsAGsZJ/CSMj27UhJJYOzNCxWOp9NBNARB/6N1Ikvv9Vs6G7lZ4Dmuk +wvAWqzlomO/ctt0XmvY7N7ddIviDCQ0Z5bGJQlOWuIBR04tt7CePNzxG91q8x7FN +P8r+BSvxtGheeFiQYsC5FINYWUelL/SU8/U9sG30YLpujvjB5mqYZJtmotSqFbwl +81/bLU170OdG9n7FWp09f9yB1KlSq3hSwKBKu2bGUy2sS6w5MqEtxBHVUjLlS9oP +GQK+wr1m70rgfK/2N3HdcSqr2e2aKxnCx5wDvqB19Zq0TX5CXobEy3ohnul3Ez7a +2HBq543rdZpS9xuF2IHK6zMn5Xv0WKrODxIOnjs1mKbQzP5/6PVOejH/AnO38pCb +hoj0/zvnKQARAQABiQIfBBgBAgAJBQJWOEgWAhsMAAoJEM76yOqvF1Gde00QAJMF +OZhnPeiDFigLsqiqPGQzqSlZ5r4rQ3t6txfBYDclTq3rMqmk75bxteZHpSgMvdHF +SgqrvcyCJP5F8IRbk+J/tUb10icnl7+vsb6PfNXXflX0cIeAC9yqB3Z6RO77NoMy +HzMlw4EcNUXdmC46s+h6y74BeWWLBwYR18XgTSuw3gYpL7P0lqM2d7H6HCQMkZD/ +on9pT3lOc5k9YeM+B+Ak0nDyJGrdj6EES/ukrmq/szJhx+2zMbKU6Ds/uIRE0zuS +VUPnCy+3KPuJk+xLWtuVD2v2G0PXBrKKcgLfQzTQeGT5R/8rTt2w3ah4dXYRG5Ad +N5fIaTfjJTZGmht3pvHuucoloqMWl6DD7a3XZjWtUBMhPboAZiCmXiBWn3c26ITu +N9j4gSpl3hbWYJXjTWocGs2YyiuMRsO6Minfz5l2/iZjp8xHJ8GajuLGQES7CwGH +uShQ0hknHZmrH0d6xOhD64czgmTI2HraujWz+u31sHM1yEJgQKAtEL2AKWGSadly +/eI2rCQDEn6mIe34I04SPr/XrTpFClmUBbZBBir7KMRhB8B9ERdJElbtb4ubGZ0D +FCYpueJgVv9agvV2ONVb/K0BIevJy9v5+FbSFIQG/spkwf/71olib93iUr9tKTaE +mOMR1xJlCiQvAQYsmqwM9FHDmGJYTQE1WbVZu4gZ +=6vF7 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/EAF1C276A747E9ED86210CBAC3126D3B4AE55E93.key b/build/unix/build-gcc/EAF1C276A747E9ED86210CBAC3126D3B4AE55E93.key new file mode 100644 index 0000000000..13ea6d69ec --- /dev/null +++ b/build/unix/build-gcc/EAF1C276A747E9ED86210CBAC3126D3B4AE55E93.key @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBEj3S14RBACUE+e2hRWwM6AFWaNKsLgDg6ebDNCI6z/Pk38t6JUeM+D5MAvq +fnL45bF/3CUrZRK+/qLg5iwRWehKh08VQ7GqDxMerZkPmfvirVxLwpc5ngCOGJwv +ba13xdaxfTLMkHxaQyGWiUqHIwdzFoNBgjq9XTY0GGqHwVA1Hb+xTAL8PwCg+wru +41p/aOq9cfPN1U1BjulWCSMD/2YP23pI19o9Hr26ltyJcd/xkSRiCUk84efIw5JH +7QlxoMoW/SdJQAGi2pZN9o4I/fPDB3Gna9M9rZfacKda857dwkALPK8xTsfHiZzH +40g+eYUvl9nloNidneSFcxbLO/euURcCJ6Ri6nb4QWWLVH1XF6wQxEGyn7ojYMOn +ihlkA/9KATtSt+T0zgWskqckgV1ZQg9Ysqwp3GAvezJuyUTXlB02ApVFEsRTQtLZ +2WPvo/gzfih/EdNLrq7UeeB4dr/nlpANn4IyBRN6EmBHaJ4MMKN77B7bB0GaBfGJ +rgNNp7W0xG0FLjaMoQzP62qqAtZHNlW1qCmkyJGUpAa6tJw9CbQlVHJpc3RhbiBH +aW5nb2xkIDxnaW5nb2xkQGFkYWNvcmUuY29tPohgBBMRAgAgBQJI90teAhsDBgsJ +CAcDAgQVAggDBBYCAwECHgECF4AACgkQwxJtO0rlXpMVcwCgoQ91OLI+m2bsu2SS +d5MsRQH3FWsAnRFG2YGk5o5zuoLzdZd6KlL9xJ+uuQINBEj3S2MQCACnDo5dHujc +u7QHRPnxNwiKhMP6eIZaEm9tavab3UxsRufMyVC8nQ8+EmCOwfBrqstfRVoQnoDI +s5UY1XAM3mBFXYqfY9wR6NISUlzK/HPyFhGE7t3lVjOkiqbWOftDt6GgRETeqYsW +XkDV/dL4+P3eSaOSP6KMZwdjgXPOciN59KIiii9NK4icxP0lJHDk5WJFwfucEyUt +Sz7uwuUFcajHZmMxxHAnWT3uJ+ZasSijduZevsHhKTTXaZRideqf+ur1/TcUaZDQ +O3wist1qc03NkL+oGu6HYPx9ZV40p/axdTaUXMcBjtAZIzvy984HF9EsFQnvbiXt +R8zg6SYXLRmbAAMGB/9JMKWsCuxUzXmU1jyJvMXdRBZ4YQYkKFYWrEXwjYlBEGx6 +01PkR//4QJVR4zFjy4zVnaUrOxtR+65Eedf+9fNZzSNeI24TGaqyVM0OYYQtp9cH +kRDu3wif1k2NW3BnrmTjVefdAWVH6zKT9lP9m6RPHCwVGyORhVQtB3+ZXOehNJwL +9NBU4MUpGKpoQCuODdgZ8iQXbo+plg0eCxcpNaYzSnq9DMAU+2qnP6d3x4DeWzlL +wvJ2K2Mw89gvCImy/JDe05EXqKowR6aiIPvw5ou9xSHmjT6rcaIBiROCe+1hh4XC +djCdb4kOskWCEXfFKcHax4N5fI9vmk3P5068BELMiEkEGBECAAkFAkj3S2MCGwwA +CgkQwxJtO0rlXpNxdwCgjr4sQRf2cyDkCSWe4AElbI74BREAoPdet3XvE6ZcZJGl +UIZySRkdpk/A +=dGh0 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build/unix/build-gcc/build-gcc.sh b/build/unix/build-gcc/build-gcc.sh new file mode 100755 index 0000000000..0a27af1ecd --- /dev/null +++ b/build/unix/build-gcc/build-gcc.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +set -e +set -x + +make_flags="-j$(nproc)" + +apply_patch() { + if [ $# -ge 2 ]; then + pushd $root_dir/$1 + shift + else + pushd $root_dir/gcc-source + fi + patch -p1 < $1 + popd +} + +build_binutils() { + # if binutils_configure_flags is not set at all, give it the default value + if [ -z "${binutils_configure_flags+xxx}" ]; + then + # gold is disabled because we don't use it on automation, and also we ran into + # some issues with it using this script in build-clang.py. + # + # --enable-targets builds extra target support in ld. + # Enabling aarch64 support brings in arm support, so we don't need to specify that too. + # + # It is important to have the binutils --target and the gcc --target match, + # so binutils will install binaries in a place that gcc will look for them. + binutils_configure_flags="--enable-targets=aarch64-unknown-linux-gnu --build=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu --disable-gold --enable-plugins --disable-nls --with-sysroot=/" + fi + + mkdir $root_dir/binutils-objdir + pushd $root_dir/binutils-objdir + ../binutils-source/configure --prefix=${prefix-/tools/gcc}/ $binutils_configure_flags + make $make_flags + make install $make_flags DESTDIR=$root_dir + export PATH=$root_dir/${prefix-/tools/gcc}/bin:$PATH + popd +} + +build_gcc() { + # Be explicit about --build and --target so header and library install + # directories are consistent. + local target="${1:-x86_64-unknown-linux-gnu}" + + mkdir $root_dir/gcc-objdir + pushd $root_dir/gcc-objdir + + if [ -d $MOZ_FETCHES_DIR/sysroot ]; then + EXTRA_CONFIGURE_FLAGS="--with-build-sysroot=$MOZ_FETCHES_DIR/sysroot" + export CFLAGS_FOR_BUILD="--sysroot=$MOZ_FETCHES_DIR/sysroot" + fi + ../gcc-source/configure --prefix=${prefix-/tools/gcc} --build=x86_64-unknown-linux-gnu --target="${target}" --enable-languages=c,c++ --disable-nls --disable-gnu-unique-object --enable-__cxa_atexit --with-arch-32=pentiumpro --with-sysroot=/ $EXTRA_CONFIGURE_FLAGS + make $make_flags + make $make_flags install-strip DESTDIR=$root_dir + + cd $root_dir/tools + ln -s gcc gcc/bin/cc + + tar caf $root_dir/gcc.tar.zst gcc/ + popd +} diff --git a/build/unix/build-hfsplus/build-hfsplus.sh b/build/unix/build-hfsplus/build-hfsplus.sh new file mode 100755 index 0000000000..5d3417e63e --- /dev/null +++ b/build/unix/build-hfsplus/build-hfsplus.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# hfsplus needs to be rebuilt when changing the clang version used to build it. +# Until bug 1471905 is addressed, increase the following number +# when that happens: 1 + +set -e +set -x + +hfplus_version=540.1.linux3 +dirname=diskdev_cmds-${hfplus_version} +make_flags="-j$(nproc)" + +root_dir="$1" +if [ -z "$root_dir" -o ! -d "$root_dir" ]; then + root_dir=$(mktemp -d) +fi +cd $root_dir + +if test -z $TMPDIR; then + TMPDIR=/tmp/ +fi + +# Build +cd $dirname +# We want to statically link against libcrypto. On CentOS, that requires zlib +# and libdl, because of FIPS functions pulling in more than necessary from +# libcrypto (only SHA1 functions are used), but not on Debian, thus +# --as-needed. +patch -p1 << 'EOF' +--- a/newfs_hfs.tproj/Makefile.lnx ++++ b/newfs_hfs.tproj/Makefile.lnx +@@ -6,3 +6,3 @@ + newfs_hfs: $(OFILES) +- ${CC} ${CFLAGS} ${LDFLAGS} -o newfs_hfs ${OFILES} -lcrypto ++ ${CC} ${CFLAGS} ${LDFLAGS} -o newfs_hfs ${OFILES} -Wl,-Bstatic -lcrypto -Wl,-Bdynamic,--as-needed,-lz,-ldl + +EOF +grep -rl sysctl.h . | xargs sed -i /sysctl.h/d +make $make_flags || exit 1 +cd .. + +mkdir hfsplus +cp $dirname/newfs_hfs.tproj/newfs_hfs hfsplus/newfs_hfs +## XXX fsck_hfs is unused, but is small and built from the package. +cp $dirname/fsck_hfs.tproj/fsck_hfs hfsplus/fsck_hfs + +# Make a package of the built utils +cd $root_dir +tar caf $root_dir/hfsplus.tar.zst hfsplus diff --git a/build/unix/elfhack/Makefile.in b/build/unix/elfhack/Makefile.in new file mode 100644 index 0000000000..d5e58efa67 --- /dev/null +++ b/build/unix/elfhack/Makefile.in @@ -0,0 +1,46 @@ +# +# 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/rules.mk + +ifdef COMPILE_ENVIRONMENT +ifndef RELRHACK +test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX): %$(DLL_SUFFIX): %.$(OBJ_SUFFIX) elfhack + $(MKSHLIB) $(LDFLAGS) $< -nostartfiles + @echo === + @echo === If you get failures below, please file a bug describing the error + @echo === and your environment \(compiler and linker versions\), and + @echo === provide the pre-elfhacked library as an attachment. + @echo === Use --disable-elf-hack until this is fixed. + @echo === + # Fail if the library doesn't have $(DT_TYPE) .dynamic info + $(READELF) -d $@ | grep '\b$(DT_TYPE)\b' + @rm -f $@.bak + $(CURDIR)/elfhack -b -f $@ + # Fail if the backup file doesn't exist + [ -f '$@.bak' ] + # Fail if the new library doesn't contain less relocations + [ $$($(READELF) -r $@.bak | wc -l) -gt $$($(READELF) -r $@ | wc -l) ] + +test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX): DSO_SONAME=$@ +test-array$(DLL_SUFFIX): DT_TYPE=INIT_ARRAY +test-ctors$(DLL_SUFFIX): DT_TYPE=INIT + +libs:: test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX) + +.PRECIOUS: test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX) + +ifndef CROSS_COMPILE +dummy: dummy.$(OBJ_SUFFIX) + $(CC) -o $@ $^ $(LDFLAGS) + +libs:: dummy + # Will either crash or return exit code 1 if elfhack is broken + LD_PRELOAD=$(CURDIR)/test-array$(DLL_SUFFIX) $(CURDIR)/dummy + LD_PRELOAD=$(CURDIR)/test-ctors$(DLL_SUFFIX) $(CURDIR)/dummy + +endif +endif +endif diff --git a/build/unix/elfhack/README b/build/unix/elfhack/README new file mode 100644 index 0000000000..8c68031e33 --- /dev/null +++ b/build/unix/elfhack/README @@ -0,0 +1,28 @@ +Elfhack is a program to optimize ELF binaries for size and cold startup +speed. + +Presently, it is quite experimental, though it works well for the target +it was created for: Firefox's libxul.so. + +Elfhack currently only does one thing: packing dynamic relocations ; +which ends up being a quite complex task, that can be summarized this +way: +- Remove RELATIVE relocations from the .rel.dyn/.rela.dyn section. +- Inject a small code able to apply relative relocations "by hand" + after the .rel.dyn/.rela.dyn section. +- Inject a section containing relocative relocations in a different + and more packed format, after the small code. +- Register the small code as DT_INIT function. Make the small code call + what was initially the DT_INIT function, if there was one. +- Remove the hole between the new section containing relative + relocations and the following sections, adjusting offsets and base + addresses accordingly. +- Adjust PT_LOAD entries to fit new offsets, and add an additional + PT_LOAD entry when that is necessary to handle the discrepancy between + offsets and base addresses, meaning the section offsets may yet again + need adjustments. +- Adjust various DT_* dynamic tags to fit the new ELF layout. +- Adjust section headers. +- Adjust ELF headers. + +See http://glandium.org/blog/?p=1177#relocations for some figures. diff --git a/build/unix/elfhack/dummy.c b/build/unix/elfhack/dummy.c new file mode 100644 index 0000000000..2cde16102e --- /dev/null +++ b/build/unix/elfhack/dummy.c @@ -0,0 +1,7 @@ +/* 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 __attribute__((visibility("default"), weak)) int print_status(); + +int main() { return print_status(); } diff --git a/build/unix/elfhack/elf.cpp b/build/unix/elfhack/elf.cpp new file mode 100644 index 0000000000..b2a21e4901 --- /dev/null +++ b/build/unix/elfhack/elf.cpp @@ -0,0 +1,935 @@ +/* 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/. */ + +#undef NDEBUG +#include <cstring> +#include <assert.h> +#include "elfxx.h" + +template <class endian, typename R, typename T> +void Elf_Ehdr_Traits::swap(T& t, R& r) { + memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident)); + r.e_type = endian::swap(t.e_type); + r.e_machine = endian::swap(t.e_machine); + r.e_version = endian::swap(t.e_version); + r.e_entry = endian::swap(t.e_entry); + r.e_phoff = endian::swap(t.e_phoff); + r.e_shoff = endian::swap(t.e_shoff); + r.e_flags = endian::swap(t.e_flags); + r.e_ehsize = endian::swap(t.e_ehsize); + r.e_phentsize = endian::swap(t.e_phentsize); + r.e_phnum = endian::swap(t.e_phnum); + r.e_shentsize = endian::swap(t.e_shentsize); + r.e_shnum = endian::swap(t.e_shnum); + r.e_shstrndx = endian::swap(t.e_shstrndx); +} + +template <class endian, typename R, typename T> +void Elf_Phdr_Traits::swap(T& t, R& r) { + r.p_type = endian::swap(t.p_type); + r.p_offset = endian::swap(t.p_offset); + r.p_vaddr = endian::swap(t.p_vaddr); + r.p_paddr = endian::swap(t.p_paddr); + r.p_filesz = endian::swap(t.p_filesz); + r.p_memsz = endian::swap(t.p_memsz); + r.p_flags = endian::swap(t.p_flags); + r.p_align = endian::swap(t.p_align); +} + +template <class endian, typename R, typename T> +void Elf_Shdr_Traits::swap(T& t, R& r) { + r.sh_name = endian::swap(t.sh_name); + r.sh_type = endian::swap(t.sh_type); + r.sh_flags = endian::swap(t.sh_flags); + r.sh_addr = endian::swap(t.sh_addr); + r.sh_offset = endian::swap(t.sh_offset); + r.sh_size = endian::swap(t.sh_size); + r.sh_link = endian::swap(t.sh_link); + r.sh_info = endian::swap(t.sh_info); + r.sh_addralign = endian::swap(t.sh_addralign); + r.sh_entsize = endian::swap(t.sh_entsize); +} + +template <class endian, typename R, typename T> +void Elf_Dyn_Traits::swap(T& t, R& r) { + r.d_tag = endian::swap(t.d_tag); + r.d_un.d_val = endian::swap(t.d_un.d_val); +} + +template <class endian, typename R, typename T> +void Elf_Sym_Traits::swap(T& t, R& r) { + r.st_name = endian::swap(t.st_name); + r.st_value = endian::swap(t.st_value); + r.st_size = endian::swap(t.st_size); + r.st_info = t.st_info; + r.st_other = t.st_other; + r.st_shndx = endian::swap(t.st_shndx); +} + +template <class endian> +struct _Rel_info { + static inline void swap(Elf32_Word& t, Elf32_Word& r) { r = endian::swap(t); } + static inline void swap(Elf64_Xword& t, Elf64_Xword& r) { + r = endian::swap(t); + } + static inline void swap(Elf64_Xword& t, Elf32_Word& r) { + r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t))); + } + static inline void swap(Elf32_Word& t, Elf64_Xword& r) { + r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t))); + } +}; + +template <class endian, typename R, typename T> +void Elf_Rel_Traits::swap(T& t, R& r) { + r.r_offset = endian::swap(t.r_offset); + _Rel_info<endian>::swap(t.r_info, r.r_info); +} + +template <class endian, typename R, typename T> +void Elf_Rela_Traits::swap(T& t, R& r) { + r.r_offset = endian::swap(t.r_offset); + _Rel_info<endian>::swap(t.r_info, r.r_info); + r.r_addend = endian::swap(t.r_addend); +} + +static const Elf64_Shdr null64_section = {0, SHT_NULL, 0, 0, 0, + 0, SHN_UNDEF, 0, 0, 0}; + +Elf_Shdr null_section(null64_section); + +Elf_Ehdr::Elf_Ehdr(std::ifstream& file, unsigned char ei_class, + unsigned char ei_data) + : serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data), + ElfSection(null_section, nullptr, nullptr) { + shdr.sh_size = Elf_Ehdr::size(ei_class); +} + +Elf::Elf(std::ifstream& file) { + if (!file.is_open()) throw std::runtime_error("Error opening file"); + + file.exceptions(std::ifstream::eofbit | std::ifstream::failbit | + std::ifstream::badbit); + // Read ELF magic number and identification information + unsigned char e_ident[EI_VERSION]; + file.seekg(0); + file.read((char*)e_ident, sizeof(e_ident)); + file.seekg(0); + ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]); + + // ELFOSABI_LINUX is kept unsupported because I haven't looked whether + // STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing. + if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) && + (ehdr->e_ident[EI_ABIVERSION] != 0)) + throw std::runtime_error("unsupported ELF ABI"); + + if (ehdr->e_version != 1) throw std::runtime_error("unsupported ELF version"); + + // Sanity checks + if (ehdr->e_shnum == 0) + throw std::runtime_error("sstripped ELF files aren't supported"); + + if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS])) + throw std::runtime_error( + "unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)"); + + if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS])) + throw std::runtime_error( + "unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)"); + + if (ehdr->e_phnum == 0) { + if (ehdr->e_phoff != 0) + throw std::runtime_error( + "unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0"); + if (ehdr->e_phentsize != 0) + throw std::runtime_error( + "unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0"); + } else if (ehdr->e_phoff != ehdr->e_ehsize) + throw std::runtime_error( + "unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize"); + else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS])) + throw std::runtime_error( + "unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)"); + + // Read section headers + Elf_Shdr** shdr = new Elf_Shdr*[ehdr->e_shnum]; + file.seekg(ehdr->e_shoff); + for (int i = 0; i < ehdr->e_shnum; i++) + shdr[i] = new Elf_Shdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]); + + // Sanity check in section header for index 0 + if ((shdr[0]->sh_name != 0) || (shdr[0]->sh_type != SHT_NULL) || + (shdr[0]->sh_flags != 0) || (shdr[0]->sh_addr != 0) || + (shdr[0]->sh_offset != 0) || (shdr[0]->sh_size != 0) || + (shdr[0]->sh_link != SHN_UNDEF) || (shdr[0]->sh_info != 0) || + (shdr[0]->sh_addralign != 0) || (shdr[0]->sh_entsize != 0)) + throw std::runtime_error( + "Section header for index 0 contains unsupported values"); + + if ((shdr[ehdr->e_shstrndx]->sh_link != 0) || + (shdr[ehdr->e_shstrndx]->sh_info != 0)) + throw std::runtime_error( + "unsupported ELF content: string table with sh_link != 0 || sh_info != " + "0"); + + // Store these temporarily + tmp_shdr = shdr; + tmp_file = &file; + + // Fill sections list + sections = new ElfSection*[ehdr->e_shnum]; + for (int i = 0; i < ehdr->e_shnum; i++) sections[i] = nullptr; + for (int i = 1; i < ehdr->e_shnum; i++) { + // The .dynamic section is going to have references to other sections, + // so it's better to start with that one and recursively initialize those + // other sections first, to avoid possible infinite recursion (bug 1606739). + if (tmp_shdr[i]->sh_type == SHT_DYNAMIC) { + getSection(i); + } + } + for (int i = 1; i < ehdr->e_shnum; i++) { + if (sections[i] != nullptr) continue; + getSection(i); + } + Elf_Shdr s; + s.sh_name = 0; + s.sh_type = SHT_NULL; + s.sh_flags = 0; + s.sh_addr = 0; + s.sh_offset = ehdr->e_shoff; + s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]); + s.sh_size = s.sh_entsize * ehdr->e_shnum; + s.sh_link = 0; + s.sh_info = 0; + s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8; + shdr_section = new ElfSection(s, nullptr, nullptr); + + // Fake section for program headers + s.sh_offset = ehdr->e_phoff; + s.sh_addr = ehdr->e_phoff; + s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]); + s.sh_size = s.sh_entsize * ehdr->e_phnum; + phdr_section = new ElfSection(s, nullptr, nullptr); + + phdr_section->insertAfter(ehdr, false); + + sections[1]->insertAfter(phdr_section, false); + for (int i = 2; i < ehdr->e_shnum; i++) { + // TODO: this should be done in a better way + if ((shdr_section->getPrevious() == nullptr) && + (shdr[i]->sh_offset > ehdr->e_shoff)) { + shdr_section->insertAfter(sections[i - 1], false); + sections[i]->insertAfter(shdr_section, false); + } else + sections[i]->insertAfter(sections[i - 1], false); + } + if (shdr_section->getPrevious() == nullptr) + shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false); + + tmp_file = nullptr; + tmp_shdr = nullptr; + for (int i = 0; i < ehdr->e_shnum; i++) delete shdr[i]; + delete[] shdr; + + eh_shstrndx = (ElfStrtab_Section*)sections[ehdr->e_shstrndx]; + + // Skip reading program headers if there aren't any + if (ehdr->e_phnum == 0) return; + + bool adjusted_phdr_section = false; + // Read program headers + file.seekg(ehdr->e_phoff); + for (int i = 0; i < ehdr->e_phnum; i++) { + Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]); + if (phdr.p_type == PT_LOAD) { + // Default alignment for PT_LOAD on x86-64 prevents elfhack from + // doing anything useful. However, the system doesn't actually + // require such a big alignment, so in order for elfhack to work + // efficiently, reduce alignment when it's originally the default + // one. + if ((ehdr->e_machine == EM_X86_64) && (phdr.p_align == 0x200000)) + phdr.p_align = 0x1000; + } + ElfSegment* segment = new ElfSegment(&phdr); + // Some segments aren't entirely filled (if at all) by sections + // For those, we use fake sections + if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) { + // Use a fake section for ehdr and phdr + ehdr->getShdr().sh_addr = phdr.p_vaddr; + if (!adjusted_phdr_section) { + phdr_section->getShdr().sh_addr += phdr.p_vaddr; + adjusted_phdr_section = true; + } + segment->addSection(ehdr); + segment->addSection(phdr_section); + } + if (phdr.p_type == PT_PHDR) { + if (!adjusted_phdr_section) { + phdr_section->getShdr().sh_addr = phdr.p_vaddr; + adjusted_phdr_section = true; + } + segment->addSection(phdr_section); + } + for (int j = 1; j < ehdr->e_shnum; j++) + if (phdr.contains(sections[j])) segment->addSection(sections[j]); + // Make sure that our view of segments corresponds to the original + // ELF file. + // GNU gold likes to start some segments before the first section + // they contain. https://sourceware.org/bugzilla/show_bug.cgi?id=19392 + unsigned int gold_adjustment = segment->getAddr() - phdr.p_vaddr; + assert(segment->getFileSize() == phdr.p_filesz - gold_adjustment); + // gold makes TLS segments end on an aligned virtual address, even + // when the underlying section ends before that, while bfd ld + // doesn't. It's fine if we don't keep that alignment. + unsigned int memsize = segment->getMemSize(); + if (phdr.p_type == PT_TLS && memsize != phdr.p_memsz) { + unsigned int align = segment->getAlign(); + memsize = (memsize + align - 1) & ~(align - 1); + } + assert(memsize == phdr.p_memsz - gold_adjustment); + segments.push_back(segment); + } + + new (&eh_entry) ElfLocation(ehdr->e_entry, this); +} + +Elf::~Elf() { + for (std::vector<ElfSegment*>::iterator seg = segments.begin(); + seg != segments.end(); seg++) + delete *seg; + delete[] sections; + ElfSection* section = ehdr; + while (section != nullptr) { + ElfSection* next = section->getNext(); + delete section; + section = next; + } +} + +// TODO: This shouldn't fail after inserting sections +ElfSection* Elf::getSection(int index) { + if ((index < -1) || (index >= ehdr->e_shnum)) + throw std::runtime_error("Section index out of bounds"); + if (index == -1) + index = ehdr->e_shstrndx; // TODO: should be fixed to use the actual + // current number + // Special case: the section at index 0 is void + if (index == 0) return nullptr; + // Infinite recursion guard + if (sections[index] == (ElfSection*)this) return nullptr; + if (sections[index] == nullptr) { + sections[index] = (ElfSection*)this; + switch (tmp_shdr[index]->sh_type) { + case SHT_DYNAMIC: + sections[index] = + new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this); + break; + case SHT_REL: + sections[index] = + new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this); + break; + case SHT_RELA: + sections[index] = + new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this); + break; + case SHT_DYNSYM: + case SHT_SYMTAB: + sections[index] = + new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this); + break; + case SHT_STRTAB: + sections[index] = + new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this); + break; + default: + sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this); + } + } + return sections[index]; +} + +ElfSection* Elf::getSectionAt(Elf64_Off offset) { + for (int i = 1; i < ehdr->e_shnum; i++) { + ElfSection* section = getSection(i); + if ((section != nullptr) && (section->getFlags() & SHF_ALLOC) && + !(section->getFlags() & SHF_TLS) && (offset >= section->getAddr()) && + (offset < section->getAddr() + section->getSize())) + return section; + } + return nullptr; +} + +ElfSegment* Elf::getSegmentByType(unsigned int type, ElfSegment* last) { + std::vector<ElfSegment*>::iterator seg; + if (last) { + seg = std::find(segments.begin(), segments.end(), last); + ++seg; + } else + seg = segments.begin(); + for (; seg != segments.end(); seg++) + if ((*seg)->getType() == type) return *seg; + return nullptr; +} + +void Elf::removeSegment(ElfSegment* segment) { + if (!segment) return; + std::vector<ElfSegment*>::iterator seg; + seg = std::find(segments.begin(), segments.end(), segment); + if (seg == segments.end()) return; + segment->clear(); + segments.erase(seg); +} + +ElfDynamic_Section* Elf::getDynSection() { + for (std::vector<ElfSegment*>::iterator seg = segments.begin(); + seg != segments.end(); seg++) + if (((*seg)->getType() == PT_DYNAMIC) && + ((*seg)->getFirstSection() != nullptr) && + (*seg)->getFirstSection()->getType() == SHT_DYNAMIC) + return (ElfDynamic_Section*)(*seg)->getFirstSection(); + + return nullptr; +} + +void Elf::normalize() { + // fixup section headers sh_name; TODO: that should be done by sections + // themselves + for (ElfSection* section = ehdr; section != nullptr; + section = section->getNext()) { + if (section->getIndex() == 0) + continue; + else + ehdr->e_shnum = section->getIndex() + 1; + section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName()); + } + ehdr->markDirty(); + // Check segments consistency + int i = 0; + for (std::vector<ElfSegment*>::iterator seg = segments.begin(); + seg != segments.end(); seg++, i++) { + std::list<ElfSection*>::iterator it = (*seg)->begin(); + for (ElfSection* last = *(it++); it != (*seg)->end(); last = *(it++)) { + if (((*it)->getType() != SHT_NOBITS) && + ((*it)->getAddr() - last->getAddr()) != + ((*it)->getOffset() - last->getOffset())) { + throw std::runtime_error("Segments inconsistency"); + } + } + } + + ElfSegment* prevLoad = nullptr; + for (auto& it : segments) { + if (it->getType() == PT_LOAD) { + if (prevLoad) { + size_t alignedPrevEnd = (prevLoad->getAddr() + prevLoad->getMemSize() + + prevLoad->getAlign() - 1) & + ~(prevLoad->getAlign() - 1); + size_t alignedStart = it->getAddr() & ~(it->getAlign() - 1); + if (alignedPrevEnd > alignedStart) { + throw std::runtime_error("Segments overlap"); + } + } + prevLoad = it; + } + } + + // fixup ehdr before writing + if (ehdr->e_phnum != segments.size()) { + ehdr->e_phnum = segments.size(); + phdr_section->getShdr().sh_size = + segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]); + phdr_section->getNext()->markDirty(); + } + // fixup shdr before writing + if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize()) + shdr_section->getShdr().sh_size = + ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]); + ehdr->e_shoff = shdr_section->getOffset(); + ehdr->e_entry = eh_entry.getValue(); + ehdr->e_shstrndx = eh_shstrndx->getIndex(); + + // Check sections consistency + unsigned int minOffset = 0; + for (ElfSection* section = ehdr; section != nullptr; + section = section->getNext()) { + unsigned int offset = section->getOffset(); + if (offset < minOffset) { + throw std::runtime_error("Sections overlap"); + } + if (section->getType() != SHT_NOBITS) { + minOffset = offset + section->getSize(); + } + } +} + +void Elf::write(std::ofstream& file) { + normalize(); + for (ElfSection* section = ehdr; section != nullptr; + section = section->getNext()) { + file.seekp(section->getOffset()); + if (section == phdr_section) { + for (std::vector<ElfSegment*>::iterator seg = segments.begin(); + seg != segments.end(); seg++) { + Elf_Phdr phdr; + phdr.p_type = (*seg)->getType(); + phdr.p_flags = (*seg)->getFlags(); + phdr.p_offset = (*seg)->getOffset(); + phdr.p_vaddr = (*seg)->getAddr(); + phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff(); + phdr.p_filesz = (*seg)->getFileSize(); + phdr.p_memsz = (*seg)->getMemSize(); + phdr.p_align = (*seg)->getAlign(); + phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]); + } + } else if (section == shdr_section) { + null_section.serialize(file, ehdr->e_ident[EI_CLASS], + ehdr->e_ident[EI_DATA]); + for (ElfSection* sec = ehdr; sec != nullptr; sec = sec->getNext()) { + if (sec->getType() != SHT_NULL) + sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS], + ehdr->e_ident[EI_DATA]); + } + } else + section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]); + } +} + +ElfSection::ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent) + : shdr(s), + link(shdr.sh_link == SHN_UNDEF ? nullptr + : parent->getSection(shdr.sh_link)), + next(nullptr), + previous(nullptr), + index(-1) { + if ((file == nullptr) || (shdr.sh_type == SHT_NULL) || + (shdr.sh_type == SHT_NOBITS)) + data = nullptr; + else { + data = static_cast<char*>(malloc(shdr.sh_size)); + if (!data) { + throw std::runtime_error("Could not malloc ElfSection data"); + } + auto pos = file->tellg(); + file->seekg(shdr.sh_offset); + file->read(data, shdr.sh_size); + file->seekg(pos); + } + if (shdr.sh_name == 0) + name = nullptr; + else { + ElfStrtab_Section* strtab = (ElfStrtab_Section*)parent->getSection(-1); + // Special case (see elfgeneric.cpp): if strtab is nullptr, the + // section being created is the strtab. + if (strtab == nullptr) + name = &data[shdr.sh_name]; + else + name = strtab->getStr(shdr.sh_name); + } + // Only SHT_REL/SHT_RELA sections use sh_info to store a section + // number. + if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA)) + info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : nullptr; + else + info.index = shdr.sh_info; +} + +Elf64_Addr ElfSection::getAddr() { + if (shdr.sh_addr != (Elf64_Addr)-1) return shdr.sh_addr; + + // It should be safe to adjust sh_addr for all allocated sections that + // are neither SHT_NOBITS nor SHT_PROGBITS + if ((previous != nullptr) && isRelocatable()) { + unsigned int addr = previous->getAddr(); + if (previous->getType() != SHT_NOBITS) addr += previous->getSize(); + + if (addr & (getAddrAlign() - 1)) addr = (addr | (getAddrAlign() - 1)) + 1; + + return (shdr.sh_addr = addr); + } + return shdr.sh_addr; +} + +Elf64_Off ElfSection::getOffset() { + if (shdr.sh_offset != (Elf64_Off)-1) return shdr.sh_offset; + + if (previous == nullptr) return (shdr.sh_offset = 0); + + Elf64_Off offset = previous->getOffset(); + + ElfSegment* ptload = getSegmentByType(PT_LOAD); + ElfSegment* prev_ptload = previous->getSegmentByType(PT_LOAD); + + if (ptload && (ptload == prev_ptload)) { + offset += getAddr() - previous->getAddr(); + return (shdr.sh_offset = offset); + } + + if (previous->getType() != SHT_NOBITS) offset += previous->getSize(); + + Elf32_Word align = 0x1000; + for (std::vector<ElfSegment*>::iterator seg = segments.begin(); + seg != segments.end(); seg++) + align = std::max(align, (*seg)->getAlign()); + + Elf32_Word mask = align - 1; + // SHF_TLS is used for .tbss which is some kind of special case. + if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) && + (getFlags() & SHF_ALLOC)) { + if ((getAddr() & mask) < (offset & mask)) + offset = (offset | mask) + (getAddr() & mask) + 1; + else + offset = (offset & ~mask) + (getAddr() & mask); + } + if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1))) + offset = (offset | (getAddrAlign() - 1)) + 1; + + return (shdr.sh_offset = offset); +} + +int ElfSection::getIndex() { + if (index != -1) return index; + if (getType() == SHT_NULL) return (index = 0); + ElfSection* reference; + for (reference = previous; + (reference != nullptr) && (reference->getType() == SHT_NULL); + reference = reference->getPrevious()) + ; + if (reference == nullptr) return (index = 1); + return (index = reference->getIndex() + 1); +} + +Elf_Shdr& ElfSection::getShdr() { + getOffset(); + if (shdr.sh_link == (Elf64_Word)-1) + shdr.sh_link = getLink() ? getLink()->getIndex() : 0; + if (shdr.sh_info == (Elf64_Word)-1) + shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA)) + ? (getInfo().section ? getInfo().section->getIndex() : 0) + : getInfo().index; + + return shdr; +} + +ElfSegment::ElfSegment(Elf_Phdr* phdr) + : type(phdr->p_type), + v_p_diff(phdr->p_paddr - phdr->p_vaddr), + flags(phdr->p_flags), + align(phdr->p_align), + vaddr(phdr->p_vaddr), + filesz(phdr->p_filesz), + memsz(phdr->p_memsz) {} + +void ElfSegment::addSection(ElfSection* section) { + // Make sure all sections in PT_GNU_RELRO won't be moved by elfhack + assert(!((type == PT_GNU_RELRO) && (section->isRelocatable()))); + + // TODO: Check overlapping sections + std::list<ElfSection*>::iterator i; + for (i = sections.begin(); i != sections.end(); ++i) + if ((*i)->getAddr() > section->getAddr()) break; + sections.insert(i, section); + section->addToSegment(this); +} + +void ElfSegment::removeSection(ElfSection* section) { + sections.remove(section); + section->removeFromSegment(this); +} + +unsigned int ElfSegment::getFileSize() { + if (type == PT_GNU_RELRO) return filesz; + + if (sections.empty()) return 0; + // Search the last section that is not SHT_NOBITS + std::list<ElfSection*>::reverse_iterator i; + for (i = sections.rbegin(); + (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i) + ; + // All sections are SHT_NOBITS + if (i == sections.rend()) return 0; + + unsigned int end = (*i)->getAddr() + (*i)->getSize(); + + return end - sections.front()->getAddr(); +} + +unsigned int ElfSegment::getMemSize() { + if (type == PT_GNU_RELRO) return memsz; + + if (sections.empty()) return 0; + + unsigned int end = sections.back()->getAddr() + sections.back()->getSize(); + + return end - sections.front()->getAddr(); +} + +unsigned int ElfSegment::getOffset() { + if ((type == PT_GNU_RELRO) && !sections.empty() && + (sections.front()->getAddr() != vaddr)) + throw std::runtime_error( + "PT_GNU_RELRO segment doesn't start on a section start"); + + return sections.empty() ? 0 : sections.front()->getOffset(); +} + +unsigned int ElfSegment::getAddr() { + if ((type == PT_GNU_RELRO) && !sections.empty() && + (sections.front()->getAddr() != vaddr)) + throw std::runtime_error( + "PT_GNU_RELRO segment doesn't start on a section start"); + + return sections.empty() ? 0 : sections.front()->getAddr(); +} + +void ElfSegment::clear() { + for (std::list<ElfSection*>::iterator i = sections.begin(); + i != sections.end(); ++i) + (*i)->removeFromSegment(this); + sections.clear(); +} + +ElfValue* ElfDynamic_Section::getValueForType(unsigned int tag) { + for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) + if (dyns[i].tag == tag) return dyns[i].value; + + return nullptr; +} + +ElfSection* ElfDynamic_Section::getSectionForType(unsigned int tag) { + ElfValue* value = getValueForType(tag); + return value ? value->getSection() : nullptr; +} + +bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue* val) { + unsigned int i; + unsigned int shnum = shdr.sh_size / shdr.sh_entsize; + for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++) + if (dyns[i].tag == tag) { + delete dyns[i].value; + dyns[i].value = val; + return true; + } + // If we get here, this means we didn't match for the given tag + // Most of the time, there are a few DT_NULL entries, that we can + // use to add our value, but if we are on the last entry, we can't. + if (i >= shnum - 1) return false; + + dyns[i].tag = tag; + dyns[i].value = val; + return true; +} + +ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file, + Elf* parent) + : ElfSection(s, file, parent) { + auto pos = file->tellg(); + dyns.resize(s.sh_size / s.sh_entsize); + file->seekg(shdr.sh_offset); + // Here we assume tags refer to only one section (e.g. DT_RELSZ accounts + // for .rel.dyn size) + for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) { + Elf_Dyn dyn(*file, parent->getClass(), parent->getData()); + dyns[i].tag = dyn.d_tag; + switch (dyn.d_tag) { + case DT_NULL: + case DT_SYMBOLIC: + case DT_TEXTREL: + case DT_BIND_NOW: + dyns[i].value = new ElfValue(); + break; + case DT_NEEDED: + case DT_SONAME: + case DT_RPATH: + case DT_PLTREL: + case DT_RUNPATH: + case DT_FLAGS: + case DT_RELACOUNT: + case DT_RELCOUNT: + case DT_VERDEFNUM: + case DT_VERNEEDNUM: + dyns[i].value = new ElfPlainValue(dyn.d_un.d_val); + break; + case DT_PLTGOT: + case DT_HASH: + case DT_STRTAB: + case DT_SYMTAB: + case DT_RELA: + case DT_INIT: + case DT_FINI: + case DT_REL: + case DT_JMPREL: + case DT_INIT_ARRAY: + case DT_FINI_ARRAY: + case DT_GNU_HASH: + case DT_VERSYM: + case DT_VERNEED: + case DT_VERDEF: + dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent); + break; + default: + dyns[i].value = nullptr; + } + } + // Another loop to get the section sizes + for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) + switch (dyns[i].tag) { + case DT_PLTRELSZ: + dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL)); + break; + case DT_RELASZ: + dyns[i].value = new ElfSize(getSectionForType(DT_RELA)); + break; + case DT_STRSZ: + dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB)); + break; + case DT_RELSZ: + dyns[i].value = new ElfSize(getSectionForType(DT_REL)); + break; + case DT_INIT_ARRAYSZ: + dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY)); + break; + case DT_FINI_ARRAYSZ: + dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY)); + break; + case DT_RELAENT: + dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA)); + break; + case DT_SYMENT: + dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB)); + break; + case DT_RELENT: + dyns[i].value = new ElfEntSize(getSectionForType(DT_REL)); + break; + } + + file->seekg(pos); +} + +ElfDynamic_Section::~ElfDynamic_Section() { + for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) + delete dyns[i].value; +} + +void ElfDynamic_Section::serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { + Elf_Dyn dyn; + dyn.d_tag = dyns[i].tag; + dyn.d_un.d_val = (dyns[i].value != nullptr) ? dyns[i].value->getValue() : 0; + dyn.serialize(file, ei_class, ei_data); + } +} + +ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file, + Elf* parent) + : ElfSection(s, file, parent) { + auto pos = file->tellg(); + syms.resize(s.sh_size / s.sh_entsize); + ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink(); + file->seekg(shdr.sh_offset); + for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { + Elf_Sym sym(*file, parent->getClass(), parent->getData()); + syms[i].name = strtab->getStr(sym.st_name); + syms[i].info = sym.st_info; + syms[i].other = sym.st_other; + ElfSection* section = + (sym.st_shndx == SHN_ABS) ? nullptr : parent->getSection(sym.st_shndx); + new (&syms[i].value) + ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE); + syms[i].size = sym.st_size; + syms[i].defined = (sym.st_shndx != SHN_UNDEF); + } + file->seekg(pos); +} + +void ElfSymtab_Section::serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink(); + for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { + Elf_Sym sym; + sym.st_name = strtab->getStrIndex(syms[i].name); + sym.st_info = syms[i].info; + sym.st_other = syms[i].other; + sym.st_value = syms[i].value.getValue(); + ElfSection* section = syms[i].value.getSection(); + if (syms[i].defined) + sym.st_shndx = section ? section->getIndex() : SHN_ABS; + else + sym.st_shndx = SHN_UNDEF; + sym.st_size = syms[i].size; + sym.serialize(file, ei_class, ei_data); + } +} + +Elf_SymValue* ElfSymtab_Section::lookup(const char* name, + unsigned int type_filter) { + for (std::vector<Elf_SymValue>::iterator sym = syms.begin(); + sym != syms.end(); sym++) { + if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) && + (strcmp(sym->name, name) == 0)) { + return &*sym; + } + } + return nullptr; +} + +const char* ElfStrtab_Section::getStr(unsigned int index) { + for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); + t++) { + if (index < t->used) return t->buf + index; + index -= t->used; + } + assert(1 == 0); + return nullptr; +} + +const char* ElfStrtab_Section::getStr(const char* string) { + if (string == nullptr) return nullptr; + + // If the given string is within the section, return it + for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); + t++) + if ((string >= t->buf) && (string < t->buf + t->used)) return string; + + // TODO: should scan in the section to find an existing string + + // If not, we need to allocate the string in the section + size_t len = strlen(string) + 1; + + if (table.back().size - table.back().used < len) + table.resize(table.size() + 1); + + char* alloc_str = table.back().buf + table.back().used; + memcpy(alloc_str, string, len); + table.back().used += len; + + shdr.sh_size += len; + markDirty(); + + return alloc_str; +} + +unsigned int ElfStrtab_Section::getStrIndex(const char* string) { + if (string == nullptr) return 0; + + unsigned int index = 0; + string = getStr(string); + for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); + t++) { + if ((string >= t->buf) && (string < t->buf + t->used)) + return index + (string - t->buf); + index += t->used; + } + + assert(1 == 0); + return 0; +} + +void ElfStrtab_Section::serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + file.seekp(getOffset()); + for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); + t++) + file.write(t->buf, t->used); +} diff --git a/build/unix/elfhack/elfhack.cpp b/build/unix/elfhack/elfhack.cpp new file mode 100644 index 0000000000..719d4ac8f5 --- /dev/null +++ b/build/unix/elfhack/elfhack.cpp @@ -0,0 +1,1458 @@ +/* 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/. */ + +#undef NDEBUG +#include <assert.h> +#include <cstring> +#include <cstdlib> +#include <cstdio> +#include <memory> + +#include "elfxx.h" +#include "mozilla/CheckedInt.h" + +#define ver "1" +#define elfhack_data ".elfhack.data.v" ver +#define elfhack_text ".elfhack.text.v" ver + +#ifndef R_ARM_V4BX +# define R_ARM_V4BX 0x28 +#endif +#ifndef R_ARM_CALL +# define R_ARM_CALL 0x1c +#endif +#ifndef R_ARM_JUMP24 +# define R_ARM_JUMP24 0x1d +#endif +#ifndef R_ARM_THM_JUMP24 +# define R_ARM_THM_JUMP24 0x1e +#endif + +char* rundir = nullptr; + +template <typename T> +struct wrapped { + T value; +}; + +class Elf_Addr_Traits { + public: + typedef wrapped<Elf32_Addr> Type32; + typedef wrapped<Elf64_Addr> Type64; + + template <class endian, typename R, typename T> + static inline void swap(T& t, R& r) { + r.value = endian::swap(t.value); + } +}; + +typedef serializable<Elf_Addr_Traits> Elf_Addr; + +class ElfRelHack_Section : public ElfSection { + public: + ElfRelHack_Section(Elf_Shdr& s) + : ElfSection(s, nullptr, nullptr), + block_size((8 * s.sh_entsize - 1) * s.sh_entsize) { + name = elfhack_data; + }; + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + if (bitmap) { + relr.push_back((bitmap << 1) | 1); + } + for (std::vector<Elf64_Addr>::iterator i = relr.begin(); i != relr.end(); + ++i) { + Elf_Addr out; + out.value = *i; + out.serialize(file, ei_class, ei_data); + } + } + + bool isRelocatable() { return true; } + + void push_back(Elf64_Addr offset) { + // The format used for the packed relocations is SHT_RELR, described in + // https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/Jnz1lgLJAgAJ + // The gist of it is that an address is recorded, and the following words, + // if their LSB is 1, represent a bitmap of word-size-spaced relocations + // at the addresses that follow. There can be multiple such bitmaps, such + // that very long streaks of (possibly spaced) relocations can be recorded + // in a very compact way. + for (;;) { + // [block_start; block_start + block_size] represents the range of offsets + // the current bitmap can record. If the offset doesn't fall in that + // range, or if doesn't align properly to be recorded, we record the + // bitmap, and slide the block corresponding to a new bitmap. If the + // offset doesn't fall in the range for the new bitmap, or if there wasn't + // an active bitmap in the first place, we record the offset and start a + // new bitmap for the block that follows it. + if (!block_start || offset < block_start || + offset >= block_start + block_size || + (offset - block_start) % shdr.sh_entsize) { + if (bitmap) { + relr.push_back((bitmap << 1) | 1); + block_start += block_size; + bitmap = 0; + continue; + } + relr.push_back(offset); + block_start = offset + shdr.sh_entsize; + break; + } + bitmap |= 1ULL << ((offset - block_start) / shdr.sh_entsize); + break; + } + shdr.sh_size = (relr.size() + (bitmap ? 1 : 0)) * shdr.sh_entsize; + } + + private: + std::vector<Elf64_Addr> relr; + size_t block_size; + Elf64_Addr block_start = 0; + Elf64_Addr bitmap = 0; +}; + +class ElfRelHackCode_Section : public ElfSection { + public: + ElfRelHackCode_Section(Elf_Shdr& s, Elf& e, + ElfRelHack_Section& relhack_section, unsigned int init, + unsigned int mprotect_cb, unsigned int sysconf_cb) + : ElfSection(s, nullptr, nullptr), + parent(e), + relhack_section(relhack_section), + init(init), + init_trampoline(nullptr), + mprotect_cb(mprotect_cb), + sysconf_cb(sysconf_cb) { + std::string file(rundir); + file += "/inject/"; + switch (parent.getMachine()) { + case EM_386: + file += "x86"; + break; + case EM_X86_64: + file += "x86_64"; + break; + case EM_ARM: + file += "arm"; + break; + case EM_AARCH64: + file += "aarch64"; + break; + default: + throw std::runtime_error("unsupported architecture"); + } + file += ".o"; + std::ifstream inject(file.c_str(), std::ios::in | std::ios::binary); + elf = new Elf(inject); + if (elf->getType() != ET_REL) + throw std::runtime_error("object for injected code is not ET_REL"); + if (elf->getMachine() != parent.getMachine()) + throw std::runtime_error( + "architecture of object for injected code doesn't match"); + + ElfSymtab_Section* symtab = nullptr; + + // Find the symbol table. + for (ElfSection* section = elf->getSection(1); section != nullptr; + section = section->getNext()) { + if (section->getType() == SHT_SYMTAB) + symtab = (ElfSymtab_Section*)section; + } + if (symtab == nullptr) + throw std::runtime_error( + "Couldn't find a symbol table for the injected code"); + + relro = parent.getSegmentByType(PT_GNU_RELRO); + + // Find the init symbol + entry_point = -1; + std::string symbol = "init"; + if (!init) symbol += "_noinit"; + if (relro) symbol += "_relro"; + Elf_SymValue* sym = symtab->lookup(symbol.c_str()); + if (!sym) + throw std::runtime_error( + "Couldn't find an 'init' symbol in the injected code"); + + entry_point = sym->value.getValue(); + + // Get all relevant sections from the injected code object. + add_code_section(sym->value.getSection()); + + // If the original init function is located too far away, we're going to + // need to use a trampoline. See comment in inject.c. + // Theoretically, we should check for (init - instr) > boundary, where + // boundary is the platform-dependent limit, and instr is the virtual + // address of the instruction that calls the original init, but we don't + // have it at this point, so punt to just init. + if ((init > 0xffffff && parent.getMachine() == EM_ARM) || + (init > 0x07ffffff && parent.getMachine() == EM_AARCH64)) { + Elf_SymValue* trampoline = symtab->lookup("init_trampoline"); + if (!trampoline) { + throw std::runtime_error( + "Couldn't find an 'init_trampoline' symbol in the injected code"); + } + + init_trampoline = trampoline->value.getSection(); + add_code_section(init_trampoline); + } + + // Adjust code sections offsets according to their size + std::vector<ElfSection*>::iterator c = code.begin(); + (*c)->getShdr().sh_addr = 0; + for (ElfSection* last = *(c++); c != code.end(); ++c) { + unsigned int addr = last->getShdr().sh_addr + last->getSize(); + if (addr & ((*c)->getAddrAlign() - 1)) + addr = (addr | ((*c)->getAddrAlign() - 1)) + 1; + (*c)->getShdr().sh_addr = addr; + // We need to align this section depending on the greater + // alignment required by code sections. + if (shdr.sh_addralign < (*c)->getAddrAlign()) + shdr.sh_addralign = (*c)->getAddrAlign(); + last = *c; + } + shdr.sh_size = code.back()->getAddr() + code.back()->getSize(); + data = static_cast<char*>(malloc(shdr.sh_size)); + if (!data) { + throw std::runtime_error("Could not malloc ElfSection data"); + } + char* buf = data; + for (c = code.begin(); c != code.end(); ++c) { + memcpy(buf, (*c)->getData(), (*c)->getSize()); + buf += (*c)->getSize(); + } + name = elfhack_text; + } + + ~ElfRelHackCode_Section() { delete elf; } + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) override { + // Readjust code offsets + for (std::vector<ElfSection*>::iterator c = code.begin(); c != code.end(); + ++c) + (*c)->getShdr().sh_addr += getAddr(); + + // Apply relocations + for (std::vector<ElfSection*>::iterator c = code.begin(); c != code.end(); + ++c) { + for (ElfSection* rel = elf->getSection(1); rel != nullptr; + rel = rel->getNext()) + if (((rel->getType() == SHT_REL) || (rel->getType() == SHT_RELA)) && + (rel->getInfo().section == *c)) { + if (rel->getType() == SHT_REL) + apply_relocations((ElfRel_Section<Elf_Rel>*)rel, *c); + else + apply_relocations((ElfRel_Section<Elf_Rela>*)rel, *c); + } + } + + ElfSection::serialize(file, ei_class, ei_data); + } + + bool isRelocatable() override { return false; } + + unsigned int getEntryPoint() { return entry_point; } + + void insertBefore(ElfSection* section, bool dirty = true) override { + // Adjust the address so that this section is adjacent to the one it's + // being inserted before. This avoids creating holes which subsequently + // might lead the PHDR-adjusting code to create unnecessary additional + // PT_LOADs. + shdr.sh_addr = + (section->getAddr() - shdr.sh_size) & ~(shdr.sh_addralign - 1); + ElfSection::insertBefore(section, dirty); + } + + private: + void add_code_section(ElfSection* section) { + if (section) { + /* Don't add section if it's already been added in the past */ + for (auto s = code.begin(); s != code.end(); ++s) { + if (section == *s) return; + } + code.push_back(section); + find_code(section); + } + } + + /* Look at the relocations associated to the given section to find other + * sections that it requires */ + void find_code(ElfSection* section) { + for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) { + if (((s->getType() == SHT_REL) || (s->getType() == SHT_RELA)) && + (s->getInfo().section == section)) { + if (s->getType() == SHT_REL) + scan_relocs_for_code((ElfRel_Section<Elf_Rel>*)s); + else + scan_relocs_for_code((ElfRel_Section<Elf_Rela>*)s); + } + } + } + + template <typename Rel_Type> + void scan_relocs_for_code(ElfRel_Section<Rel_Type>* rel) { + ElfSymtab_Section* symtab = (ElfSymtab_Section*)rel->getLink(); + for (auto r = rel->rels.begin(); r != rel->rels.end(); ++r) { + ElfSection* section = + symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection(); + add_code_section(section); + } + } + + // TODO: sort out which non-aarch64 relocation types should be using + // `value` (even though in practice it's either 0 or the same as addend) + class pc32_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + return addr + addend - offset - base_addr; + } + }; + + class arm_plt32_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + // We don't care about sign_extend because the only case where this is + // going to be used only jumps forward. + Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr) >> 2; + tmp = (addend + tmp) & 0x00ffffff; + return (addend & 0xff000000) | tmp; + } + }; + + class arm_thm_jump24_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + /* Follows description of b.w and bl instructions as per + ARM Architecture Reference Manual ARM® v7-A and ARM® v7-R edition, + A8.6.16 We limit ourselves to Encoding T4 of b.w and Encoding T1 of bl. + We don't care about sign_extend because the only case where this is + going to be used only jumps forward. */ + Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr); + unsigned int word0 = addend & 0xffff, word1 = addend >> 16; + + /* Encoding T4 of B.W is 10x1 ; Encoding T1 of BL is 11x1. */ + unsigned int type = (word1 & 0xd000) >> 12; + if (((word0 & 0xf800) != 0xf000) || ((type & 0x9) != 0x9)) + throw std::runtime_error( + "R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for B.W " + "<label> and BL <label>"); + + /* When the target address points to ARM code, switch a BL to a + * BLX. This however can't be done with a B.W without adding a + * trampoline, which is not supported as of now. */ + if ((addr & 0x1) == 0) { + if (type == 0x9) + throw std::runtime_error( + "R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for " + "BL <label> when label points to ARM code"); + /* The address of the target is always relative to a 4-bytes + * aligned address, so if the address of the BL instruction is + * not 4-bytes aligned, adjust for it. */ + if ((base_addr + offset) & 0x2) tmp += 2; + /* Encoding T2 of BLX is 11x0. */ + type = 0xc; + } + + unsigned int s = (word0 & (1 << 10)) >> 10; + unsigned int j1 = (word1 & (1 << 13)) >> 13; + unsigned int j2 = (word1 & (1 << 11)) >> 11; + unsigned int i1 = j1 ^ s ? 0 : 1; + unsigned int i2 = j2 ^ s ? 0 : 1; + + tmp += ((s << 24) | (i1 << 23) | (i2 << 22) | ((word0 & 0x3ff) << 12) | + ((word1 & 0x7ff) << 1)); + + s = (tmp & (1 << 24)) >> 24; + j1 = ((tmp & (1 << 23)) >> 23) ^ !s; + j2 = ((tmp & (1 << 22)) >> 22) ^ !s; + + return 0xf000 | (s << 10) | ((tmp & (0x3ff << 12)) >> 12) | (type << 28) | + (j1 << 29) | (j2 << 27) | ((tmp & 0xffe) << 15); + } + }; + + class gotoff_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + return addr + addend; + } + }; + + template <int start, int end> + class abs_lo12_nc_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + // Fill the bits [end:start] of the immediate value in an ADD, LDR or STR + // instruction, at bits [21:10]. + // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture + // profile C5.6.4, C5.6.83 or C5.6.178 and ELF for the ARM® 64-bit + // Architecture (AArch64) 4.6.6, Table 4-9. + Elf64_Word mask = (1 << (end + 1)) - 1; + return value | (((((addr + addend) & mask) >> start) & 0xfff) << 10); + } + }; + + class adr_prel_pg_hi21_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + // Fill the bits [32:12] of the immediate value in a ADRP instruction, + // at bits [23:5]+[30:29]. + // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture + // profile C5.6.10 and ELF for the ARM® 64-bit Architecture + // (AArch64) 4.6.6, Table 4-9. + Elf64_Word imm = ((addr + addend) >> 12) - ((base_addr + offset) >> 12); + Elf64_Word immLo = (imm & 0x3) << 29; + Elf64_Word immHi = (imm & 0x1ffffc) << 3; + return value & 0x9f00001f | immLo | immHi; + } + }; + + class call26_relocation { + public: + Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset, + Elf64_Sxword addend, unsigned int addr, + Elf64_Word value) { + // Fill the bits [27:2] of the immediate value in a BL instruction, + // at bits [25:0]. + // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture + // profile C5.6.26 and ELF for the ARM® 64-bit Architecture + // (AArch64) 4.6.6, Table 4-10. + return value | (((addr + addend - offset - base_addr) & 0x0ffffffc) >> 2); + } + }; + + template <class relocation_type> + void apply_relocation(ElfSection* the_code, char* base, Elf_Rel* r, + unsigned int addr) { + relocation_type relocation; + Elf32_Addr value; + memcpy(&value, base + r->r_offset, 4); + value = relocation(the_code->getAddr(), r->r_offset, value, addr, value); + memcpy(base + r->r_offset, &value, 4); + } + + template <class relocation_type> + void apply_relocation(ElfSection* the_code, char* base, Elf_Rela* r, + unsigned int addr) { + relocation_type relocation; + Elf64_Word value; + memcpy(&value, base + r->r_offset, 4); + Elf32_Addr new_value = + relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr, value); + memcpy(base + r->r_offset, &new_value, 4); + } + + template <typename Rel_Type> + void apply_relocations(ElfRel_Section<Rel_Type>* rel, ElfSection* the_code) { + assert(rel->getType() == Rel_Type::sh_type); + char* buf = data + (the_code->getAddr() - code.front()->getAddr()); + // TODO: various checks on the sections + ElfSymtab_Section* symtab = (ElfSymtab_Section*)rel->getLink(); + for (typename std::vector<Rel_Type>::iterator r = rel->rels.begin(); + r != rel->rels.end(); ++r) { + // TODO: various checks on the symbol + const char* name = symtab->syms[ELF64_R_SYM(r->r_info)].name; + unsigned int addr; + if (symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection() == nullptr) { + if (strcmp(name, "relhack") == 0) { + addr = relhack_section.getAddr(); + } else if (strcmp(name, "relhack_end") == 0) { + addr = relhack_section.getAddr() + relhack_section.getSize(); + } else if (strcmp(name, "__ehdr_start") == 0) { + // TODO: change this ugly hack to something better + ElfSection* ehdr = parent.getSection(1)->getPrevious()->getPrevious(); + addr = ehdr->getAddr(); + } else if (strcmp(name, "original_init") == 0) { + if (init_trampoline) { + addr = init_trampoline->getAddr(); + } else { + addr = init; + } + } else if (strcmp(name, "real_original_init") == 0) { + addr = init; + } else if (relro && strcmp(name, "mprotect_cb") == 0) { + addr = mprotect_cb; + } else if (relro && strcmp(name, "sysconf_cb") == 0) { + addr = sysconf_cb; + } else if (relro && strcmp(name, "relro_start") == 0) { + addr = relro->getAddr(); + } else if (relro && strcmp(name, "relro_end") == 0) { + addr = (relro->getAddr() + relro->getMemSize()); + } else if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") == 0) { + // We actually don't need a GOT, but need it as a reference for + // GOTOFF relocations. We'll just use the start of the ELF file + addr = 0; + } else if (strcmp(name, "") == 0) { + // This is for R_ARM_V4BX, until we find something better + addr = -1; + } else { + throw std::runtime_error("Unsupported symbol in relocation"); + } + } else { + ElfSection* section = + symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection(); + assert((section->getType() == SHT_PROGBITS) && + (section->getFlags() & SHF_EXECINSTR)); + addr = symtab->syms[ELF64_R_SYM(r->r_info)].value.getValue(); + } + // Do the relocation +#define REL(machine, type) (EM_##machine | (R_##machine##_##type << 8)) + switch (elf->getMachine() | (ELF64_R_TYPE(r->r_info) << 8)) { + case REL(X86_64, PC32): + case REL(X86_64, PLT32): + case REL(386, PC32): + case REL(386, GOTPC): + case REL(ARM, GOTPC): + case REL(ARM, REL32): + case REL(AARCH64, PREL32): + case REL(AARCH64, + PREL64): // In theory PREL64 should have its own relocation + // function, but in practice it doesn't matter. + apply_relocation<pc32_relocation>(the_code, buf, &*r, addr); + break; + case REL(ARM, CALL): + case REL(ARM, JUMP24): + case REL(ARM, PLT32): + apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr); + break; + case REL(ARM, THM_PC22 /* THM_CALL */): + case REL(ARM, THM_JUMP24): + apply_relocation<arm_thm_jump24_relocation>(the_code, buf, &*r, addr); + break; + case REL(386, GOTOFF): + case REL(ARM, GOTOFF): + apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr); + break; + case REL(AARCH64, ADD_ABS_LO12_NC): + apply_relocation<abs_lo12_nc_relocation<0, 11>>(the_code, buf, &*r, + addr); + break; + case REL(AARCH64, ADR_PREL_PG_HI21): + apply_relocation<adr_prel_pg_hi21_relocation>(the_code, buf, &*r, + addr); + break; + case REL(AARCH64, LDST32_ABS_LO12_NC): + apply_relocation<abs_lo12_nc_relocation<2, 11>>(the_code, buf, &*r, + addr); + break; + case REL(AARCH64, LDST64_ABS_LO12_NC): + apply_relocation<abs_lo12_nc_relocation<3, 11>>(the_code, buf, &*r, + addr); + break; + case REL(AARCH64, CALL26): + apply_relocation<call26_relocation>(the_code, buf, &*r, addr); + break; + case REL(ARM, V4BX): + // Ignore R_ARM_V4BX relocations + break; + default: + throw std::runtime_error("Unsupported relocation type"); + } + } + } + + Elf *elf, &parent; + ElfRelHack_Section& relhack_section; + std::vector<ElfSection*> code; + unsigned int init; + ElfSection* init_trampoline; + unsigned int mprotect_cb; + unsigned int sysconf_cb; + int entry_point; + ElfSegment* relro; +}; + +unsigned int get_addend(Elf_Rel* rel, Elf* elf) { + ElfLocation loc(rel->r_offset, elf); + Elf_Addr addr(loc.getBuffer(), Elf_Addr::size(elf->getClass()), + elf->getClass(), elf->getData()); + return addr.value; +} + +unsigned int get_addend(Elf_Rela* rel, Elf* elf) { return rel->r_addend; } + +void set_relative_reloc(Elf_Rel* rel, Elf* elf, unsigned int value) { + ElfLocation loc(rel->r_offset, elf); + Elf_Addr addr; + addr.value = value; + addr.serialize(const_cast<char*>(loc.getBuffer()), + Elf_Addr::size(elf->getClass()), elf->getClass(), + elf->getData()); +} + +void set_relative_reloc(Elf_Rela* rel, Elf* elf, unsigned int value) { + // ld puts the value of relocated relocations both in the addend and + // at r_offset. For consistency, keep it that way. + set_relative_reloc((Elf_Rel*)rel, elf, value); + rel->r_addend = value; +} + +void maybe_split_segment(Elf* elf, ElfSegment* segment) { + std::list<ElfSection*>::iterator it = segment->begin(); + for (ElfSection* last = *(it++); it != segment->end(); last = *(it++)) { + // When two consecutive non-SHT_NOBITS sections are apart by more + // than the alignment of the section, the second can be moved closer + // to the first, but this requires the segment to be split. + if (((*it)->getType() != SHT_NOBITS) && (last->getType() != SHT_NOBITS) && + ((*it)->getOffset() - last->getOffset() - last->getSize() > + segment->getAlign())) { + // Probably very wrong. + Elf_Phdr phdr; + phdr.p_type = PT_LOAD; + phdr.p_vaddr = 0; + phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff(); + phdr.p_flags = segment->getFlags(); + phdr.p_align = segment->getAlign(); + phdr.p_filesz = (Elf64_Xword)-1LL; + phdr.p_memsz = (Elf64_Xword)-1LL; + ElfSegment* newSegment = new ElfSegment(&phdr); + elf->insertSegmentAfter(segment, newSegment); + for (; it != segment->end(); ++it) { + newSegment->addSection(*it); + } + for (it = newSegment->begin(); it != newSegment->end(); ++it) { + segment->removeSection(*it); + } + break; + } + } +} + +// EH_FRAME constants +static const unsigned char DW_EH_PE_absptr = 0x00; +static const unsigned char DW_EH_PE_omit = 0xff; + +// Data size +static const unsigned char DW_EH_PE_LEB128 = 0x01; +static const unsigned char DW_EH_PE_data2 = 0x02; +static const unsigned char DW_EH_PE_data4 = 0x03; +static const unsigned char DW_EH_PE_data8 = 0x04; + +// Data signedness +static const unsigned char DW_EH_PE_signed = 0x08; + +// Modifiers +static const unsigned char DW_EH_PE_pcrel = 0x10; + +// Return the data size part of the encoding value +static unsigned char encoding_data_size(unsigned char encoding) { + return encoding & 0x07; +} + +// Advance `step` bytes in the buffer at `data` with size `size`, returning +// the advanced buffer pointer and remaining size. +// Returns true if step <= size. +static bool advance_buffer(char** data, size_t* size, size_t step) { + if (step > *size) return false; + + *data += step; + *size -= step; + return true; +} + +// Advance in the given buffer, skipping the full length of the variable-length +// encoded LEB128 type in CIE/FDE data. +static bool skip_LEB128(char** data, size_t* size) { + if (!*size) return false; + + while (*size && (*(*data)++ & (char)0x80)) { + (*size)--; + } + return true; +} + +// Advance in the given buffer, skipping the full length of a pointer encoded +// with the given encoding. +static bool skip_eh_frame_pointer(char** data, size_t* size, + unsigned char encoding) { + switch (encoding_data_size(encoding)) { + case DW_EH_PE_data2: + return advance_buffer(data, size, 2); + case DW_EH_PE_data4: + return advance_buffer(data, size, 4); + case DW_EH_PE_data8: + return advance_buffer(data, size, 8); + case DW_EH_PE_LEB128: + return skip_LEB128(data, size); + } + throw std::runtime_error("unreachable"); +} + +// Specialized implementations for adjust_eh_frame_pointer(). +template <typename T> +static bool adjust_eh_frame_sized_pointer(char** data, size_t* size, + ElfSection* eh_frame, + unsigned int origAddr, Elf* elf) { + if (*size < sizeof(T)) return false; + + serializable<FixedSizeData<T>> pointer(*data, *size, elf->getClass(), + elf->getData()); + mozilla::CheckedInt<T> value = pointer.value; + if (origAddr < eh_frame->getAddr()) { + unsigned int diff = eh_frame->getAddr() - origAddr; + value -= diff; + } else { + unsigned int diff = origAddr - eh_frame->getAddr(); + value += diff; + } + if (!value.isValid()) + throw std::runtime_error("Overflow while adjusting eh_frame"); + pointer.value = value.value(); + pointer.serialize(*data, *size, elf->getClass(), elf->getData()); + return advance_buffer(data, size, sizeof(T)); +} + +// In the given eh_frame section, adjust the pointer with the given encoding, +// pointed to by the given buffer (`data`, `size`), considering the eh_frame +// section was originally at `origAddr`. Also advances in the buffer. +static bool adjust_eh_frame_pointer(char** data, size_t* size, + unsigned char encoding, + ElfSection* eh_frame, unsigned int origAddr, + Elf* elf) { + if ((encoding & 0x70) != DW_EH_PE_pcrel) + return skip_eh_frame_pointer(data, size, encoding); + + if (encoding & DW_EH_PE_signed) { + switch (encoding_data_size(encoding)) { + case DW_EH_PE_data2: + return adjust_eh_frame_sized_pointer<int16_t>(data, size, eh_frame, + origAddr, elf); + case DW_EH_PE_data4: + return adjust_eh_frame_sized_pointer<int32_t>(data, size, eh_frame, + origAddr, elf); + case DW_EH_PE_data8: + return adjust_eh_frame_sized_pointer<int64_t>(data, size, eh_frame, + origAddr, elf); + } + } else { + switch (encoding_data_size(encoding)) { + case DW_EH_PE_data2: + return adjust_eh_frame_sized_pointer<uint16_t>(data, size, eh_frame, + origAddr, elf); + case DW_EH_PE_data4: + return adjust_eh_frame_sized_pointer<uint32_t>(data, size, eh_frame, + origAddr, elf); + case DW_EH_PE_data8: + return adjust_eh_frame_sized_pointer<uint64_t>(data, size, eh_frame, + origAddr, elf); + } + } + + throw std::runtime_error("Unsupported eh_frame pointer encoding"); +} + +// The eh_frame section may contain "PC"-relative pointers. If we move the +// section, those need to be adjusted. Other type of pointers are relative to +// sections we don't touch. +static void adjust_eh_frame(ElfSection* eh_frame, unsigned int origAddr, + Elf* elf) { + if (eh_frame->getAddr() == origAddr) // nothing to do; + return; + + char* data = const_cast<char*>(eh_frame->getData()); + size_t size = eh_frame->getSize(); + unsigned char LSDAencoding = DW_EH_PE_omit; + unsigned char FDEencoding = DW_EH_PE_absptr; + bool hasZ = false; + + // Decoding of eh_frame based on https://www.airs.com/blog/archives/460 + while (size) { + if (size < sizeof(uint32_t)) goto malformed; + + serializable<FixedSizeData<uint32_t>> entryLength( + data, size, elf->getClass(), elf->getData()); + if (!advance_buffer(&data, &size, sizeof(uint32_t))) goto malformed; + + char* cursor = data; + size_t length = entryLength.value; + + if (length == 0) { + continue; + } + + if (size < sizeof(uint32_t)) goto malformed; + + serializable<FixedSizeData<uint32_t>> id(data, size, elf->getClass(), + elf->getData()); + if (!advance_buffer(&cursor, &length, sizeof(uint32_t))) goto malformed; + + if (id.value == 0) { + // This is a Common Information Entry + if (length < 2) goto malformed; + // Reset LSDA and FDE encodings, and hasZ for subsequent FDEs. + LSDAencoding = DW_EH_PE_omit; + FDEencoding = DW_EH_PE_absptr; + hasZ = false; + // CIE version. Should only be 1 or 3. + char version = *cursor++; + length--; + if (version != 1 && version != 3) { + throw std::runtime_error("Unsupported eh_frame version"); + } + // NUL terminated string. + const char* augmentationString = cursor; + size_t l = strnlen(augmentationString, length - 1); + if (l == length - 1) goto malformed; + if (!advance_buffer(&cursor, &length, l + 1)) goto malformed; + // Skip code alignment factor (LEB128) + if (!skip_LEB128(&cursor, &length)) goto malformed; + // Skip data alignment factor (LEB128) + if (!skip_LEB128(&cursor, &length)) goto malformed; + // Skip return address register (single byte in CIE version 1, LEB128 + // in CIE version 3) + if (version == 1) { + if (!advance_buffer(&cursor, &length, 1)) goto malformed; + } else { + if (!skip_LEB128(&cursor, &length)) goto malformed; + } + // Past this, it's data driven by the contents of the augmentation string. + for (size_t i = 0; i < l; i++) { + if (!length) goto malformed; + switch (augmentationString[i]) { + case 'z': + if (!skip_LEB128(&cursor, &length)) goto malformed; + hasZ = true; + break; + case 'L': + LSDAencoding = *cursor++; + length--; + break; + case 'R': + FDEencoding = *cursor++; + length--; + break; + case 'P': { + unsigned char encoding = (unsigned char)*cursor++; + length--; + if (!adjust_eh_frame_pointer(&cursor, &length, encoding, eh_frame, + origAddr, elf)) + goto malformed; + } break; + default: + goto malformed; + } + } + } else { + // This is a Frame Description Entry + // Starting address + if (!adjust_eh_frame_pointer(&cursor, &length, FDEencoding, eh_frame, + origAddr, elf)) + goto malformed; + + if (LSDAencoding != DW_EH_PE_omit) { + // Skip number of bytes, same size as the starting address. + if (!skip_eh_frame_pointer(&cursor, &length, FDEencoding)) + goto malformed; + if (hasZ) { + if (!skip_LEB128(&cursor, &length)) goto malformed; + } + // pointer to the LSDA. + if (!adjust_eh_frame_pointer(&cursor, &length, LSDAencoding, eh_frame, + origAddr, elf)) + goto malformed; + } + } + + data += entryLength.value; + size -= entryLength.value; + } + return; + +malformed: + throw std::runtime_error("malformed .eh_frame"); +} + +template <typename Rel_Type> +int do_relocation_section(Elf* elf, unsigned int rel_type, + unsigned int rel_type2, bool force) { + ElfDynamic_Section* dyn = elf->getDynSection(); + if (dyn == nullptr) { + fprintf(stderr, "Couldn't find SHT_DYNAMIC section\n"); + return -1; + } + + ElfRel_Section<Rel_Type>* section = + (ElfRel_Section<Rel_Type>*)dyn->getSectionForType(Rel_Type::d_tag); + if (section == nullptr) { + fprintf(stderr, "No relocations\n"); + return -1; + } + assert(section->getType() == Rel_Type::sh_type); + + Elf64_Shdr relhack64_section = {0, + SHT_PROGBITS, + SHF_ALLOC, + 0, + (Elf64_Off)-1LL, + 0, + SHN_UNDEF, + 0, + Elf_Addr::size(elf->getClass()), + Elf_Addr::size(elf->getClass())}; + Elf64_Shdr relhackcode64_section = {0, + SHT_PROGBITS, + SHF_ALLOC | SHF_EXECINSTR, + 0, + (Elf64_Off)-1LL, + 0, + SHN_UNDEF, + 0, + 1, + 0}; + + unsigned int entry_sz = Elf_Addr::size(elf->getClass()); + + // The injected code needs to be executed before any init code in the + // binary. There are three possible cases: + // - The binary has no init code at all. In this case, we will add a + // DT_INIT entry pointing to the injected code. + // - The binary has a DT_INIT entry. In this case, we will interpose: + // we change DT_INIT to point to the injected code, and have the + // injected code call the original DT_INIT entry point. + // - The binary has no DT_INIT entry, but has a DT_INIT_ARRAY. In this + // case, we interpose as well, by replacing the first entry in the + // array to point to the injected code, and have the injected code + // call the original first entry. + // The binary may have .ctors instead of DT_INIT_ARRAY, for its init + // functions, but this falls into the second case above, since .ctors + // are actually run by DT_INIT code. + ElfValue* value = dyn->getValueForType(DT_INIT); + unsigned int original_init = value ? value->getValue() : 0; + ElfSection* init_array = nullptr; + if (!value || !value->getValue()) { + value = dyn->getValueForType(DT_INIT_ARRAYSZ); + if (value && value->getValue() >= entry_sz) + init_array = dyn->getSectionForType(DT_INIT_ARRAY); + } + + Elf_Shdr relhack_section(relhack64_section); + Elf_Shdr relhackcode_section(relhackcode64_section); + auto relhack_ptr = std::make_unique<ElfRelHack_Section>(relhack_section); + auto relhack = relhack_ptr.get(); + + ElfSymtab_Section* symtab = (ElfSymtab_Section*)section->getLink(); + Elf_SymValue* sym = symtab->lookup("__cxa_pure_virtual"); + + std::vector<Rel_Type> new_rels; + std::vector<Rel_Type> init_array_relocs; + size_t init_array_insert = 0; + for (typename std::vector<Rel_Type>::iterator i = section->rels.begin(); + i != section->rels.end(); ++i) { + // We don't need to keep R_*_NONE relocations + if (!ELF64_R_TYPE(i->r_info)) continue; + ElfLocation loc(i->r_offset, elf); + // __cxa_pure_virtual is a function used in vtables to point at pure + // virtual methods. The __cxa_pure_virtual function usually abort()s. + // These functions are however normally never called. In the case + // where they would, jumping to the null address instead of calling + // __cxa_pure_virtual is going to work just as well. So we can remove + // relocations for the __cxa_pure_virtual symbol and null out the + // content at the offset pointed by the relocation. + if (sym) { + if (sym->defined) { + // If we are statically linked to libstdc++, the + // __cxa_pure_virtual symbol is defined in our lib, and we + // have relative relocations (rel_type) for it. + if (ELF64_R_TYPE(i->r_info) == rel_type) { + Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(), + elf->getData()); + if (addr.value == sym->value.getValue()) { + memset((char*)loc.getBuffer(), 0, entry_sz); + continue; + } + } + } else { + // If we are dynamically linked to libstdc++, the + // __cxa_pure_virtual symbol is undefined in our lib, and we + // have absolute relocations (rel_type2) for it. + if ((ELF64_R_TYPE(i->r_info) == rel_type2) && + (sym == &symtab->syms[ELF64_R_SYM(i->r_info)])) { + memset((char*)loc.getBuffer(), 0, entry_sz); + continue; + } + } + } + // Keep track of the relocations associated with the init_array section. + if (init_array && i->r_offset >= init_array->getAddr() && + i->r_offset < init_array->getAddr() + init_array->getSize()) { + init_array_relocs.push_back(*i); + init_array_insert = new_rels.size(); + } else if (!(loc.getSection()->getFlags() & SHF_WRITE) || + (ELF64_R_TYPE(i->r_info) != rel_type)) { + // Don't pack relocations happening in non writable sections. + // Our injected code is likely not to be allowed to write there. + new_rels.push_back(*i); + } else if (i->r_offset & 1) { + // RELR packing doesn't support relocations at an odd address, but + // there shouldn't be any. + new_rels.push_back(*i); + } else { + // With Elf_Rel, the value pointed by the relocation offset is the addend. + // With Elf_Rela, the addend is in the relocation entry, but the elfhacked + // relocation info doesn't contain it. Elfhack relies on the value pointed + // by the relocation offset to also contain the addend. Which is true with + // BFD ld and gold, but not lld, which leaves that nulled out. So if that + // value is nulled out, we update it to the addend. + Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(), elf->getData()); + unsigned int addend = get_addend(&*i, elf); + if (addr.value == 0) { + addr.value = addend; + addr.serialize(const_cast<char*>(loc.getBuffer()), entry_sz, + elf->getClass(), elf->getData()); + } else if (addr.value != addend) { + fprintf(stderr, + "Relocation addend inconsistent with content. Skipping\n"); + return -1; + } + relhack->push_back(i->r_offset); + } + } + + if (init_array) { + // Some linkers create a DT_INIT_ARRAY section that, for all purposes, + // is empty: it only contains 0x0 or 0xffffffff pointers with no + // relocations. In some other cases, there can be null pointers with no + // relocations in the middle of the section. Example: crtend_so.o in the + // Android NDK contains a sized .init_array with a null pointer and no + // relocation, which ends up in all Android libraries, and in some cases it + // ends up in the middle of the final .init_array section. If we have such a + // reusable slot at the beginning of .init_array, we just use it. It we have + // one in the middle of .init_array, we slide its content to move the "hole" + // at the beginning and use it there (we need our injected code to run + // before any other). Otherwise, replace the first entry and keep the + // original pointer. + std::sort(init_array_relocs.begin(), init_array_relocs.end(), + [](Rel_Type& a, Rel_Type& b) { return a.r_offset < b.r_offset; }); + size_t expected = init_array->getAddr(); + const size_t zero = 0; + const size_t all = SIZE_MAX; + const char* data = init_array->getData(); + size_t length = Elf_Addr::size(elf->getClass()); + size_t off = 0; + for (; off < init_array_relocs.size(); off++) { + auto& r = init_array_relocs[off]; + if (r.r_offset >= expected + length && + (memcmp(data + off * length, &zero, length) == 0 || + memcmp(data + off * length, &all, length) == 0)) { + // We found a hole, move the preceding entries. + while (off) { + auto& p = init_array_relocs[--off]; + if (ELF64_R_TYPE(p.r_info) == rel_type) { + unsigned int addend = get_addend(&p, elf); + p.r_offset += length; + set_relative_reloc(&p, elf, addend); + } else { + fprintf(stderr, + "Unsupported relocation type in DT_INIT_ARRAY. Skipping\n"); + return -1; + } + } + break; + } + expected = r.r_offset + length; + } + + if (off == 0) { + // We either found a hole above, and can now use the first entry, + // or the init_array section is effectively empty (see further above) + // and we also can use the first entry. + // Either way, code further below will take care of actually setting + // the right r_info and r_added for the relocation. + Rel_Type rel; + rel.r_offset = init_array->getAddr(); + init_array_relocs.insert(init_array_relocs.begin(), rel); + } else { + // Use relocated value of DT_INIT_ARRAY's first entry for the + // function to be called by the injected code. + auto& rel = init_array_relocs[0]; + unsigned int addend = get_addend(&rel, elf); + if (ELF64_R_TYPE(rel.r_info) == rel_type) { + original_init = addend; + } else if (ELF64_R_TYPE(rel.r_info) == rel_type2) { + ElfSymtab_Section* symtab = (ElfSymtab_Section*)section->getLink(); + original_init = + symtab->syms[ELF64_R_SYM(rel.r_info)].value.getValue() + addend; + } else { + fprintf(stderr, + "Unsupported relocation type for DT_INIT_ARRAY's first entry. " + "Skipping\n"); + return -1; + } + } + + new_rels.insert(std::next(new_rels.begin(), init_array_insert), + init_array_relocs.begin(), init_array_relocs.end()); + } + + unsigned int mprotect_cb = 0; + unsigned int sysconf_cb = 0; + // If there is a relro segment, our injected code will run after the linker + // sets the corresponding pages read-only. We need to make our code change + // that to read-write before applying relocations, which means it needs to + // call mprotect. To do that, we need to find a reference to the mprotect + // symbol. In case the library already has one, we use that, but otherwise, we + // add the symbol. Then the injected code needs to be able to call the + // corresponding function, which means it needs access to a pointer to it. We + // get such a pointer by making the linker apply a relocation for the symbol + // at an address our code can read. The problem here is that there is not much + // relocated space where we can put such a pointer, so we abuse the bss + // section temporarily (it will be restored to a null value before any code + // can actually use it) + if (elf->getSegmentByType(PT_GNU_RELRO)) { + ElfSection* gnu_versym = dyn->getSectionForType(DT_VERSYM); + auto lookup = [&symtab, &gnu_versym](const char* symbol) { + Elf_SymValue* sym_value = symtab->lookup(symbol, STT(FUNC)); + if (!sym_value) { + symtab->syms.emplace_back(); + sym_value = &symtab->syms.back(); + symtab->grow(symtab->syms.size() * symtab->getEntSize()); + sym_value->name = + ((ElfStrtab_Section*)symtab->getLink())->getStr(symbol); + sym_value->info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC); + sym_value->other = STV_DEFAULT; + new (&sym_value->value) ElfLocation(nullptr, 0, ElfLocation::ABSOLUTE); + sym_value->size = 0; + sym_value->defined = false; + + // The DT_VERSYM data (in the .gnu.version section) has the same number + // of entries as the symbols table. Since we added one entry there, we + // need to add one entry here. Zeroes in the extra data means no version + // for that symbol, which is the simplest thing to do. + if (gnu_versym) { + gnu_versym->grow(gnu_versym->getSize() + gnu_versym->getEntSize()); + } + } + return sym_value; + }; + + Elf_SymValue* mprotect = lookup("mprotect"); + Elf_SymValue* sysconf = lookup("sysconf"); + + // Add relocations for the mprotect and sysconf symbols. + auto add_relocation_to = [&new_rels, &symtab, rel_type2]( + Elf_SymValue* symbol, unsigned int location) { + new_rels.emplace_back(); + Rel_Type& rel = new_rels.back(); + memset(&rel, 0, sizeof(rel)); + rel.r_info = ELF64_R_INFO( + std::distance(symtab->syms.begin(), + std::vector<Elf_SymValue>::iterator(symbol)), + rel_type2); + rel.r_offset = location; + return location; + }; + + // Find the beginning of the bss section, and use an aligned location in + // there for the relocation. + for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) { + if (s->getType() != SHT_NOBITS || + (s->getFlags() & (SHF_TLS | SHF_WRITE)) != SHF_WRITE) { + continue; + } + size_t ptr_size = Elf_Addr::size(elf->getClass()); + size_t usable_start = (s->getAddr() + ptr_size - 1) & ~(ptr_size - 1); + size_t usable_end = (s->getAddr() + s->getSize()) & ~(ptr_size - 1); + if (usable_end - usable_start >= 2 * ptr_size) { + mprotect_cb = add_relocation_to(mprotect, usable_start); + sysconf_cb = add_relocation_to(sysconf, usable_start + ptr_size); + break; + } + } + + if (mprotect_cb == 0 || sysconf_cb == 0) { + fprintf(stderr, "Couldn't find .bss. Skipping\n"); + return -1; + } + } + + size_t old_size = section->getSize(); + + section->rels.assign(new_rels.begin(), new_rels.end()); + section->shrink(new_rels.size() * section->getEntSize()); + + auto relhackcode_ptr = std::make_unique<ElfRelHackCode_Section>( + relhackcode_section, *elf, *relhack, original_init, mprotect_cb, + sysconf_cb); + auto relhackcode = relhackcode_ptr.get(); + // Find the first executable section, and insert the relhack code before + // that. The relhack data is inserted between .rel.dyn and .rel.plt. + ElfSection* first_executable = nullptr; + for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) { + if (s->getFlags() & SHF_EXECINSTR) { + first_executable = s; + break; + } + } + + if (!first_executable) { + fprintf(stderr, "Couldn't find executable section. Skipping\n"); + return -1; + } + + // Once the pointers for relhack, relhackcode, and init are inserted, + // their ownership is transferred to the Elf object, which will free + // them when itself is freed. Hence the .release() calls here (and + // the init.release() call later on). Please note that the raw + // pointers will continue to be used after .release(), which is why + // we are caching them (since .release() will end up setting the + // smart pointer's internal raw pointer to nullptr). + + relhack->insertBefore(section); + relhack_ptr.release(); + + relhackcode->insertBefore(first_executable); + relhackcode_ptr.release(); + + // Don't try further if we can't gain from the relocation section size change. + // We account for the fact we're going to split the PT_LOAD before the + // injected code section, so the overhead of the page alignment for section + // needs to be accounted for. + size_t align = first_executable->getSegmentByType(PT_LOAD)->getAlign(); + size_t new_size = relhack->getSize() + section->getSize() + + relhackcode->getSize() + + (relhackcode->getAddr() & (align - 1)); + if (!force && (new_size >= old_size || old_size - new_size < align)) { + fprintf(stderr, "No gain. Skipping\n"); + return -1; + } + + // .eh_frame/.eh_frame_hdr may be between the relocation sections and the + // executable sections. When that happens, we may end up creating a separate + // PT_LOAD for just both of them because they are not considered relocatable. + // But they are, in fact, kind of relocatable, albeit with some manual work. + // Which we'll do here. + ElfSegment* eh_frame_segment = elf->getSegmentByType(PT_GNU_EH_FRAME); + ElfSection* eh_frame_hdr = + eh_frame_segment ? eh_frame_segment->getFirstSection() : nullptr; + // The .eh_frame section usually follows the eh_frame_hdr section. + ElfSection* eh_frame = eh_frame_hdr ? eh_frame_hdr->getNext() : nullptr; + ElfSection* first = eh_frame_hdr; + ElfSection* second = eh_frame; + if (eh_frame && strcmp(eh_frame->getName(), ".eh_frame")) { + // But sometimes it appears *before* the eh_frame_hdr section. + eh_frame = eh_frame_hdr->getPrevious(); + first = eh_frame; + second = eh_frame_hdr; + } + if (eh_frame_hdr && (!eh_frame || strcmp(eh_frame->getName(), ".eh_frame"))) { + throw std::runtime_error( + "Expected to find an .eh_frame section adjacent to .eh_frame_hdr"); + } + if (eh_frame && first->getAddr() > relhack->getAddr() && + second->getAddr() < first_executable->getAddr()) { + // The distance between both sections needs to be preserved because + // eh_frame_hdr contains relative offsets to eh_frame. Well, they could be + // relocated too, but it's not worth the effort for the few number of bytes + // this would save. + Elf64_Off distance = second->getAddr() - first->getAddr(); + Elf64_Addr origAddr = eh_frame->getAddr(); + ElfSection* previous = first->getPrevious(); + first->getShdr().sh_addr = (previous->getAddr() + previous->getSize() + + first->getAddrAlign() - 1) & + ~(first->getAddrAlign() - 1); + second->getShdr().sh_addr = + (first->getAddr() + std::min(first->getSize(), distance) + + second->getAddrAlign() - 1) & + ~(second->getAddrAlign() - 1); + // Re-adjust to keep the original distance. + // If the first section has a smaller alignment requirement than the second, + // the second will be farther away, so we need to adjust the first. + // If the second section has a smaller alignment requirement than the first, + // it will already be at the right distance. + first->getShdr().sh_addr = second->getAddr() - distance; + assert(distance == second->getAddr() - first->getAddr()); + first->markDirty(); + adjust_eh_frame(eh_frame, origAddr, elf); + } + + // Adjust PT_LOAD segments + for (ElfSegment* segment = elf->getSegmentByType(PT_LOAD); segment; + segment = elf->getSegmentByType(PT_LOAD, segment)) { + maybe_split_segment(elf, segment); + } + + // Ensure Elf sections will be at their final location. + elf->normalize(); + auto init = + std::make_unique<ElfLocation>(relhackcode, relhackcode->getEntryPoint()); + if (init_array) { + // Adjust the first DT_INIT_ARRAY entry to point at the injected code + // by transforming its relocation into a relative one pointing to the + // address of the injected code. + Rel_Type* rel = §ion->rels[init_array_insert]; + rel->r_info = ELF64_R_INFO(0, rel_type); // Set as a relative relocation + set_relative_reloc(rel, elf, init->getValue()); + } else { + if (dyn->setValueForType(DT_INIT, init.get())) { + init.release(); + } else { + fprintf(stderr, "Can't grow .dynamic section to set DT_INIT. Skipping\n"); + return -1; + } + } + + // TODO: adjust the value according to the remaining number of relative + // relocations + if (dyn->getValueForType(Rel_Type::d_tag_count)) + dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0)); + + return 0; +} + +static inline int backup_file(const char* name) { + std::string fname(name); + fname += ".bak"; + return rename(name, fname.c_str()); +} + +void do_file(const char* name, bool backup = false, bool force = false) { + std::ifstream file(name, std::ios::in | std::ios::binary); + Elf elf(file); + unsigned int size = elf.getSize(); + fprintf(stderr, "%s: ", name); + if (elf.getType() != ET_DYN) { + fprintf(stderr, "Not a shared object. Skipping\n"); + return; + } + + for (ElfSection* section = elf.getSection(1); section != nullptr; + section = section->getNext()) { + if (section->getName() && + (strncmp(section->getName(), ".elfhack.", 9) == 0)) { + fprintf(stderr, "Already elfhacked. Skipping\n"); + return; + } + } + + int exit = -1; + switch (elf.getMachine()) { + case EM_386: + exit = + do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force); + break; + case EM_X86_64: + exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE, + R_X86_64_64, force); + break; + case EM_ARM: + exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32, + force); + break; + case EM_AARCH64: + exit = do_relocation_section<Elf_Rela>(&elf, R_AARCH64_RELATIVE, + R_AARCH64_ABS64, force); + break; + default: + throw std::runtime_error("unsupported architecture"); + } + if (exit == 0) { + if (!force && (elf.getSize() >= size)) { + fprintf(stderr, "No gain. Skipping\n"); + } else if (backup && backup_file(name) != 0) { + fprintf(stderr, "Couln't create backup file\n"); + } else { + std::ofstream ofile(name, + std::ios::out | std::ios::binary | std::ios::trunc); + elf.write(ofile); + fprintf(stderr, "Reduced by %d bytes\n", size - elf.getSize()); + } + } +} + +void undo_file(const char* name, bool backup = false) { + std::ifstream file(name, std::ios::in | std::ios::binary); + Elf elf(file); + unsigned int size = elf.getSize(); + fprintf(stderr, "%s: ", name); + if (elf.getType() != ET_DYN) { + fprintf(stderr, "Not a shared object. Skipping\n"); + return; + } + + ElfSection *data = nullptr, *text = nullptr; + for (ElfSection* section = elf.getSection(1); section != nullptr; + section = section->getNext()) { + if (section->getName() && (strcmp(section->getName(), elfhack_data) == 0)) + data = section; + if (section->getName() && (strcmp(section->getName(), elfhack_text) == 0)) + text = section; + } + + if (!data || !text) { + fprintf(stderr, "Not elfhacked. Skipping\n"); + return; + } + + // When both elfhack sections are in the same segment, try to merge + // the segment that contains them both and the following segment. + // When the elfhack sections are in separate segments, try to merge + // those segments. + ElfSegment* first = data->getSegmentByType(PT_LOAD); + ElfSegment* second = text->getSegmentByType(PT_LOAD); + if (first == second) { + second = elf.getSegmentByType(PT_LOAD, first); + } + + // Only merge the segments when their flags match. + if (second->getFlags() != first->getFlags()) { + fprintf(stderr, "Couldn't merge PT_LOAD segments. Skipping\n"); + return; + } + // Move sections from the second PT_LOAD to the first, and remove the + // second PT_LOAD segment. + for (std::list<ElfSection*>::iterator section = second->begin(); + section != second->end(); ++section) + first->addSection(*section); + + elf.removeSegment(second); + elf.normalize(); + + if (backup && backup_file(name) != 0) { + fprintf(stderr, "Couln't create backup file\n"); + } else { + std::ofstream ofile(name, + std::ios::out | std::ios::binary | std::ios::trunc); + elf.write(ofile); + fprintf(stderr, "Grown by %d bytes\n", elf.getSize() - size); + } +} + +int main(int argc, char* argv[]) { + int arg; + bool backup = false; + bool force = false; + bool revert = false; + char* lastSlash = rindex(argv[0], '/'); + if (lastSlash != nullptr) rundir = strndup(argv[0], lastSlash - argv[0]); + for (arg = 1; arg < argc; arg++) { + if (strcmp(argv[arg], "-f") == 0) + force = true; + else if (strcmp(argv[arg], "-b") == 0) + backup = true; + else if (strcmp(argv[arg], "-r") == 0) + revert = true; + else if (revert) { + undo_file(argv[arg], backup); + } else + do_file(argv[arg], backup, force); + } + + free(rundir); + return 0; +} diff --git a/build/unix/elfhack/elfxx.h b/build/unix/elfhack/elfxx.h new file mode 100644 index 0000000000..26dce9b9cd --- /dev/null +++ b/build/unix/elfhack/elfxx.h @@ -0,0 +1,700 @@ +/* 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 <stdexcept> +#include <list> +#include <vector> +#include <cstring> +#include <fstream> +#include <algorithm> +#include <elf.h> +#include <asm/byteorder.h> + +// Technically, __*_to_cpu and __cpu_to* function are equivalent, +// so swap can use either of both. +#define def_swap(endian, type, bits) \ + static inline type##bits##_t swap(type##bits##_t i) { \ + return __##endian##bits##_to_cpu(i); \ + } + +class little_endian { + public: + def_swap(le, uint, 16); + def_swap(le, uint, 32); + def_swap(le, uint, 64); + def_swap(le, int, 16); + def_swap(le, int, 32); + def_swap(le, int, 64); +}; + +class big_endian { + public: + def_swap(be, uint, 16); + def_swap(be, uint, 32); + def_swap(be, uint, 64); + def_swap(be, int, 16); + def_swap(be, int, 32); + def_swap(be, int, 64); +}; + +// forward declaration +class ElfSection; +class ElfSegment; +// TODO: Rename Elf_* types +class Elf_Ehdr; +class Elf_Phdr; +class Elf; +class ElfDynamic_Section; +class ElfStrtab_Section; + +template <typename X> +class FixedSizeData { + public: + struct Wrapper { + X value; + }; + typedef Wrapper Type32; + typedef Wrapper Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r) { + r.value = endian::swap(t.value); + } +}; + +class Elf_Ehdr_Traits { + public: + typedef Elf32_Ehdr Type32; + typedef Elf64_Ehdr Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class Elf_Phdr_Traits { + public: + typedef Elf32_Phdr Type32; + typedef Elf64_Phdr Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class Elf_Shdr_Traits { + public: + typedef Elf32_Shdr Type32; + typedef Elf64_Shdr Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class Elf_Dyn_Traits { + public: + typedef Elf32_Dyn Type32; + typedef Elf64_Dyn Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class Elf_Sym_Traits { + public: + typedef Elf32_Sym Type32; + typedef Elf64_Sym Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class Elf_Rel_Traits { + public: + typedef Elf32_Rel Type32; + typedef Elf64_Rel Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class Elf_Rela_Traits { + public: + typedef Elf32_Rela Type32; + typedef Elf64_Rela Type64; + + template <class endian, typename R, typename T> + static void swap(T& t, R& r); +}; + +class ElfValue { + public: + virtual unsigned int getValue() { return 0; } + virtual ElfSection* getSection() { return nullptr; } +}; + +class ElfPlainValue : public ElfValue { + unsigned int value; + + public: + ElfPlainValue(unsigned int val) : value(val){}; + unsigned int getValue() { return value; } +}; + +class ElfLocation : public ElfValue { + ElfSection* section; + unsigned int offset; + + public: + enum position { ABSOLUTE, RELATIVE }; + ElfLocation() : section(nullptr), offset(0){}; + ElfLocation(ElfSection* section, unsigned int off, + enum position pos = RELATIVE); + ElfLocation(unsigned int location, Elf* elf); + unsigned int getValue(); + ElfSection* getSection() { return section; } + const char* getBuffer(); +}; + +class ElfSize : public ElfValue { + ElfSection* section; + + public: + ElfSize(ElfSection* s) : section(s){}; + unsigned int getValue(); + ElfSection* getSection() { return section; } +}; + +class ElfEntSize : public ElfValue { + ElfSection* section; + + public: + ElfEntSize(ElfSection* s) : section(s){}; + unsigned int getValue(); + ElfSection* getSection() { return section; } +}; + +template <typename T> +class serializable : public T::Type64 { + public: + serializable(){}; + serializable(const typename T::Type64& p) : T::Type64(p){}; + + private: + template <typename R> + void init(const char* buf, size_t len, unsigned char ei_data) { + R e; + assert(len >= sizeof(e)); + memcpy(&e, buf, sizeof(e)); + if (ei_data == ELFDATA2LSB) { + T::template swap<little_endian>(e, *this); + return; + } else if (ei_data == ELFDATA2MSB) { + T::template swap<big_endian>(e, *this); + return; + } + throw std::runtime_error("Unsupported ELF data encoding"); + } + + template <typename R> + void serialize(const char* buf, size_t len, unsigned char ei_data) { + assert(len >= sizeof(R)); + if (ei_data == ELFDATA2LSB) { + T::template swap<little_endian>(*this, *(R*)buf); + return; + } else if (ei_data == ELFDATA2MSB) { + T::template swap<big_endian>(*this, *(R*)buf); + return; + } + throw std::runtime_error("Unsupported ELF data encoding"); + } + + public: + serializable(const char* buf, size_t len, unsigned char ei_class, + unsigned char ei_data) { + if (ei_class == ELFCLASS32) { + init<typename T::Type32>(buf, len, ei_data); + return; + } else if (ei_class == ELFCLASS64) { + init<typename T::Type64>(buf, len, ei_data); + return; + } + throw std::runtime_error("Unsupported ELF class"); + } + + serializable(std::ifstream& file, unsigned char ei_class, + unsigned char ei_data) { + if (ei_class == ELFCLASS32) { + typename T::Type32 e; + file.read((char*)&e, sizeof(e)); + init<typename T::Type32>((char*)&e, sizeof(e), ei_data); + return; + } else if (ei_class == ELFCLASS64) { + typename T::Type64 e; + file.read((char*)&e, sizeof(e)); + init<typename T::Type64>((char*)&e, sizeof(e), ei_data); + return; + } + throw std::runtime_error("Unsupported ELF class or data encoding"); + } + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + if (ei_class == ELFCLASS32) { + typename T::Type32 e; + serialize<typename T::Type32>((char*)&e, sizeof(e), ei_data); + file.write((char*)&e, sizeof(e)); + return; + } else if (ei_class == ELFCLASS64) { + typename T::Type64 e; + serialize<typename T::Type64>((char*)&e, sizeof(e), ei_data); + file.write((char*)&e, sizeof(e)); + return; + } + throw std::runtime_error("Unsupported ELF class or data encoding"); + } + + void serialize(char* buf, size_t len, unsigned char ei_class, + unsigned char ei_data) { + if (ei_class == ELFCLASS32) { + serialize<typename T::Type32>(buf, len, ei_data); + return; + } else if (ei_class == ELFCLASS64) { + serialize<typename T::Type64>(buf, len, ei_data); + return; + } + throw std::runtime_error("Unsupported ELF class"); + } + + static inline unsigned int size(unsigned char ei_class) { + if (ei_class == ELFCLASS32) + return sizeof(typename T::Type32); + else if (ei_class == ELFCLASS64) + return sizeof(typename T::Type64); + return 0; + } +}; + +typedef serializable<Elf_Shdr_Traits> Elf_Shdr; + +class Elf { + public: + Elf(std::ifstream& file); + ~Elf(); + + /* index == -1 is treated as index == ehdr.e_shstrndx */ + ElfSection* getSection(int index); + + ElfSection* getSectionAt(Elf64_Off offset); + + ElfSegment* getSegmentByType(unsigned int type, ElfSegment* last = nullptr); + + ElfDynamic_Section* getDynSection(); + + void normalize(); + void write(std::ofstream& file); + + unsigned char getClass(); + unsigned char getData(); + unsigned char getType(); + unsigned char getMachine(); + unsigned int getSize(); + + void insertSegmentAfter(ElfSegment* previous, ElfSegment* segment) { + std::vector<ElfSegment*>::iterator prev = + std::find(segments.begin(), segments.end(), previous); + segments.insert(prev + 1, segment); + } + + void removeSegment(ElfSegment* segment); + + private: + Elf_Ehdr* ehdr; + ElfLocation eh_entry; + ElfStrtab_Section* eh_shstrndx; + ElfSection** sections; + std::vector<ElfSegment*> segments; + ElfSection *shdr_section, *phdr_section; + /* Values used only during initialization */ + Elf_Shdr** tmp_shdr; + std::ifstream* tmp_file; +}; + +class ElfSection { + public: + typedef union { + ElfSection* section; + int index; + } SectionInfo; + + ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent); + + virtual ~ElfSection() { free(data); } + + const char* getName() { return name; } + unsigned int getType() { return shdr.sh_type; } + unsigned int getFlags() { return shdr.sh_flags; } + Elf64_Addr getAddr(); + Elf64_Off getSize() { return shdr.sh_size; } + unsigned int getAddrAlign() { return shdr.sh_addralign; } + unsigned int getEntSize() { return shdr.sh_entsize; } + const char* getData() { return data; } + ElfSection* getLink() { return link; } + SectionInfo getInfo() { return info; } + + void shrink(unsigned int newsize) { + if (newsize < shdr.sh_size) { + shdr.sh_size = newsize; + markDirty(); + } + } + + void grow(unsigned int newsize) { + if (newsize > shdr.sh_size) { + data = static_cast<char*>(realloc(data, newsize)); + memset(data + shdr.sh_size, 0, newsize - shdr.sh_size); + shdr.sh_size = newsize; + markDirty(); + } + } + + Elf64_Off getOffset(); + int getIndex(); + Elf_Shdr& getShdr(); + + ElfSection* getNext() { return next; } + ElfSection* getPrevious() { return previous; } + + virtual bool isRelocatable() { + return ((getType() == SHT_SYMTAB) || (getType() == SHT_STRTAB) || + (getType() == SHT_RELA) || (getType() == SHT_HASH) || + (getType() == SHT_NOTE) || (getType() == SHT_REL) || + (getType() == SHT_DYNSYM) || (getType() == SHT_GNU_HASH) || + (getType() == SHT_GNU_verdef) || (getType() == SHT_GNU_verneed) || + (getType() == SHT_GNU_versym) || getSegmentByType(PT_INTERP)) && + (getFlags() & SHF_ALLOC); + } + + void insertAfter(ElfSection* section, bool dirty = true) { + if (previous != nullptr) previous->next = next; + if (next != nullptr) next->previous = previous; + previous = section; + if (section != nullptr) { + next = section->next; + section->next = this; + } else + next = nullptr; + if (next != nullptr) next->previous = this; + if (dirty) markDirty(); + insertInSegments(section->segments); + } + + virtual void insertBefore(ElfSection* section, bool dirty = true) { + if (previous != nullptr) previous->next = next; + if (next != nullptr) next->previous = previous; + next = section; + if (section != nullptr) { + previous = section->previous; + section->previous = this; + } else + previous = nullptr; + if (previous != nullptr) previous->next = this; + if (dirty) markDirty(); + insertInSegments(section->segments); + } + + void markDirty() { + if (link != nullptr) shdr.sh_link = -1; + if (info.index) shdr.sh_info = -1; + shdr.sh_offset = -1; + if (isRelocatable()) shdr.sh_addr = -1; + if (next) next->markDirty(); + } + + virtual void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + if (getType() == SHT_NOBITS) return; + file.seekp(getOffset()); + file.write(data, getSize()); + } + + ElfSegment* getSegmentByType(unsigned int type); + + private: + friend class ElfSegment; + + void addToSegment(ElfSegment* segment) { segments.push_back(segment); } + + void removeFromSegment(ElfSegment* segment) { + std::vector<ElfSegment*>::iterator i = + std::find(segments.begin(), segments.end(), segment); + segments.erase(i, i + 1); + } + + void insertInSegments(std::vector<ElfSegment*>& segs); + + protected: + Elf_Shdr shdr; + char* data; + const char* name; + + private: + ElfSection* link; + SectionInfo info; + ElfSection *next, *previous; + int index; + std::vector<ElfSegment*> segments; +}; + +class ElfSegment { + public: + ElfSegment(Elf_Phdr* phdr); + + unsigned int getType() { return type; } + unsigned int getFlags() { return flags; } + unsigned int getAlign() { return align; } + + ElfSection* getFirstSection() { + return sections.empty() ? nullptr : sections.front(); + } + int getVPDiff() { return v_p_diff; } + unsigned int getFileSize(); + unsigned int getMemSize(); + unsigned int getOffset(); + unsigned int getAddr(); + + void addSection(ElfSection* section); + void removeSection(ElfSection* section); + + std::list<ElfSection*>::iterator begin() { return sections.begin(); } + std::list<ElfSection*>::iterator end() { return sections.end(); } + + void clear(); + + private: + unsigned int type; + int v_p_diff; // Difference between physical and virtual address + unsigned int flags; + unsigned int align; + std::list<ElfSection*> sections; + // The following are only really used for PT_GNU_RELRO until something + // better is found. + unsigned int vaddr; + unsigned int filesz, memsz; +}; + +class Elf_Ehdr : public serializable<Elf_Ehdr_Traits>, public ElfSection { + public: + Elf_Ehdr(std::ifstream& file, unsigned char ei_class, unsigned char ei_data); + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + serializable<Elf_Ehdr_Traits>::serialize(file, ei_class, ei_data); + } +}; + +class Elf_Phdr : public serializable<Elf_Phdr_Traits> { + public: + Elf_Phdr(){}; + Elf_Phdr(std::ifstream& file, unsigned char ei_class, unsigned char ei_data) + : serializable<Elf_Phdr_Traits>(file, ei_class, ei_data){}; + bool contains(ElfSection* section) { + unsigned int size = section->getSize(); + unsigned int addr = section->getAddr(); + // This may be biased, but should work in most cases + if ((section->getFlags() & SHF_ALLOC) == 0) return false; + // Special case for PT_DYNAMIC. Eventually, this should + // be better handled than special cases + if ((p_type == PT_DYNAMIC) && (section->getType() != SHT_DYNAMIC)) + return false; + // Special case for PT_TLS. + if ((p_type == PT_TLS) && !(section->getFlags() & SHF_TLS)) return false; + return (addr >= p_vaddr) && (addr + size <= p_vaddr + p_memsz); + } +}; + +typedef serializable<Elf_Dyn_Traits> Elf_Dyn; + +struct Elf_DynValue { + unsigned int tag; + ElfValue* value; +}; + +class ElfDynamic_Section : public ElfSection { + public: + ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent); + ~ElfDynamic_Section(); + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data); + + ElfValue* getValueForType(unsigned int tag); + ElfSection* getSectionForType(unsigned int tag); + bool setValueForType(unsigned int tag, ElfValue* val); + + private: + std::vector<Elf_DynValue> dyns; +}; + +typedef serializable<Elf_Sym_Traits> Elf_Sym; + +struct Elf_SymValue { + const char* name; + unsigned char info; + unsigned char other; + ElfLocation value; + unsigned int size; + bool defined; +}; + +#define STT(type) (1 << STT_##type) + +class ElfSymtab_Section : public ElfSection { + public: + ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent); + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data); + + Elf_SymValue* lookup(const char* name, + unsigned int type_filter = STT(OBJECT) | STT(FUNC)); + + // private: // Until we have a real API + std::vector<Elf_SymValue> syms; +}; + +class Elf_Rel : public serializable<Elf_Rel_Traits> { + public: + Elf_Rel() : serializable<Elf_Rel_Traits>(){}; + + Elf_Rel(std::ifstream& file, unsigned char ei_class, unsigned char ei_data) + : serializable<Elf_Rel_Traits>(file, ei_class, ei_data){}; + + static const unsigned int sh_type = SHT_REL; + static const unsigned int d_tag = DT_REL; + static const unsigned int d_tag_count = DT_RELCOUNT; +}; + +class Elf_Rela : public serializable<Elf_Rela_Traits> { + public: + Elf_Rela() : serializable<Elf_Rela_Traits>(){}; + + Elf_Rela(std::ifstream& file, unsigned char ei_class, unsigned char ei_data) + : serializable<Elf_Rela_Traits>(file, ei_class, ei_data){}; + + static const unsigned int sh_type = SHT_RELA; + static const unsigned int d_tag = DT_RELA; + static const unsigned int d_tag_count = DT_RELACOUNT; +}; + +template <class Rel> +class ElfRel_Section : public ElfSection { + public: + ElfRel_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent) + : ElfSection(s, file, parent) { + auto pos = file->tellg(); + file->seekg(shdr.sh_offset); + for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) { + Rel r(*file, parent->getClass(), parent->getData()); + rels.push_back(r); + } + file->seekg(pos); + } + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data) { + for (typename std::vector<Rel>::iterator i = rels.begin(); i != rels.end(); + ++i) + (*i).serialize(file, ei_class, ei_data); + } + // private: // Until we have a real API + std::vector<Rel> rels; +}; + +class ElfStrtab_Section : public ElfSection { + public: + ElfStrtab_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent) + : ElfSection(s, file, parent) { + table.push_back(table_storage(data, shdr.sh_size)); + } + + ~ElfStrtab_Section() { + for (std::vector<table_storage>::iterator t = table.begin() + 1; + t != table.end(); ++t) + delete[] t->buf; + } + + const char* getStr(unsigned int index); + + const char* getStr(const char* string); + + unsigned int getStrIndex(const char* string); + + void serialize(std::ofstream& file, unsigned char ei_class, + unsigned char ei_data); + + private: + struct table_storage { + unsigned int size, used; + char* buf; + + table_storage() : size(4096), used(0), buf(new char[4096]) {} + table_storage(const char* data, unsigned int sz) + : size(sz), used(sz), buf(const_cast<char*>(data)) {} + }; + std::vector<table_storage> table; +}; + +inline unsigned char Elf::getClass() { return ehdr->e_ident[EI_CLASS]; } + +inline unsigned char Elf::getData() { return ehdr->e_ident[EI_DATA]; } + +inline unsigned char Elf::getType() { return ehdr->e_type; } + +inline unsigned char Elf::getMachine() { return ehdr->e_machine; } + +inline unsigned int Elf::getSize() { + ElfSection* section; + for (section = shdr_section /* It's usually not far from the end */; + section->getNext() != nullptr; section = section->getNext()) + ; + return section->getOffset() + section->getSize(); +} + +inline ElfSegment* ElfSection::getSegmentByType(unsigned int type) { + for (std::vector<ElfSegment*>::iterator seg = segments.begin(); + seg != segments.end(); ++seg) + if ((*seg)->getType() == type) return *seg; + return nullptr; +} + +inline void ElfSection::insertInSegments(std::vector<ElfSegment*>& segs) { + for (std::vector<ElfSegment*>::iterator it = segs.begin(); it != segs.end(); + ++it) { + (*it)->addSection(this); + } +} + +inline ElfLocation::ElfLocation(ElfSection* section, unsigned int off, + enum position pos) + : section(section) { + if ((pos == ABSOLUTE) && section) + offset = off - section->getAddr(); + else + offset = off; +} + +inline ElfLocation::ElfLocation(unsigned int location, Elf* elf) { + section = elf->getSectionAt(location); + offset = location - (section ? section->getAddr() : 0); +} + +inline unsigned int ElfLocation::getValue() { + return (section ? section->getAddr() : 0) + offset; +} + +inline const char* ElfLocation::getBuffer() { + return section ? section->getData() + offset : nullptr; +} + +inline unsigned int ElfSize::getValue() { return section->getSize(); } + +inline unsigned int ElfEntSize::getValue() { return section->getEntSize(); } diff --git a/build/unix/elfhack/inject.c b/build/unix/elfhack/inject.c new file mode 100644 index 0000000000..f1a8e36e1c --- /dev/null +++ b/build/unix/elfhack/inject.c @@ -0,0 +1,225 @@ +/* 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 <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <elf.h> + +/* The Android NDK headers define those */ +#undef Elf_Ehdr +#undef Elf_Addr + +#if defined(__LP64__) +# define Elf_Ehdr Elf64_Ehdr +# define Elf_Phdr Elf64_Phdr +# define Elf_Addr Elf64_Addr +# define Elf_Word Elf64_Word +# define Elf_Dyn Elf64_Dyn +#else +# define Elf_Phdr Elf32_Phdr +# define Elf_Ehdr Elf32_Ehdr +# define Elf_Addr Elf32_Addr +# define Elf_Word Elf32_Word +# define Elf_Dyn Elf32_Dyn +#endif + +#ifdef RELRHACK +# include "relrhack.h" +# define mprotect_cb mprotect +# define sysconf_cb sysconf + +#else +// On ARM, PC-relative function calls have a limit in how far they can jump, +// which might not be enough for e.g. libxul.so. The easy way out would be +// to use the long_call attribute, which forces the compiler to generate code +// that can call anywhere, but clang doesn't support the attribute yet +// (https://bugs.llvm.org/show_bug.cgi?id=40623), and while the command-line +// equivalent does exist, it's currently broken +// (https://bugs.llvm.org/show_bug.cgi?id=40624). So we create a manual +// trampoline, corresponding to the code GCC generates with long_call. +# ifdef __arm__ +__attribute__((section(".text._init_trampoline"), naked)) int init_trampoline( + int argc, char** argv, char** env) { + __asm__ __volatile__( + // thumb doesn't allow to use r12/ip with ldr, and thus would require an + // additional push/pop to save/restore the modified register, which would + // also change the call into a blx. It's simpler to switch to arm. + ".arm\n" + " ldr ip, .LADDR\n" + ".LAFTER:\n" + " add ip, pc, ip\n" + " bx ip\n" + ".LADDR:\n" + " .word real_original_init-(.LAFTER+8)\n"); +} +# endif + +// On aarch64, a similar problem exists, but long_call is not an option at all +// (even GCC doesn't support them on aarch64). +# ifdef __aarch64__ +__attribute__((section(".text._init_trampoline"), naked)) int init_trampoline( + int argc, char** argv, char** env) { + __asm__ __volatile__( + " adrp x8, .LADDR\n" + " add x8, x8, :lo12:.LADDR\n" // adrp + add gives us the full address + // for .LADDR + " ldr x0, [x8]\n" // Load the address of real_original_init relative to + // .LADDR + " add x0, x8, x0\n" // Add the address of .LADDR + " br x0\n" // Branch to real_original_init + ".LADDR:\n" + " .xword real_original_init-.LADDR\n"); +} +# endif + +extern __attribute__((visibility("hidden"))) void original_init(int argc, + char** argv, + char** env); + +extern __attribute__((visibility("hidden"))) Elf_Addr relhack[]; +extern __attribute__((visibility("hidden"))) Elf_Addr relhack_end[]; + +extern __attribute__((visibility("hidden"))) int (*mprotect_cb)(void* addr, + size_t len, + int prot); +extern __attribute__((visibility("hidden"))) long (*sysconf_cb)(int name); +extern __attribute__((visibility("hidden"))) char relro_start[]; +extern __attribute__((visibility("hidden"))) char relro_end[]; +#endif + +extern __attribute__((visibility("hidden"))) Elf_Ehdr __ehdr_start; + +static inline __attribute__((always_inline)) void do_relocations( + Elf_Addr* relhack, Elf_Addr* relhack_end) { + Elf_Addr* ptr; + for (Elf_Addr* entry = relhack; entry < relhack_end; entry++) { + if ((*entry & 1) == 0) { + ptr = (Elf_Addr*)((intptr_t)&__ehdr_start + *entry); + *ptr += (intptr_t)&__ehdr_start; + } else { + Elf_Addr bits = *entry; + Elf_Addr* end = ptr + 8 * sizeof(Elf_Addr) - 1; + do { + ptr++; + bits >>= 1; + if (bits & 1) { + *ptr += (intptr_t)&__ehdr_start; + } + } while (ptr < end); + } + } +} + +#ifndef RELRHACK +__attribute__((section(".text._init_noinit"))) int init_noinit(int argc, + char** argv, + char** env) { + do_relocations(relhack, relhack_end); + return 0; +} + +__attribute__((section(".text._init"))) int init(int argc, char** argv, + char** env) { + do_relocations(relhack, relhack_end); + original_init(argc, argv, env); + // Ensure there is no tail-call optimization, avoiding the use of the + // B.W instruction in Thumb for the call above. + return 0; +} +#endif + +static inline __attribute__((always_inline)) void do_relocations_with_relro( + Elf_Addr* relhack, Elf_Addr* relhack_end, char* relro_start, + char* relro_end) { + long page_size = sysconf_cb(_SC_PAGESIZE); + uintptr_t aligned_relro_start = ((uintptr_t)relro_start) & ~(page_size - 1); + // The relro segment may not end at a page boundary. If that's the case, the + // remainder of the page needs to stay read-write, so the last page is never + // set read-only. Thus the aligned relro end is page-rounded down. + uintptr_t aligned_relro_end = ((uintptr_t)relro_end) & ~(page_size - 1); + // By the time the injected code runs, the relro segment is read-only. But + // we want to apply relocations in it, so we set it r/w first. We'll restore + // it to read-only in relro_post. + mprotect_cb((void*)aligned_relro_start, + aligned_relro_end - aligned_relro_start, PROT_READ | PROT_WRITE); + + do_relocations(relhack, relhack_end); + + mprotect_cb((void*)aligned_relro_start, + aligned_relro_end - aligned_relro_start, PROT_READ); +#ifndef RELRHACK + // mprotect_cb and sysconf_cb are allocated in .bss, so we need to restore + // them to a NULL value. + mprotect_cb = NULL; + sysconf_cb = NULL; +#endif +} + +#ifndef RELRHACK +__attribute__((section(".text._init_noinit_relro"))) int init_noinit_relro( + int argc, char** argv, char** env) { + do_relocations_with_relro(relhack, relhack_end, relro_start, relro_end); + return 0; +} + +__attribute__((section(".text._init_relro"))) int init_relro(int argc, + char** argv, + char** env) { + do_relocations_with_relro(relhack, relhack_end, relro_start, relro_end); + original_init(argc, argv, env); + return 0; +} +#else + +extern __attribute__((visibility("hidden"))) Elf_Dyn _DYNAMIC[]; + +static void _relrhack_init(void) { + // Get the location of the SHT_RELR data from the PT_DYNAMIC segment. + uintptr_t elf_header = (uintptr_t)&__ehdr_start; + Elf_Addr* relhack = NULL; + Elf_Word size = 0; + for (Elf_Dyn* dyn = _DYNAMIC; dyn->d_tag != DT_NULL; dyn++) { + if ((dyn->d_tag & ~DT_RELRHACK_BIT) == DT_RELR) { + relhack = (Elf_Addr*)(elf_header + dyn->d_un.d_ptr); + } else if ((dyn->d_tag & ~DT_RELRHACK_BIT) == DT_RELRSZ) { + size = dyn->d_un.d_val; + } + } + + Elf_Addr* relhack_end = (Elf_Addr*)((uintptr_t)relhack + size); + + // Find the location of the PT_GNU_RELRO segment in the program headers. + Elf_Phdr* phdr = (Elf_Phdr*)(elf_header + __ehdr_start.e_phoff); + char* relro_start = NULL; + char* relro_end = NULL; + for (int i = 0; i < __ehdr_start.e_phnum; i++) { + if (phdr[i].p_type == PT_GNU_RELRO) { + relro_start = (char*)(elf_header + phdr[i].p_vaddr); + relro_end = (char*)(relro_start + phdr[i].p_memsz); + break; + } + } + + if (relro_start != relro_end) { + do_relocations_with_relro(relhack, relhack_end, relro_start, relro_end); + } else { + do_relocations(relhack, relhack_end); + } +} + +// The Android CRT doesn't contain an init function. +# ifndef ANDROID +extern __attribute__((visibility("hidden"))) void _init(int argc, char** argv, + char** env); +# endif + +void _relrhack_wrap_init(int argc, char** argv, char** env) { + _relrhack_init(); +# ifndef ANDROID + _init(argc, argv, env); +# endif +} +#endif diff --git a/build/unix/elfhack/inject/copy_source.py b/build/unix/elfhack/inject/copy_source.py new file mode 100644 index 0000000000..02b4f6237e --- /dev/null +++ b/build/unix/elfhack/inject/copy_source.py @@ -0,0 +1,10 @@ +# -*- 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/. + + +def copy(out_file, in_path): + with open(in_path, "r") as fh: + out_file.write(fh.read()) diff --git a/build/unix/elfhack/inject/moz.build b/build/unix/elfhack/inject/moz.build new file mode 100644 index 0000000000..92f48e6c0a --- /dev/null +++ b/build/unix/elfhack/inject/moz.build @@ -0,0 +1,56 @@ +# -*- 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/. + +# dummy library name to avoid skipping building the source here, which +# we only need the object for. +Library("elfhack_inject") + +DIST_INSTALL = False + +stem = CONFIG["TARGET_CPU"] +if CONFIG["RELRHACK"] and CONFIG["OS_TARGET"] == "Android": + stem += "-android" + +gen_src = "%s.c" % stem +GeneratedFile( + gen_src, script="copy_source.py", entry_point="copy", inputs=["../inject.c"] +) + +SOURCES += [ + "!%s" % gen_src, +] + +if CONFIG["RELRHACK"]: + DEFINES["RELRHACK"] = True + LOCAL_INCLUDES += [".."] + +NO_PGO = True + +for v in ("OS_CPPFLAGS", "OS_CFLAGS", "DEBUG", "CLANG_PLUGIN", "OPTIMIZE", "FRAMEPTR"): + flags = [] + idx = 0 + for flag in COMPILE_FLAGS[v]: + if flag == "-isystem": + flags.append("".join(COMPILE_FLAGS[v][idx : idx + 2])) + elif ( + flag.startswith(("-g", "-m", "-I", "-isystem", "--sysroot=")) + or flag == "-fPIC" + ): + flags.append(flag) + idx += 1 + COMPILE_FLAGS[v] = flags + +COMPILE_FLAGS["OS_CFLAGS"] += [ + "-O2", + "-fno-stack-protector", + "-fno-lto", + # The injected code runs early enough that it supporting unwinding is useless. + # Moreover, elfhack doesn't inject the eh_frame section anyways. + "-fno-asynchronous-unwind-tables", +] + +AllowCompilerWarnings() +NoVisibilityFlags() diff --git a/build/unix/elfhack/moz.build b/build/unix/elfhack/moz.build new file mode 100644 index 0000000000..6f8c81af25 --- /dev/null +++ b/build/unix/elfhack/moz.build @@ -0,0 +1,46 @@ +# -*- 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/. + +DIST_INSTALL = False +DIRS += ["inject"] + +if CONFIG["RELRHACK"]: + HOST_SOURCES += [ + "relrhack.cpp", + ] + + HostProgram(CONFIG["RELRHACK_LINKER"]) + + HOST_OS_LIBS += CONFIG["RELRHACK_LIBS"] + + if CONFIG["MOZ_STDCXX_COMPAT"]: + HOST_DEFINES["MOZ_STDCXX_COMPAT"] = True +else: + HOST_SOURCES += [ + "elf.cpp", + "elfhack.cpp", + ] + + HostProgram("elfhack") + + if not CONFIG["CROSS_COMPILE"]: + SOURCES += [ + "dummy.c", + ] + SOURCES["dummy.c"].flags += ["-fno-lto"] + + SOURCES += [ + "test-array.c", + "test-ctors.c", + ] + SOURCES["test-array.c"].flags += ["-fno-lto"] + SOURCES["test-ctors.c"].flags += ["-fno-lto"] + +NO_PGO = True + +COMPILE_FLAGS["OS_CXXFLAGS"] = [ + f for f in COMPILE_FLAGS["OS_CXXFLAGS"] if f != "-fno-exceptions" +] + ["-fexceptions"] diff --git a/build/unix/elfhack/relrhack.cpp b/build/unix/elfhack/relrhack.cpp new file mode 100644 index 0000000000..2d78d783c9 --- /dev/null +++ b/build/unix/elfhack/relrhack.cpp @@ -0,0 +1,567 @@ +/* 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/. */ + +// This program acts as a linker wrapper. Its executable name is meant +// to be that of a linker, and it will find the next linker with the same +// name in $PATH. However, if for some reason the next linker cannot be +// found this way, the caller may pass its path via the --real-linker +// option. +// +// More in-depth background on https://glandium.org/blog/?p=4297 + +#include "relrhack.h" +#include <algorithm> +#include <cstring> +#include <filesystem> +#include <fstream> +#include <iostream> +#include <optional> +#include <spawn.h> +#include <sstream> +#include <stdexcept> +#include <sys/wait.h> +#include <unistd.h> +#include <unordered_map> +#include <utility> +#include <vector> + +namespace fs = std::filesystem; + +class CantSwapSections : public std::runtime_error { + public: + CantSwapSections(const char* what) : std::runtime_error(what) {} +}; + +template <int bits> +struct Elf {}; + +#define ELF(bits) \ + template <> \ + struct Elf<bits> { \ + using Ehdr = Elf##bits##_Ehdr; \ + using Phdr = Elf##bits##_Phdr; \ + using Shdr = Elf##bits##_Shdr; \ + using Dyn = Elf##bits##_Dyn; \ + using Addr = Elf##bits##_Addr; \ + using Word = Elf##bits##_Word; \ + using Off = Elf##bits##_Off; \ + using Verneed = Elf##bits##_Verneed; \ + using Vernaux = Elf##bits##_Vernaux; \ + } + +ELF(32); +ELF(64); + +template <int bits> +struct RelR : public Elf<bits> { + using Elf_Ehdr = typename Elf<bits>::Ehdr; + using Elf_Phdr = typename Elf<bits>::Phdr; + using Elf_Shdr = typename Elf<bits>::Shdr; + using Elf_Dyn = typename Elf<bits>::Dyn; + using Elf_Addr = typename Elf<bits>::Addr; + using Elf_Word = typename Elf<bits>::Word; + using Elf_Off = typename Elf<bits>::Off; + using Elf_Verneed = typename Elf<bits>::Verneed; + using Elf_Vernaux = typename Elf<bits>::Vernaux; + +#define TAG_NAME(t) \ + { t, #t } + class DynInfo { + public: + using Tag = decltype(Elf_Dyn::d_tag); + using Value = decltype(Elf_Dyn::d_un.d_val); + bool is_wanted(Tag tag) const { return tag_names.count(tag); } + void insert(off_t offset, Tag tag, Value val) { + data[tag] = std::make_pair(offset, val); + } + off_t offset(Tag tag) const { return data.at(tag).first; } + bool contains(Tag tag) const { return data.count(tag); } + Value& operator[](Tag tag) { + if (!is_wanted(tag)) { + std::stringstream msg; + msg << "Tag 0x" << std::hex << tag << " is not in DynInfo::tag_names"; + throw std::runtime_error(msg.str()); + } + return data[tag].second; + } + const char* name(Tag tag) const { return tag_names.at(tag); } + + private: + std::unordered_map<Tag, std::pair<off_t, Value>> data; + + const std::unordered_map<Tag, const char*> tag_names = { + TAG_NAME(DT_JMPREL), TAG_NAME(DT_PLTRELSZ), TAG_NAME(DT_RELR), + TAG_NAME(DT_RELRENT), TAG_NAME(DT_RELRSZ), TAG_NAME(DT_RELA), + TAG_NAME(DT_RELASZ), TAG_NAME(DT_RELAENT), TAG_NAME(DT_REL), + TAG_NAME(DT_RELSZ), TAG_NAME(DT_RELENT), TAG_NAME(DT_STRTAB), + TAG_NAME(DT_STRSZ), TAG_NAME(DT_VERNEED), TAG_NAME(DT_VERNEEDNUM), + }; + }; + + // Translate a virtual address into an offset in the file based on the program + // headers' PT_LOAD. + static Elf_Addr get_offset(const std::vector<Elf_Phdr>& phdr, Elf_Addr addr) { + for (const auto& p : phdr) { + if (p.p_type == PT_LOAD && addr >= p.p_vaddr && + addr < p.p_vaddr + p.p_filesz) { + return addr - (p.p_vaddr - p.p_paddr); + } + } + return 0; + } + + static bool hack(std::fstream& f); +}; + +template <typename T> +T read_one_at(std::istream& in, off_t pos) { + T result; + in.seekg(pos, std::ios::beg); + in.read(reinterpret_cast<char*>(&result), sizeof(T)); + return result; +} + +template <typename T> +std::vector<T> read_vector_at(std::istream& in, off_t pos, size_t num) { + std::vector<T> result(num); + in.seekg(pos, std::ios::beg); + in.read(reinterpret_cast<char*>(result.data()), num * sizeof(T)); + return result; +} + +void write_at(std::ostream& out, off_t pos, const char* buf, size_t len) { + out.seekp(pos, std::ios::beg); + out.write(buf, len); +} + +template <typename T> +void write_one_at(std::ostream& out, off_t pos, const T& data) { + write_at(out, pos, reinterpret_cast<const char*>(&data), sizeof(T)); +} + +template <typename T> +void write_vector_at(std::ostream& out, off_t pos, const std::vector<T>& vec) { + write_at(out, pos, reinterpret_cast<const char*>(&vec.front()), + vec.size() * sizeof(T)); +} + +template <int bits> +bool RelR<bits>::hack(std::fstream& f) { + auto ehdr = read_one_at<Elf_Ehdr>(f, 0); + if (ehdr.e_phentsize != sizeof(Elf_Phdr)) { + throw std::runtime_error("Invalid ELF?"); + } + auto phdr = read_vector_at<Elf_Phdr>(f, ehdr.e_phoff, ehdr.e_phnum); + const auto& dyn_phdr = + std::find_if(phdr.begin(), phdr.end(), + [](const auto& p) { return p.p_type == PT_DYNAMIC; }); + if (dyn_phdr == phdr.end()) { + return false; + } + if (dyn_phdr->p_filesz % sizeof(Elf_Dyn)) { + throw std::runtime_error("Invalid ELF?"); + } + auto dyn = read_vector_at<Elf_Dyn>(f, dyn_phdr->p_offset, + dyn_phdr->p_filesz / sizeof(Elf_Dyn)); + off_t dyn_offset = dyn_phdr->p_offset; + DynInfo dyn_info; + for (const auto& d : dyn) { + if (d.d_tag == DT_NULL) { + break; + } + + if (dyn_info.is_wanted(d.d_tag)) { + if (dyn_info.contains(d.d_tag)) { + std::stringstream msg; + msg << dyn_info.name(d.d_tag) << " appears twice?"; + throw std::runtime_error(msg.str()); + } + dyn_info.insert(dyn_offset, d.d_tag, d.d_un.d_val); + } + dyn_offset += sizeof(Elf_Dyn); + } + + // Find the location and size of the SHT_RELR section, which contains the + // packed-relative-relocs. + Elf_Addr relr_off = + dyn_info.contains(DT_RELR) ? get_offset(phdr, dyn_info[DT_RELR]) : 0; + Elf_Off relrsz = dyn_info[DT_RELRSZ]; + const decltype(Elf_Dyn::d_tag) rel_tags[3][2] = { + {DT_REL, DT_RELA}, {DT_RELSZ, DT_RELASZ}, {DT_RELENT, DT_RELAENT}}; + for (const auto& [rel_tag, rela_tag] : rel_tags) { + if (dyn_info.contains(rel_tag) && dyn_info.contains(rela_tag)) { + std::stringstream msg; + msg << "Both " << dyn_info.name(rel_tag) << " and " + << dyn_info.name(rela_tag) << " appear?"; + throw std::runtime_error(msg.str()); + } + } + Elf_Off relent = + dyn_info.contains(DT_RELENT) ? dyn_info[DT_RELENT] : dyn_info[DT_RELAENT]; + + // Estimate the size of the unpacked relative relocations corresponding + // to the SHT_RELR section. + auto relr = read_vector_at<Elf_Addr>(f, relr_off, relrsz / sizeof(Elf_Addr)); + size_t relocs = 0; + for (const auto& entry : relr) { + if ((entry & 1) == 0) { + // LSB is 0, this is a pointer for a single relocation. + relocs++; + } else { + // LSB is 1, remaining bits are a bitmap. Each bit represents a + // relocation. + relocs += __builtin_popcount(entry) - 1; + } + } + // If the packed relocations + some overhead (we pick 4K arbitrarily, the + // real size would require digging into the section sizes of the injected + // .o file, which is not worth the error) is larger than the estimated + // unpacked relocations, we'll just relink without packed relocations. + if (relocs * relent < relrsz + 4096) { + return false; + } + + // Change DT_RELR* tags to add DT_RELRHACK_BIT. + for (const auto tag : {DT_RELR, DT_RELRSZ, DT_RELRENT}) { + write_one_at(f, dyn_info.offset(tag), tag | DT_RELRHACK_BIT); + } + + bool is_glibc = false; + + if (dyn_info.contains(DT_VERNEEDNUM) && dyn_info.contains(DT_VERNEED) && + dyn_info.contains(DT_STRSZ) && dyn_info.contains(DT_STRTAB)) { + // Scan SHT_VERNEED for the GLIBC_ABI_DT_RELR version on the libc + // library. + Elf_Addr verneed_off = get_offset(phdr, dyn_info[DT_VERNEED]); + Elf_Off verneednum = dyn_info[DT_VERNEEDNUM]; + // SHT_STRTAB section, which contains the string table for, among other + // things, the symbol versions in the SHT_VERNEED section. + auto strtab = read_vector_at<char>(f, get_offset(phdr, dyn_info[DT_STRTAB]), + dyn_info[DT_STRSZ]); + // Guarantee a nul character at the end of the string table. + strtab.push_back(0); + while (verneednum--) { + auto verneed = read_one_at<Elf_Verneed>(f, verneed_off); + if (std::string_view{"libc.so.6"} == &strtab.at(verneed.vn_file)) { + is_glibc = true; + Elf_Addr vernaux_off = verneed_off + verneed.vn_aux; + Elf_Addr relr = 0; + Elf_Vernaux reuse; + for (auto n = 0; n < verneed.vn_cnt; n++) { + auto vernaux = read_one_at<Elf_Vernaux>(f, vernaux_off); + if (std::string_view{"GLIBC_ABI_DT_RELR"} == + &strtab.at(vernaux.vna_name)) { + relr = vernaux_off; + } else { + reuse = vernaux; + } + vernaux_off += vernaux.vna_next; + } + // In the case where we do have the GLIBC_ABI_DT_RELR version, we + // need to edit the binary to make the following changes: + // - Remove the GLIBC_ABI_DT_RELR version, we replace it with an + // arbitrary other version entry, which is simpler than completely + // removing it. We need to remove it because older versions of glibc + // don't have the version (after all, that's why the symbol version + // is there in the first place, to avoid running against older versions + // of glibc that don't support packed relocations). + // - Alter the DT_RELR* tags in the dynamic section, so that they + // are not recognized by ld.so, because, while all versions of ld.so + // ignore tags they don't know, glibc's ld.so versions that support + // packed relocations don't want to load a binary that has DT_RELR* + // tags but *not* a dependency on the GLIBC_ABI_DT_RELR version. + if (relr) { + // Don't overwrite vn_aux. + write_at(f, relr, reinterpret_cast<char*>(&reuse), + sizeof(reuse) - sizeof(Elf_Word)); + } + } + verneed_off += verneed.vn_next; + } + } + + // Location of the .rel.plt section. + Elf_Addr jmprel = dyn_info.contains(DT_JMPREL) ? dyn_info[DT_JMPREL] : 0; + if (is_glibc) { +#ifndef MOZ_STDCXX_COMPAT + try { +#endif + // ld.so in glibc 2.16 to 2.23 expects .rel.plt to strictly follow + // .rel.dyn. (https://sourceware.org/bugzilla/show_bug.cgi?id=14341) + // BFD ld places .relr.dyn after .rel.plt, so this works fine, but lld + // places it between both sections, which doesn't work out for us. In that + // case, we want to swap .relr.dyn and .rel.plt. + Elf_Addr rel_end = dyn_info.contains(DT_REL) + ? (dyn_info[DT_REL] + dyn_info[DT_RELSZ]) + : (dyn_info[DT_RELA] + dyn_info[DT_RELASZ]); + if (dyn_info.contains(DT_JMPREL) && dyn_info[DT_PLTRELSZ] && + dyn_info[DT_JMPREL] != rel_end) { + if (dyn_info[DT_RELR] != rel_end) { + throw CantSwapSections("RELR section doesn't follow REL/RELA?"); + } + if (dyn_info[DT_JMPREL] != dyn_info[DT_RELR] + dyn_info[DT_RELRSZ]) { + throw CantSwapSections("PLT REL/RELA doesn't follow RELR?"); + } + auto plt_rel = read_vector_at<char>( + f, get_offset(phdr, dyn_info[DT_JMPREL]), dyn_info[DT_PLTRELSZ]); + // Write the content of both sections swapped, and adjust the + // corresponding PT_DYNAMIC entries. + write_vector_at(f, relr_off, plt_rel); + write_vector_at(f, relr_off + plt_rel.size(), relr); + dyn_info[DT_JMPREL] = rel_end; + dyn_info[DT_RELR] = rel_end + plt_rel.size(); + for (const auto tag : {DT_JMPREL, DT_RELR}) { + write_one_at(f, dyn_info.offset(tag) + sizeof(typename DynInfo::Tag), + dyn_info[tag]); + } + } +#ifndef MOZ_STDCXX_COMPAT + } catch (const CantSwapSections& err) { + // When binary compatibility with older libstdc++/glibc is not enabled, we + // only emit a warning about why swapping the sections is not happening. + std::cerr << "WARNING: " << err.what() << std::endl; + } +#endif + } + + off_t shdr_offset = ehdr.e_shoff; + auto shdr = read_vector_at<Elf_Shdr>(f, ehdr.e_shoff, ehdr.e_shnum); + for (auto& s : shdr) { + // Some tools don't like sections of types they don't know, so change + // SHT_RELR, which might be unknown on older systems, to SHT_PROGBITS. + if (s.sh_type == SHT_RELR) { + s.sh_type = SHT_PROGBITS; + // If DT_RELR has been adjusted to swap with DT_JMPREL, also adjust + // the corresponding SHT_RELR section header. + if (s.sh_addr != dyn_info[DT_RELR]) { + s.sh_offset += dyn_info[DT_RELR] - s.sh_addr; + s.sh_addr = dyn_info[DT_RELR]; + } + write_one_at(f, shdr_offset, s); + } else if (jmprel && (s.sh_addr == jmprel) && + (s.sh_addr != dyn_info[DT_JMPREL])) { + // If DT_JMPREL has been adjusted to swap with DT_RELR, also adjust + // the corresponding section header. + s.sh_offset -= s.sh_addr - dyn_info[DT_JMPREL]; + s.sh_addr = dyn_info[DT_JMPREL]; + write_one_at(f, shdr_offset, s); + } + shdr_offset += sizeof(Elf_Shdr); + } + return true; +} + +std::vector<std::string> get_path() { + std::vector<std::string> result; + std::stringstream stream{std::getenv("PATH")}; + std::string item; + + while (std::getline(stream, item, ':')) { + result.push_back(std::move(item)); + } + + return result; +} + +std::optional<fs::path> next_program(fs::path& this_program, + std::optional<fs::path>& program) { + auto program_name = program ? *program : this_program.filename(); + for (const auto& dir : get_path()) { + auto path = fs::path(dir) / program_name; + auto status = fs::status(path); + if ((status.type() == fs::file_type::regular) && + ((status.permissions() & fs::perms::owner_exec) == + fs::perms::owner_exec) && + !fs::equivalent(path, this_program)) + return path; + } + return std::nullopt; +} + +unsigned char get_elf_class(unsigned char (&e_ident)[EI_NIDENT]) { + if (std::string_view{reinterpret_cast<char*>(e_ident), SELFMAG} != + std::string_view{ELFMAG, SELFMAG}) { + throw std::runtime_error("Not ELF?"); + } +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + if (e_ident[EI_DATA] != ELFDATA2LSB) { + throw std::runtime_error("Not Little Endian ELF?"); + } +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + if (e_ident[EI_DATA] != ELFDATA2MSB) { + throw std::runtime_error("Not Big Endian ELF?"); + } +#else +# error Unknown byte order. +#endif + if (e_ident[EI_VERSION] != 1) { + throw std::runtime_error("Not ELF version 1?"); + } + auto elf_class = e_ident[EI_CLASS]; + if (elf_class != ELFCLASS32 && elf_class != ELFCLASS64) { + throw std::runtime_error("Not 32 or 64-bits ELF?"); + } + return elf_class; +} + +unsigned char get_elf_class(std::istream& in) { + unsigned char e_ident[EI_NIDENT]; + in.read(reinterpret_cast<char*>(e_ident), sizeof(e_ident)); + return get_elf_class(e_ident); +} + +uint16_t get_elf_machine(std::istream& in) { + // As far as e_machine is concerned, both Elf32_Ehdr and Elf64_Ehdr are equal. + Elf32_Ehdr ehdr; + in.read(reinterpret_cast<char*>(&ehdr), sizeof(ehdr)); + // get_elf_class will throw exceptions for the cases we don't handle. + get_elf_class(ehdr.e_ident); + return ehdr.e_machine; +} + +int run_command(std::vector<const char*>& args) { + pid_t child_pid; + if (posix_spawn(&child_pid, args[0], nullptr, nullptr, + const_cast<char* const*>(args.data()), environ) != 0) { + throw std::runtime_error("posix_spawn failed"); + } + + int status; + waitpid(child_pid, &status, 0); + return WEXITSTATUS(status); +} + +int main(int argc, char* argv[]) { + auto this_program = fs::absolute(argv[0]); + + std::vector<const char*> args; + + int i, crti = 0; + std::optional<fs::path> output = std::nullopt; + std::optional<fs::path> real_linker = std::nullopt; + bool shared = false; + bool is_android = false; + uint16_t elf_machine = EM_NONE; + // Scan argv in order to prepare the following: + // - get the output file. That's the file we may need to adjust. + // - get the --real-linker if one was passed. + // - detect whether we're linking a shared library or something else. As of + // now, only shared libraries are handled. Technically speaking, programs + // could be handled as well, but for the purpose of Firefox, that actually + // doesn't work because programs contain a memory allocator that ends up + // being called before the injected code has any chance to apply relocations, + // and the allocator itself needs the relocations to have been applied. + // - detect the position of crti.o so that we can inject our own object + // right after it, and also to detect the machine type to pick the right + // object to inject. + // + // At the same time, we also construct a new list of arguments, with + // --real-linker filtered out. We'll later inject arguments in that list. + for (i = 1, argv++; i < argc && *argv; argv++, i++) { + std::string_view arg{*argv}; + if (arg == "-shared") { + shared = true; + } else if (arg == "-o") { + args.push_back(*(argv++)); + ++i; + output = *argv; + } else if (arg == "--real-linker") { + ++i; + real_linker = *(++argv); + continue; + } else if (elf_machine == EM_NONE) { + auto filename = fs::path(arg).filename(); + if (filename == "crti.o" || filename == "crtbegin_so.o") { + is_android = (filename == "crtbegin_so.o"); + crti = i; + std::fstream f{std::string(arg), f.binary | f.in}; + f.exceptions(f.failbit); + elf_machine = get_elf_machine(f); + } + } + args.push_back(*argv); + } + + if (!output) { + std::cerr << "Could not determine output file." << std::endl; + return 1; + } + + if (!crti) { + std::cerr << "Could not find CRT object on the command line." << std::endl; + return 1; + } + + if (!real_linker || !real_linker->has_parent_path()) { + auto linker = next_program(this_program, real_linker); + if (!linker) { + std::cerr << "Could not find next " + << (real_linker ? real_linker->filename() + : this_program.filename()) + << std::endl; + return 1; + } + real_linker = linker; + } + args.insert(args.begin(), real_linker->c_str()); + args.push_back(nullptr); + + std::string stem; + switch (elf_machine) { + case EM_NONE: + std::cerr << "Could not determine target machine type." << std::endl; + return 1; + case EM_386: + stem = "x86"; + break; + case EM_X86_64: + stem = "x86_64"; + break; + case EM_ARM: + stem = "arm"; + break; + case EM_AARCH64: + stem = "aarch64"; + break; + default: + std::cerr << "Unsupported target machine type." << std::endl; + return 1; + } + if (is_android) { + stem += "-android"; + } + + if (shared) { + std::vector<const char*> hacked_args(args); + auto inject = this_program.parent_path() / "inject" / (stem + ".o"); + hacked_args.insert(hacked_args.begin() + crti + 1, inject.c_str()); + hacked_args.insert(hacked_args.end() - 1, {"-z", "pack-relative-relocs", + "-init=_relrhack_wrap_init"}); + int status = run_command(hacked_args); + if (status) { + return status; + } + bool hacked = false; + try { + std::fstream f{*output, f.binary | f.in | f.out}; + f.exceptions(f.failbit); + auto elf_class = get_elf_class(f); + f.seekg(0, std::ios::beg); + if (elf_class == ELFCLASS32) { + hacked = RelR<32>::hack(f); + } else if (elf_class == ELFCLASS64) { + hacked = RelR<64>::hack(f); + } + } catch (const std::runtime_error& err) { + std::cerr << "Failed to hack " << output->string() << ": " << err.what() + << std::endl; + return 1; + } + if (hacked) { + return 0; + } + } + + return run_command(args); +} diff --git a/build/unix/elfhack/relrhack.h b/build/unix/elfhack/relrhack.h new file mode 100644 index 0000000000..3501f21079 --- /dev/null +++ b/build/unix/elfhack/relrhack.h @@ -0,0 +1,25 @@ +/* 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/. */ + +#ifndef __RELRHACK_H__ +#define __RELRHACK_H__ + +#include <elf.h> + +#define DT_RELRHACK_BIT 0x8000000 + +#ifndef DT_RELRSZ +# define DT_RELRSZ 35 +#endif +#ifndef DT_RELR +# define DT_RELR 36 +#endif +#ifndef DT_RELRENT +# define DT_RELRENT 37 +#endif +#ifndef SHR_RELR +# define SHT_RELR 19 +#endif + +#endif /* __RELRHACK_H__ */ diff --git a/build/unix/elfhack/test-array.c b/build/unix/elfhack/test-array.c new file mode 100644 index 0000000000..21aec3d360 --- /dev/null +++ b/build/unix/elfhack/test-array.c @@ -0,0 +1,8 @@ +/* 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 "test.c" + +__attribute__((section(".init_array"), used)) static void (*init_array[])() = { + end_test, test}; diff --git a/build/unix/elfhack/test-ctors.c b/build/unix/elfhack/test-ctors.c new file mode 100644 index 0000000000..d082411e3d --- /dev/null +++ b/build/unix/elfhack/test-ctors.c @@ -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/. */ + +#include "test.c" + +/* Recent binutils would put .ctors content into a .init_array section */ +__attribute__((section(".manual_ctors"), used)) static void (*ctors[])() = { + (void (*)()) - 1, end_test, test, NULL}; + +__attribute__((section(".init"))) void _init() { + void (**func)() = &ctors[sizeof(ctors) / sizeof(void (*)()) - 1]; + while (*(--func) != (void (*)()) - 1) { + (*func)(); + } +} diff --git a/build/unix/elfhack/test.c b/build/unix/elfhack/test.c new file mode 100644 index 0000000000..f690ad8f6a --- /dev/null +++ b/build/unix/elfhack/test.c @@ -0,0 +1,221 @@ +/* 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/. */ + +#ifdef DEF +DEF(This) +DEF(is) +DEF(a) +DEF(test) +DEF(of) +DEF(string) +DEF(array) +DEF(for) +DEF(use) +DEF(with) +DEF(elfhack) +DEF(to) +DEF(see) +DEF(whether) +DEF(it) +DEF(breaks) +DEF(anything) +DEF(but) +DEF(one) +DEF(needs) +DEF(quite) +DEF(some) +DEF(strings) +DEF(before) +DEF(the) +DEF(program) +DEF(can) +DEF(do) +DEF(its) +DEF(work) +DEF(efficiently) +DEF(Without) +DEF(enough) +DEF(data) +DEF(relocation) +DEF(sections) +DEF(are) +// clang-format off +DEF(not) +// clang-format on +DEF(sufficiently) +DEF(large) +DEF(and) +DEF(injected) +DEF(code) +DEF(wouldnt) +DEF(fit) +DEF(Said) +DEF(otherwise) +DEF(we) +DEF(need) +DEF(more) +DEF(words) +DEF(than) +DEF(up) +DEF(here) +DEF(so) +DEF(that) +DEF(relocations) +DEF(take) +DEF(significant) +DEF(bytes) +DEF(amounts) +DEF(which) +DEF(isnt) +DEF(exactly) +DEF(easily) +DEF(achieved) +DEF(like) +DEF(this) +DEF(Actually) +DEF(I) +DEF(must) +DEF(cheat) +DEF(by) +DEF(including) +DEF(these) +DEF(phrases) +DEF(several) +DEF(times) + +#else +# pragma GCC visibility push(default) +# include <stdlib.h> +# include <stdio.h> + +# define DEF(w) static const char str_##w[] = #w; +# include "test.c" +# undef DEF + +const char* strings[] = { +# define DEF(w) str_##w, +# include "test.c" +# include "test.c" +# include "test.c" +}; + +/* Create a hole between two zones of relative relocations */ +int small_hole[] = {42, 42, 42, 42}; + +const char* strings2[] = { +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +}; + +/* Create a bigger hole between two zones of relative relocations */ +int bigger_hole[] = { + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, +}; + +const char* strings3[] = { +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# undef DEF +}; + +static int ret = 1; + +int print_status() { + fprintf(stderr, "%s\n", ret ? "FAIL" : "PASS"); + return ret; +} + +/* On ARM, this creates a .tbss section before .init_array, which + * elfhack could then pick instead of .init_array. + * Also, when .tbss is big enough, elfhack may wrongfully consider + * following sections as part of the PT_TLS segment. + * Finally, gold makes TLS segments end on an aligned virtual address, + * even when the underlying section ends before that, and elfhack + * sanity checks may yield an error. */ +__thread int foo; +__thread long long int bar[512]; + +/* We need a .bss that can hold at least 2 pointers. The static in + * end_test() plus this variable should do. */ +size_t dummy; + +void end_test() { + static size_t count = 0; + /* Only exit when both constructors have been called */ + if (++count == 2) { + ret = 0; + // Avoid the dummy variable being stripped out at link time because + // it's unused. + dummy = 1; + } +} + +void test() { + int i = 0, j = 0, k = 0; +# define DEF_(a, i, w) \ + if (a[i++] != str_##w) return; +# define DEF(w) DEF_(strings, i, w) +# include "test.c" +# include "test.c" +# include "test.c" +# undef DEF +# define DEF(w) DEF_(strings2, j, w) +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# undef DEF +# define DEF(w) DEF_(strings3, k, w) +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# include "test.c" +# undef DEF + if (i != sizeof(strings) / sizeof(strings[0]) && + j != sizeof(strings2) / sizeof(strings2[0]) && + k != sizeof(strings3) / sizeof(strings3[0])) + fprintf(stderr, "WARNING: Test doesn't cover the whole array\n"); + end_test(); +} + +# pragma GCC visibility pop +#endif diff --git a/build/unix/moz.build b/build/unix/moz.build new file mode 100644 index 0000000000..259e7e9c7d --- /dev/null +++ b/build/unix/moz.build @@ -0,0 +1,12 @@ +# -*- 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/. + +if CONFIG["USE_ELF_HACK"] or CONFIG["RELRHACK"]: + DIRS += ["elfhack"] + +FINAL_TARGET_FILES += [ + "run-mozilla.sh", +] diff --git a/build/unix/mozconfig.asan b/build/unix/mozconfig.asan new file mode 100644 index 0000000000..9c1e7d45e2 --- /dev/null +++ b/build/unix/mozconfig.asan @@ -0,0 +1,14 @@ +. "$topsrcdir/build/unix/mozconfig.unix" + +export LLVM_SYMBOLIZER="$MOZ_FETCHES_DIR/llvm-symbolizer/bin/llvm-symbolizer" +# +# Enable ASan specific code and build workarounds +ac_add_options --enable-address-sanitizer + +# Mandatory options required for ASan builds (both on Linux and Mac) +export MOZ_DEBUG_SYMBOLS=1 +ac_add_options --enable-debug-symbols +ac_add_options --disable-install-strip +ac_add_options --disable-jemalloc +ac_add_options --disable-crashreporter +ac_add_options --disable-profiling diff --git a/build/unix/mozconfig.linux b/build/unix/mozconfig.linux new file mode 100644 index 0000000000..b63cebe59e --- /dev/null +++ b/build/unix/mozconfig.linux @@ -0,0 +1,15 @@ +. "$topsrcdir/build/unix/mozconfig.unix" + +case "$PERFHERDER_EXTRA_OPTIONS" in +base-toolchains*) + # We don't build against wayland for base-toolchain builds. + ;; +x11) + ac_add_options --enable-default-toolkit=cairo-gtk3 + ;; +*) + ac_add_options --enable-default-toolkit=cairo-gtk3-x11-wayland + ;; +esac + +export MOZ_NO_PIE_COMPAT=1 diff --git a/build/unix/mozconfig.linux32 b/build/unix/mozconfig.linux32 new file mode 100644 index 0000000000..8da778465d --- /dev/null +++ b/build/unix/mozconfig.linux32 @@ -0,0 +1,8 @@ +. "$topsrcdir/build/unix/mozconfig.linux" + +export MOZ_LINUX_32_SSE2_STARTUP_ERROR=1 + +CFLAGS="$CFLAGS -march=pentium-m -msse -msse2 -mfpmath=sse" +CXXFLAGS="$CXXFLAGS -march=pentium-m -msse -msse2 -mfpmath=sse" + +ac_add_options --target=i686-pc-linux diff --git a/build/unix/mozconfig.stdcxx b/build/unix/mozconfig.stdcxx new file mode 100644 index 0000000000..0146f3af9a --- /dev/null +++ b/build/unix/mozconfig.stdcxx @@ -0,0 +1,2 @@ +# Avoid dependency on libstdc++ 4.7 +export MOZ_STDCXX_COMPAT=1 diff --git a/build/unix/mozconfig.tsan b/build/unix/mozconfig.tsan new file mode 100644 index 0000000000..f38a16a28f --- /dev/null +++ b/build/unix/mozconfig.tsan @@ -0,0 +1,17 @@ +export LLVM_SYMBOLIZER="$MOZ_FETCHES_DIR/llvm-symbolizer/bin/llvm-symbolizer" + +# Enable TSan specific code and build workarounds +ac_add_options --enable-thread-sanitizer + +# The ThreadSanitizer is not compatible with sandboxing +# (see bug 1182565) +ac_add_options --disable-sandbox + +# These are required by TSan +ac_add_options --disable-jemalloc +ac_add_options --disable-crashreporter +ac_add_options --disable-profiling + +# Keep symbols to symbolize TSan traces +ac_add_options --enable-debug-symbols +ac_add_options --disable-install-strip diff --git a/build/unix/mozconfig.unix b/build/unix/mozconfig.unix new file mode 100644 index 0000000000..05bf666b39 --- /dev/null +++ b/build/unix/mozconfig.unix @@ -0,0 +1,22 @@ +. "$topsrcdir/build/mozconfig.common" + +if [ -n "$FORCE_GCC" ]; then + CC="$MOZ_FETCHES_DIR/gcc/bin/gcc" + CXX="$MOZ_FETCHES_DIR/gcc/bin/g++" + + # We want to make sure we use binutils and other binaries in the tooltool + # package. + mk_add_options "export PATH=$MOZ_FETCHES_DIR/gcc/bin:$MOZ_FETCHES_DIR/binutils/bin:$PATH" +else + # For some builds we don't want to have Clang based static-analysis activated + if [ -z "$DISABLE_CLANG_PLUGIN" ]; then + export ENABLE_CLANG_PLUGIN=1 + fi + + export CFLAGS="$CFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}" + export CXXFLAGS="$CXXFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}" + + mk_add_options "export PATH=$MOZ_FETCHES_DIR/binutils/bin:$PATH" +fi + +. "$topsrcdir/build/unix/mozconfig.stdcxx" diff --git a/build/unix/print-non-newline.sh b/build/unix/print-non-newline.sh new file mode 100755 index 0000000000..5e0cf292d9 --- /dev/null +++ b/build/unix/print-non-newline.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# 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/. + +# +# The purpose of this file is to find the files that do not end with a +# newline. Some compilers fail if the source files do not end with a +# newline. +# + +# +test_file=newline_test +test_dummy=newline_testee +inlist="$*" +broken_list= + +if test "$inlist" = ""; then + echo "Usage: $0 *.c *.cpp"; + exit 0; +fi + +echo "" > $test_file + +for f in $inlist; do + if test -f $f; then + tail -c 1 $f > $test_dummy + if ! `cmp -s $test_file $test_dummy`; then + broken_list="$broken_list $f" + fi + fi +done + +rm -f $test_file $test_dummy +echo $broken_list diff --git a/build/unix/rewrite_sanitizer_dylib.py b/build/unix/rewrite_sanitizer_dylib.py new file mode 100644 index 0000000000..59198b13c8 --- /dev/null +++ b/build/unix/rewrite_sanitizer_dylib.py @@ -0,0 +1,123 @@ +# 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/. + +import os +import re +import shutil +import subprocess +import sys +from argparse import ArgumentParser +from pathlib import Path + +from buildconfig import substs + +""" +Scans the given directories for binaries referencing the AddressSanitizer +runtime library, copies it to the main directory. +""" + +# This is the dylib name pattern +DYLIB_NAME_PATTERN = re.compile(r"libclang_rt\.(a|ub)san_osx_dynamic\.dylib") + + +def resolve_rpath(filename): + otoolOut = subprocess.check_output([substs["OTOOL"], "-l", filename], text=True) + currentCmd = None + + # The lines we need to find look like this: + # ... + # Load command 22 + # cmd LC_RPATH + # cmdsize 80 + # path /home/build/src/clang/bin/../lib/clang/3.8.0/lib/darwin (offset 12) + # Load command 23 + # ... + # Other load command types have a varying number of fields. + for line in otoolOut.splitlines(): + cmdMatch = re.match(r"^\s+cmd ([A-Z_]+)", line) + if cmdMatch is not None: + currentCmd = cmdMatch.group(1) + continue + + if currentCmd == "LC_RPATH": + pathMatch = re.match(r"^\s+path (.*) \(offset \d+\)", line) + if pathMatch is not None: + path = pathMatch.group(1) + if Path(path).is_dir(): + return path + + print(f"@rpath could not be resolved from {filename}", file=sys.stderr) + sys.exit(1) + + +def scan_directory(path): + dylibsCopied = set() + dylibsRequired = set() + + if not path.is_dir(): + print(f"Input path {path} is not a folder", file=sys.stderr) + sys.exit(1) + + for file in path.rglob("*"): + if not file.is_file(): + continue + + # Skip all files that aren't either dylibs or executable + if not (file.suffix == ".dylib" or os.access(str(file), os.X_OK)): + continue + + try: + otoolOut = subprocess.check_output( + [substs["OTOOL"], "-L", str(file)], text=True + ) + except Exception: + # Errors are expected on non-mach executables, ignore them and continue + continue + + for line in otoolOut.splitlines(): + match = DYLIB_NAME_PATTERN.search(line) + + if match is not None: + dylibName = match.group(0) + absDylibPath = line.split()[0] + + dylibsRequired.add(dylibName) + + if dylibName not in dylibsCopied: + if absDylibPath.startswith("@rpath/"): + rpath = resolve_rpath(str(file)) + copyDylibPath = absDylibPath.replace("@rpath", rpath) + else: + copyDylibPath = absDylibPath + + if Path(copyDylibPath).is_file(): + # Copy the runtime once to the main directory, which is passed + # as the argument to this function. + shutil.copy(copyDylibPath, str(path)) + dylibsCopied.add(dylibName) + else: + print( + f"dylib path in {file} was not found at: {copyDylibPath}", + file=sys.stderr, + ) + + break + + dylibsMissing = dylibsRequired - dylibsCopied + if dylibsMissing: + for dylibName in dylibsMissing: + print(f"{dylibName} could not be found", file=sys.stderr) + sys.exit(1) + + +def parse_args(argv=None): + parser = ArgumentParser() + parser.add_argument("paths", metavar="path", type=Path, nargs="+") + return parser.parse_args(argv) + + +if __name__ == "__main__": + args = parse_args() + for d in args.paths: + scan_directory(d) diff --git a/build/unix/run-gprof.sh b/build/unix/run-gprof.sh new file mode 100644 index 0000000000..794d146b94 --- /dev/null +++ b/build/unix/run-gprof.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# 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/. + + +LD_LIBRARY_PATH=. +export LD_LIBRARY_PATH + +PROG=mozilla-bin +PLIBS="" + +for l in *.so components/*.so; do + PLIBS="$PLIBS -incobj $l" +done + +$ECHO /bin/gprof -L. -Lcomponents -all $PLIBS $PROG $PROG.hiout diff --git a/build/unix/run-hiprof.sh b/build/unix/run-hiprof.sh new file mode 100644 index 0000000000..cb4ec851ff --- /dev/null +++ b/build/unix/run-hiprof.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# 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/. + + +LD_LIBRARY_PATH=. +export LD_LIBRARY_PATH + +PROG=mozilla-bin +PLIBS="-L." + +TOOL=hiprof + +for l in ./*.so components/*.so; do + PLIBS="$PLIBS -incobj $l" +done + +$ECHO atom $PROG -tool $TOOL -env threads -toolargs="-calltime -systime" -all $PLIBS + +cd components && ( + for f in lib*.so; do + mv ../$f.$PROG.$TOOL.threads . + done +) diff --git a/build/unix/run-mozilla.sh b/build/unix/run-mozilla.sh new file mode 100755 index 0000000000..876fd7f7e6 --- /dev/null +++ b/build/unix/run-mozilla.sh @@ -0,0 +1,356 @@ +#!/bin/sh +# +# 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/. +cmdname=`basename "$0"` +MOZ_DIST_BIN=`dirname "$0"` +MOZ_DEFAULT_NAME="./${cmdname}-bin" +MOZ_APPRUNNER_NAME="./mozilla-bin" +MOZ_PROGRAM="" + +exitcode=1 +# +## +## Functions +## +########################################################################## +moz_usage() +{ +echo "Usage: ${cmdname} [options] [program]" +echo "" +echo " options:" +echo "" +echo " -g Run in debugger." +echo " --debug" +echo "" +echo " -d debugger Debugger to use." +echo " --debugger debugger" +echo "" +echo " -a debugger_args Arguments passed to [debugger]." +echo " --debugger-args debugger_args" +echo "" +echo " Examples:" +echo "" +echo " Run the mozilla-bin binary" +echo "" +echo " ${cmdname} mozilla-bin" +echo "" +echo " Debug the mozilla-bin binary in gdb" +echo "" +echo " ${cmdname} -g mozilla-bin -d gdb" +echo "" +echo " Run mozilla-bin under valgrind with arguments" +echo "" +echo " ${cmdname} -g -d valgrind -a '--tool=memcheck --leak-check=full' mozilla-bin" +echo "" + return 0 +} +########################################################################## +moz_bail() +{ + message=$1 + echo + echo "$cmdname: $message" + echo + exit 1 +} +########################################################################## +moz_test_binary() +{ + binary=$1 + if [ -f "$binary" ] + then + if [ -x "$binary" ] + then + return 1 + fi + fi + return 0 +} +########################################################################## +moz_get_debugger() +{ + debuggers="ddd gdb dbx bdb native-gdb" + debugger="notfound" + done="no" + for d in $debuggers + do + moz_test_binary /bin/which + if [ $? -eq 1 ] + then + dpath=`which ${d}` + else + dpath=`LC_MESSAGES=C type ${d} | awk '{print $3;}' | sed -e 's/\.$//'` + fi + if [ -x "$dpath" ] + then + debugger=$dpath + break + fi + done + echo $debugger + return 0 +} +########################################################################## +moz_run_program() +{ + prog=$MOZ_PROGRAM + ## + ## Make sure the program is executable + ## + if [ ! -x "$prog" ] + then + moz_bail "Cannot execute $prog." + fi + ## + ## Run the program + ## + exec "$prog" ${1+"$@"} + exitcode=$? +} +########################################################################## +moz_debug_program() +{ + prog=$MOZ_PROGRAM + ## + ## Make sure the program is executable + ## + if [ ! -x "$prog" ] + then + moz_bail "Cannot execute $prog." + fi + if [ -n "$moz_debugger" ] + then + moz_test_binary /bin/which + if [ $? -eq 1 ] + then + debugger=`which $moz_debugger` + else + debugger=`LC_MESSAGES=C type $moz_debugger | awk '{print $3;}' | sed -e 's/\.$//'` + fi + else + debugger=`moz_get_debugger` + fi + if [ -x "$debugger" ] + then +# If you are not using ddd, gdb and know of a way to convey the arguments +# over to the prog then add that here- Gagan Saksena 03/15/00 + case `basename $debugger` in + native-gdb) echo "$debugger $moz_debugger_args --args $prog" ${1+"$@"} + exec "$debugger" $moz_debugger_args --args "$prog" ${1+"$@"} + exitcode=$? + ;; + gdb) echo "$debugger $moz_debugger_args --args $prog" ${1+"$@"} + exec "$debugger" $moz_debugger_args --args "$prog" ${1+"$@"} + exitcode=$? + ;; + ddd) echo "$debugger $moz_debugger_args --gdb -- --args $prog" ${1+"$@"} + exec "$debugger" $moz_debugger_args --gdb -- --args "$prog" ${1+"$@"} + exitcode=$? + ;; + *) echo "$debugger $moz_debugger_args $prog ${1+"$@"}" + exec $debugger $moz_debugger_args "$prog" ${1+"$@"} + exitcode=$? + ;; + esac + else + moz_bail "Could not find a debugger on your system." + fi +} +########################################################################## +## +## Command line arg defaults +## +moz_debug=0 +moz_debugger="" +moz_debugger_args="" +# +## +## Parse the command line +## +while [ $# -gt 0 ] +do + case $1 in + -g | --debug) + moz_debug=1 + shift + ;; + -d | --debugger) + moz_debugger=$2; + if [ "${moz_debugger}" != "" ]; then + shift 2 + else + echo "-d requires an argument" + exit 1 + fi + ;; + -a | --debugger-args) + moz_debugger_args=$2; + if [ "${moz_debugger_args}" != "" ]; then + shift 2 + else + echo "-a requires an argument" + exit 1 + fi + ;; + *) + break; + ;; + esac +done +# +## +## Program name given in $1 +## +if [ $# -gt 0 ] +then + MOZ_PROGRAM=$1 + shift +fi +## +## Program not given, try to guess a default +## +if [ -z "$MOZ_PROGRAM" ] +then + ## + ## Try this script's name with '-bin' appended + ## + if [ -x "$MOZ_DEFAULT_NAME" ] + then + MOZ_PROGRAM=$MOZ_DEFAULT_NAME + ## + ## Try mozilla-bin + ## + elif [ -x "$MOZ_APPRUNNER_NAME" ] + then + MOZ_PROGRAM=$MOZ_APPRUNNER_NAME + fi +fi +# +# +## +## Make sure the program is executable +## +if [ ! -x "$MOZ_PROGRAM" ] +then + moz_bail "Cannot execute $MOZ_PROGRAM." +fi +# +if [ -z "$MRE_HOME" ]; then + MRE_HOME=$MOZ_DIST_BIN +fi +## +## Set LD_LIBRARY_PATH +## +## On Solaris we use $ORIGIN (set in RUNPATH) instead of LD_LIBRARY_PATH +## to locate shared libraries. +## +## When a shared library is a symbolic link, $ORIGIN will be replaced with +## the real path (i.e., what the symbolic link points to) by the runtime +## linker. For example, if dist/bin/libxul.so is a symbolic link to +## toolkit/library/libxul.so, $ORIGIN will be "toolkit/library" instead of "dist/bin". +## So the runtime linker will use "toolkit/library" NOT "dist/bin" to locate the +## other shared libraries that libxul.so depends on. This only happens +## when a user (developer) tries to start firefox, thunderbird, or seamonkey +## under dist/bin. To solve the problem, we should rely on LD_LIBRARY_PATH +## to locate shared libraries. +## +## Note: +## We test $MOZ_DIST_BIN/*.so. If any of them is a symbolic link, +## we need to set LD_LIBRARY_PATH. +########################################################################## +moz_should_set_ld_library_path() +{ + [ `uname -s` != "SunOS" ] && return 0 + for sharedlib in $MOZ_DIST_BIN/*.so + do + [ -h $sharedlib ] && return 0 + done + return 1 +} +if moz_should_set_ld_library_path +then + LD_LIBRARY_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"} +fi + +if [ -n "$LD_LIBRARYN32_PATH" ] +then + LD_LIBRARYN32_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARYN32_PATH:+":$LD_LIBRARYN32_PATH"} +fi +if [ -n "$LD_LIBRARYN64_PATH" ] +then + LD_LIBRARYN64_PATH=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARYN64_PATH:+":$LD_LIBRARYN64_PATH"} +fi +if [ -n "$LD_LIBRARY_PATH_64" ]; then + LD_LIBRARY_PATH_64=${MOZ_DIST_BIN}:${MOZ_DIST_BIN}/plugins:${MRE_HOME}${LD_LIBRARY_PATH_64:+":$LD_LIBRARY_PATH_64"} +fi +# +# +## Set SHLIB_PATH for HPUX +SHLIB_PATH=${MOZ_DIST_BIN}:${MRE_HOME}${SHLIB_PATH:+":$SHLIB_PATH"} +# +## Set LIBPATH for AIX +LIBPATH=${MOZ_DIST_BIN}:${MRE_HOME}${LIBPATH:+":$LIBPATH"} +# +## Set DYLD_LIBRARY_PATH for Mac OS X (Darwin) +DYLD_LIBRARY_PATH=${MOZ_DIST_BIN}:${MRE_HOME}${DYLD_LIBRARY_PATH:+":$DYLD_LIBRARY_PATH"} +# +## Solaris Xserver(Xsun) tuning - use shared memory transport if available +if [ "$XSUNTRANSPORT" = "" ] +then + XSUNTRANSPORT="shmem" + XSUNSMESIZE="512" + export XSUNTRANSPORT XSUNSMESIZE +fi + +# Disable Gnome crash dialog +GNOME_DISABLE_CRASH_DIALOG=1 +export GNOME_DISABLE_CRASH_DIALOG + +if [ "$moz_debug" -eq 1 ] +then + echo " LD_LIBRARY_PATH=$LD_LIBRARY_PATH" + if [ -n "$LD_LIBRARYN32_PATH" ] + then + echo "LD_LIBRARYN32_PATH=$LD_LIBRARYN32_PATH" + fi + if [ -n "$LD_LIBRARYN64_PATH" ] + then + echo "LD_LIBRARYN64_PATH=$LD_LIBRARYN64_PATH" + fi + if [ -n "$LD_LIBRARY_PATH_64" ]; then + echo "LD_LIBRARY_PATH_64=$LD_LIBRARY_PATH_64" + fi + if [ -n "$DISPLAY" ]; then + echo "DISPLAY=$DISPLAY" + fi + if [ -n "$FONTCONFIG_PATH" ]; then + echo "FONTCONFIG_PATH=$FONTCONFIG_PATH" + fi + if [ -n "$MOZILLA_POSTSCRIPT_PRINTER_LIST" ]; then + echo "MOZILLA_POSTSCRIPT_PRINTER_LIST=$MOZILLA_POSTSCRIPT_PRINTER_LIST" + fi + echo "DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH" + echo " LIBRARY_PATH=$LIBRARY_PATH" + echo " SHLIB_PATH=$SHLIB_PATH" + echo " LIBPATH=$LIBPATH" + echo " ADDON_PATH=$ADDON_PATH" + echo " MOZ_PROGRAM=$MOZ_PROGRAM" + echo " MOZ_TOOLKIT=$MOZ_TOOLKIT" + echo " moz_debug=$moz_debug" + echo " moz_debugger=$moz_debugger" + echo "moz_debugger_args=$moz_debugger_args" +fi +# +export LD_LIBRARY_PATH +export SHLIB_PATH LIBPATH LIBRARY_PATH ADDON_PATH DYLD_LIBRARY_PATH + +if [ $moz_debug -eq 1 ] +then + moz_debug_program ${1+"$@"} +else + moz_run_program ${1+"$@"} +fi + +exit $exitcode diff --git a/build/unix/run-third.sh b/build/unix/run-third.sh new file mode 100644 index 0000000000..cb2c661377 --- /dev/null +++ b/build/unix/run-third.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# 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/. + + +LD_LIBRARY_PATH=. +export LD_LIBRARY_PATH + +PROG=mozilla-bin +PLIBS="-L." + +TOOL=third + +for l in ./*.so components/*.so; do + PLIBS="$PLIBS -incobj $l" +done + +$ECHO atom $PROG -tool $TOOL -env threads -g -all $PLIBS -toolargs="-leaks all -before NS_ShutdownXPCOM" + +cd components && ( + for f in lib*.so; do + mv ../$f.$PROG.$TOOL.threads . + done +) diff --git a/build/unix/stdc++compat/hide_std.ld b/build/unix/stdc++compat/hide_std.ld new file mode 100644 index 0000000000..4b3400b0f3 --- /dev/null +++ b/build/unix/stdc++compat/hide_std.ld @@ -0,0 +1,5 @@ +hidden { + local: + # std::thread::_M_start_thread(...) + _ZNSt6thread15_M_start_thread*; +}; diff --git a/build/unix/stdc++compat/moz.build b/build/unix/stdc++compat/moz.build new file mode 100644 index 0000000000..a3681d15d8 --- /dev/null +++ b/build/unix/stdc++compat/moz.build @@ -0,0 +1,24 @@ +# -*- 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/. + +if CONFIG["OS_TARGET"] == "Linux": + Library("stdc++compat") + SOURCES += ["stdc++compat.cpp"] + +if CONFIG["HOST_OS_ARCH"] == "Linux": + HostLibrary("host_stdc++compat") + HOST_SOURCES += [ + "stdc++compat.cpp", + ] + +FORCE_STATIC_LIB = True + +NO_PGO = True + +DisableStlWrapping() +COMPILE_FLAGS["CLANG_PLUGIN"] = [] + +OS_LIBS += ["-Wl,--version-script,%s/hide_std.ld" % SRCDIR] diff --git a/build/unix/stdc++compat/stdc++compat.cpp b/build/unix/stdc++compat/stdc++compat.cpp new file mode 100644 index 0000000000..0180f6bcfa --- /dev/null +++ b/build/unix/stdc++compat/stdc++compat.cpp @@ -0,0 +1,196 @@ +/* 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 <ostream> +#include <istream> +#include <sstream> +#include <memory> +#include <string> +#include <stdarg.h> +#include <stdio.h> +#include <mozilla/Assertions.h> +#include <cxxabi.h> + +/* + GLIBCXX_3.4.19 is from gcc 4.8.1 (199309) + GLIBCXX_3.4.20 is from gcc 4.9.0 (199307) + GLIBCXX_3.4.21 is from gcc 5.0 (210290) + GLIBCXX_3.4.22 is from gcc 6.0 (222482) + GLIBCXX_3.4.23 is from gcc 7 + GLIBCXX_3.4.24 is from gcc 8 + GLIBCXX_3.4.25 is from gcc 8 + GLIBCXX_3.4.26 is from gcc 9 + GLIBCXX_3.4.27 is from gcc 10 + GLIBCXX_3.4.28 is from gcc 10 + GLIBCXX_3.4.29 is from gcc 11 + +This file adds the necessary compatibility tricks to avoid symbols with +version GLIBCXX_3.4.20 and bigger, keeping binary compatibility with +libstdc++ 4.8.1. + +WARNING: all symbols from this file must be defined weak when they +overlap with libstdc++. +*/ + +namespace std { + +/* We shouldn't be throwing exceptions at all, but it sadly turns out + we call STL (inline) functions that do. This avoids the GLIBCXX_3.4.20 + symbol version. */ +void __attribute__((weak)) __throw_out_of_range_fmt(char const* fmt, ...) { + va_list ap; + char buf[1024]; // That should be big enough. + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + buf[sizeof(buf) - 1] = 0; + va_end(ap); + + __throw_range_error(buf); +} + +} // namespace std + +namespace __cxxabiv1 { +/* Calls to this function are added by the compiler itself on `new Class[n]` + * calls. This avoids the GLIBCXX_3.4.20 symbol version. */ +extern "C" void __attribute__((weak)) __cxa_throw_bad_array_new_length() { + MOZ_CRASH(); +} +} // namespace __cxxabiv1 + +#if _GLIBCXX_RELEASE >= 11 +namespace std { + +/* This avoids the GLIBCXX_3.4.29 symbol version. */ +void __attribute__((weak)) __throw_bad_array_new_length() { MOZ_CRASH(); } + +} // namespace std +#endif + +/* While we generally don't build with exceptions, we have some host tools + * that do use them. libstdc++ from GCC 5.0 added exception constructors with + * char const* argument. Older versions only have a constructor with + * std::string. This avoids the GLIBCXX_3.4.21 symbol version. */ +namespace std { +__attribute__((weak)) runtime_error::runtime_error(char const* s) + : runtime_error(std::string(s)) {} +__attribute__((weak)) out_of_range::out_of_range(char const* s) + : out_of_range(std::string(s)) {} +__attribute__((weak)) invalid_argument::invalid_argument(char const* s) + : invalid_argument(std::string(s)) {} +} // namespace std + +/* Expose the definitions for the old ABI, allowing us to call its functions */ +#define _GLIBCXX_THREAD_ABI_COMPAT 1 +#include <thread> + +namespace std { +/* The old ABI has a thread::_M_start_thread(shared_ptr<_Impl_base>), + * while the new has thread::_M_start_thread(unique_ptr<_State>, void(*)()). + * There is an intermediate ABI at version 3.4.21, with + * thread::_M_start_thread(shared_ptr<_Impl_base>, void(*)()). + * The void(*)() parameter is only there to keep a reference to pthread_create + * on the caller side, and is unused in the implementation + * We're creating an entry point for the new and intermediate ABIs, and make + * them call the old ABI. This avoids the GLIBCXX_3.4.21 symbol version. */ +__attribute__((weak)) void thread::_M_start_thread(shared_ptr<_Impl_base> impl, + void (*)()) { + _M_start_thread(std::move(impl)); +} + +/* We need a _Impl_base-derived class wrapping a _State to call the old ABI + * from what we got by diverting the new API. This avoids the GLIBCXX_3.4.22 + * symbol version. */ +struct StateWrapper : public thread::_Impl_base { + unique_ptr<thread::_State> mState; + + StateWrapper(unique_ptr<thread::_State> aState) : mState(std::move(aState)) {} + + void _M_run() override { mState->_M_run(); } +}; + +/* This avoids the GLIBCXX_3.4.22 symbol version. */ +__attribute__((weak)) void thread::_M_start_thread(unique_ptr<_State> aState, + void (*)()) { + auto impl = std::make_shared<StateWrapper>(std::move(aState)); + _M_start_thread(std::move(impl)); +} + +/* For some reason this is a symbol exported by new versions of libstdc++, + * even though the destructor is default there too. This avoids the + * GLIBCXX_3.4.22 symbol version. */ +__attribute__((weak)) thread::_State::~_State() = default; + +#if _GLIBCXX_RELEASE >= 9 +// Ideally we'd define +// bool _Sp_make_shared_tag::_S_eq(const type_info& ti) noexcept +// but we wouldn't be able to change its visibility because of the existing +// definition in C++ headers. We do need to change its visibility because we +// don't want it to be shadowing the one provided by libstdc++ itself, because +// it doesn't support RTTI. Not supporting RTTI doesn't matter for Firefox +// itself because it's built with RTTI disabled. +// So we define via the mangled symbol. +// This avoids the GLIBCXX_3.4.26 symbol version. +extern "C" __attribute__((visibility("hidden"))) bool +_ZNSt19_Sp_make_shared_tag5_S_eqERKSt9type_info(const type_info*) noexcept { + return false; +} +#endif + +} // namespace std + +namespace std { +/* Instantiate this template to avoid GLIBCXX_3.4.21 symbol versions + * depending on optimization level */ +template basic_ios<char, char_traits<char>>::operator bool() const; +} // namespace std + +#if !defined(MOZ_ASAN) && !defined(MOZ_TSAN) +/* operator delete with size is only available in CXXAPI_1.3.9, equivalent to + * GLIBCXX_3.4.21. */ +void operator delete(void* ptr, size_t size) noexcept(true) { + ::operator delete(ptr); +} +#endif + +namespace std { +/* Instantiate this template to avoid GLIBCXX_3.4.23 symbol versions + * depending on optimization level */ +template basic_string<char, char_traits<char>, allocator<char>>::basic_string( + const basic_string&, size_t, const allocator<char>&); + +#if _GLIBCXX_RELEASE >= 9 +// This avoids the GLIBCXX_3.4.26 symbol version. +template basic_stringstream<char, char_traits<char>, + allocator<char>>::basic_stringstream(); + +template basic_ostringstream<char, char_traits<char>, + allocator<char>>::basic_ostringstream(); +#endif + +#if _GLIBCXX_RELEASE >= 11 +// This avoids the GLIBCXX_3.4.29 symbol version. +template void basic_string<char, char_traits<char>, allocator<char>>::reserve(); + +template void +basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>::reserve(); +#endif + +} // namespace std + +/* The __cxa_thread_atexit_impl symbol is only available on GLIBC 2.18, but we + * want things to keep working on 2.17. It's not actually used directly from + * C++ code, but through __cxa_thead_atexit in libstdc++. The problem we have, + * though, is that rust's libstd also uses it, introducing a dependency we + * don't actually want. Fortunately, we can fall back to libstdc++'s wrapper + * (which, on systems without __cxa_thread_atexit_impl, has its own compatible + * implementation). + * The __cxa_thread_atexit symbol itself is marked CXXABI_1.3.7, which is + * equivalent to GLIBCXX_3.4.18. + */ +extern "C" int __cxa_thread_atexit_impl(void (*dtor)(void*), void* obj, + void* dso_handle) { + return __cxxabiv1::__cxa_thread_atexit(dtor, obj, dso_handle); +} diff --git a/build/update-settings.ini b/build/update-settings.ini new file mode 100644 index 0000000000..9bbd40aca5 --- /dev/null +++ b/build/update-settings.ini @@ -0,0 +1,11 @@ +#if 0 +; 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/. +#endif +; If you modify this file updates may fail. +; Do not modify this file. + +#filter substitution +[Settings] +ACCEPTED_MAR_CHANNEL_IDS=@ACCEPTED_MAR_CHANNEL_IDS@ diff --git a/build/upload.py b/build/upload.py new file mode 100644 index 0000000000..75eb163b24 --- /dev/null +++ b/build/upload.py @@ -0,0 +1,106 @@ +#!/usr/bin/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/. +# +# When run directly, this script expects the following environment variables +# to be set: +# UPLOAD_PATH : path on that host to put the files in +# +# Files are simply copied to UPLOAD_PATH. +# +# All files to be uploaded should be passed as commandline arguments to this +# script. The script takes one other parameter, --base-path, which you can use +# to indicate that files should be uploaded including their paths relative +# to the base path. + +import os +import shutil +import sys +from optparse import OptionParser + + +def OptionalEnvironmentVariable(v): + """Return the value of the environment variable named v, or None + if it's unset (or empty).""" + if v in os.environ and os.environ[v] != "": + return os.environ[v] + return None + + +def FixupMsysPath(path): + """MSYS helpfully translates absolute pathnames in environment variables + and commandline arguments into Windows native paths. This sucks if you're + trying to pass an absolute path on a remote server. This function attempts + to un-mangle such paths.""" + if "OSTYPE" in os.environ and os.environ["OSTYPE"] == "msys": + # sort of awful, find out where our shell is (should be in msys2/usr/bin + # or msys/bin) and strip the first part of that path out of the other path + if "SHELL" in os.environ: + sh = os.environ["SHELL"] + msys = sh[: sh.find("/bin")] + if path.startswith(msys): + path = path[len(msys) :] + return path + + +def GetBaseRelativePath(path, local_file, base_path): + """Given a remote path to upload to, a full path to a local file, and an + optional full path that is a base path of the local file, construct the + full remote path to place the file in. If base_path is not None, include + the relative path from base_path to file.""" + if base_path is None or not local_file.startswith(base_path): + return path + + dir = os.path.dirname(local_file) + # strip base_path + extra slash and make it unixy + dir = dir[len(base_path) + 1 :].replace("\\", "/") + return path + dir + + +def CopyFilesLocally(path, files, verbose=False, base_path=None): + """Copy each file in the list of files to `path`. The `base_path` argument is treated + as it is by UploadFiles.""" + if not path.endswith("/"): + path += "/" + if base_path is not None: + base_path = os.path.abspath(base_path) + for file in files: + file = os.path.abspath(file) + if not os.path.isfile(file): + raise IOError("File not found: %s" % file) + # first ensure that path exists remotely + target_path = GetBaseRelativePath(path, file, base_path) + if not os.path.exists(target_path): + os.makedirs(target_path) + if verbose: + print("Copying " + file + " to " + target_path) + shutil.copy(file, target_path) + + +if __name__ == "__main__": + path = OptionalEnvironmentVariable("UPLOAD_PATH") + + if sys.platform == "win32": + if path is not None: + path = FixupMsysPath(path) + + parser = OptionParser(usage="usage: %prog [options] <files>") + parser.add_option( + "-b", + "--base-path", + action="store", + help="Preserve file paths relative to this path when uploading. " + "If unset, all files will be uploaded directly to UPLOAD_PATH.", + ) + (options, args) = parser.parse_args() + if len(args) < 1: + print("You must specify at least one file to upload") + sys.exit(1) + + try: + CopyFilesLocally(path, args, base_path=options.base_path, verbose=True) + except IOError as strerror: + print(strerror) + sys.exit(1) diff --git a/build/upload_generated_sources.py b/build/upload_generated_sources.py new file mode 100644 index 0000000000..3e4b4acd59 --- /dev/null +++ b/build/upload_generated_sources.py @@ -0,0 +1,169 @@ +#!/usr/bin/env/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/. + +import argparse +import gzip +import io +import logging +import os +import sys +import tarfile +import time +from contextlib import contextmanager +from threading import Event, Thread + +import requests +from mozbuild.generated_sources import ( + get_filename_with_digest, + get_s3_region_and_bucket, +) +from requests.packages.urllib3.util.retry import Retry +from six.moves.queue import Queue + +# Arbitrary, should probably measure this. +NUM_WORKER_THREADS = 10 +log = logging.getLogger("upload-generated-sources") +log.setLevel(logging.INFO) + + +@contextmanager +def timed(): + """ + Yield a function that provides the elapsed time in seconds since this + function was called. + """ + start = time.time() + + def elapsed(): + return time.time() - start + + yield elapsed + + +def gzip_compress(data): + """ + Apply gzip compression to `data` and return the result as a `BytesIO`. + """ + b = io.BytesIO() + with gzip.GzipFile(fileobj=b, mode="w") as f: + f.write(data) + b.flush() + b.seek(0) + return b + + +def upload_worker(queue, event, bucket, session_args): + """ + Get `(name, contents)` entries from `queue` and upload `contents` + to S3 with gzip compression using `name` as the key, prefixed with + the SHA-512 digest of `contents` as a hex string. If an exception occurs, + set `event`. + """ + try: + import boto3 + + session = boto3.session.Session(**session_args) + s3 = session.client("s3") + while True: + if event.is_set(): + # Some other thread hit an exception. + return + (name, contents) = queue.get() + pathname = get_filename_with_digest(name, contents) + compressed = gzip_compress(contents) + extra_args = { + "ContentEncoding": "gzip", + "ContentType": "text/plain", + } + log.info( + 'Uploading "{}" ({} bytes)'.format(pathname, len(compressed.getvalue())) + ) + with timed() as elapsed: + s3.upload_fileobj(compressed, bucket, pathname, ExtraArgs=extra_args) + log.info( + 'Finished uploading "{}" in {:0.3f}s'.format(pathname, elapsed()) + ) + queue.task_done() + except Exception: + log.exception("Thread encountered exception:") + event.set() + + +def do_work(artifact, region, bucket): + session_args = {"region_name": region} + session = requests.Session() + retry = Retry(total=5, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504]) + http_adapter = requests.adapters.HTTPAdapter(max_retries=retry) + session.mount("https://", http_adapter) + session.mount("http://", http_adapter) + + if "TASK_ID" in os.environ: + level = os.environ.get("MOZ_SCM_LEVEL", "1") + secrets_url = "http://taskcluster/secrets/v1/secret/project/releng/gecko/build/level-{}/gecko-generated-sources-upload".format( # noqa + level + ) + log.info( + 'Using AWS credentials from the secrets service: "{}"'.format(secrets_url) + ) + res = session.get(secrets_url) + res.raise_for_status() + secret = res.json() + session_args.update( + aws_access_key_id=secret["secret"]["AWS_ACCESS_KEY_ID"], + aws_secret_access_key=secret["secret"]["AWS_SECRET_ACCESS_KEY"], + ) + else: + log.info("Trying to use your AWS credentials..") + + # First, fetch the artifact containing the sources. + log.info('Fetching generated sources artifact: "{}"'.format(artifact)) + with timed() as elapsed: + res = session.get(artifact) + log.info( + "Fetch HTTP status: {}, {} bytes downloaded in {:0.3f}s".format( + res.status_code, len(res.content), elapsed() + ) + ) + res.raise_for_status() + # Create a queue and worker threads for uploading. + q = Queue() + event = Event() + log.info("Creating {} worker threads".format(NUM_WORKER_THREADS)) + for i in range(NUM_WORKER_THREADS): + t = Thread(target=upload_worker, args=(q, event, bucket, session_args)) + t.daemon = True + t.start() + with tarfile.open(fileobj=io.BytesIO(res.content), mode="r|gz") as tar: + # Next, process each file. + for entry in tar: + if event.is_set(): + break + log.info('Queueing "{}"'.format(entry.name)) + q.put((entry.name, tar.extractfile(entry).read())) + # Wait until all uploads are finished. + # We don't use q.join() here because we want to also monitor event. + while q.unfinished_tasks: + if event.wait(0.1): + log.error("Worker thread encountered exception, exiting...") + sys.exit(1) + + +def main(argv): + logging.basicConfig(format="%(levelname)s - %(threadName)s - %(message)s") + parser = argparse.ArgumentParser( + description="Upload generated source files in ARTIFACT to BUCKET in S3." + ) + parser.add_argument("artifact", help="generated-sources artifact from build task") + args = parser.parse_args(argv) + region, bucket = get_s3_region_and_bucket() + + with timed() as elapsed: + do_work(region=region, bucket=bucket, artifact=args.artifact) + log.info("Finished in {:.03f}s".format(elapsed())) + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/build/valgrind/__init__.py b/build/valgrind/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/build/valgrind/__init__.py diff --git a/build/valgrind/cross-architecture.sup b/build/valgrind/cross-architecture.sup new file mode 100644 index 0000000000..49efa69151 --- /dev/null +++ b/build/valgrind/cross-architecture.sup @@ -0,0 +1,204 @@ +# Full list is tracked through meta bug 793882 + +#################### +# Intended leaks # +#################### + +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793534.) + Memcheck:Leak + ... + fun:_ZN7mozilla9SaveToEnvEPKc + ... +} +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793534.) + Memcheck:Leak + ... + fun:SaveToEnv + ... +} +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793549.) + Memcheck:Leak + ... + fun:_ZL13SaveWordToEnvPKcRK12nsTSubstringIcE + ... +} +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793549.) + Memcheck:Leak + ... + fun:SaveWordToEnv + ... +} +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 944133.) + Memcheck:Leak + ... + fun:_ZN13CrashReporter14SetRestartArgsEiPPc + ... +} +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793548.) + Memcheck:Leak + fun:malloc + ... + fun:_Z12ToNewCStringRK10nsACString + fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK10nsACString + ... +} +{ + PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 1345153.) + Memcheck:Leak + fun:malloc + ... + fun:_ZN13CrashReporterL27SetupCrashReporterDirectoryEP7nsIFilePKcS3_PS1_ + ... +} +{ + We purposely leak the StatisticsReporter object + Memcheck:Leak + fun:malloc + fun:moz_xmalloc + fun:operator new + fun:_Z21XRE_CreateStatsObjectv + ... +} +{ + We purposely leak forkserver children's new argv strings. (See bug 1878213.) + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:strdup + ... + fun:_ZN4base17AppProcessBuilder14InitAppProcessEPiPPPc + ... +} +{ + We purposely leak copies of the initial argv/environ to implement setproctitle on Linux. (See bug 1878213.) + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:strdup + fun:_Z17setproctitle_initPPc + ... +} + +#################################### +# Leaks in third party libraries # +#################################### + +{ + See bug 793535 + Memcheck:Leak + fun:calloc + fun:_dlerror_run + fun:dlsym + ... +} +{ + See bug 793611 + Memcheck:Leak + fun:memalign + fun:tls_get_addr_tail + fun:__tls_get_addr + ... +} +{ + See bug 793611 + Memcheck:Leak + fun:memalign + fun:tls_get_addr_tail + fun:___tls_get_addr + ... +} + +################# +# Other leaks # +################# + +{ + Bug 794369 + Memcheck:Leak + fun:malloc + fun:moz_xmalloc + ... + fun:_ZN20mozJSComponentLoader10LoadModuleERN7mozilla12FileLocationE + ... +} +{ + Bug 794370 + Memcheck:Leak + fun:malloc + fun:moz_xmalloc + ... + fun:_ZN22nsComponentManagerImpl15RegisterFactoryERK4nsIDPKcS4_P10nsIFactory + ... +} +{ + Bug 794372 + Memcheck:Leak + fun:malloc + fun:moz_xmalloc + ... + fun:_ZN22nsComponentManagerImpl22RegisterCIDEntryLockedEPKN7mozilla6Module8CIDEntryEPNS_11KnownModuleE + ... +} +{ + Bug 794374 + Memcheck:Leak + fun:malloc + fun:moz_xmalloc + ... + fun:_ZN22nsComponentManagerImpl17ManifestComponentERNS_25ManifestProcessingContextEiPKPc + ... +} +{ + Bug 1017112 + Memcheck:Leak + fun:malloc + ... + fun:PK11_InitPin + fun:_ZN11nsPK11Token12InitPasswordEPKDs + ... +} +{ + We intentionally leak TLS data in the global servo thread-pool until we can free it consistently (https://github.com/rayon-rs/rayon/issues/688) + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + ... + fun:_ZN3std*thread*local*fast*12Key$LT$T$GT$14try_initialize* + ... + fun:_ZN5style5bloom19StyleBloom$LT$E$GT$3new* + ... +} +{ + We intentionally leak TLS data in the global servo thread-pool until we can free it consistently (https://github.com/rayon-rs/rayon/issues/688) + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + ... + fun:_ZN3std*thread*local*fast*12Key$LT$T$GT$14try_initialize* + ... + fun:_ZN5style7sharing26StyleSharingCache$LT$E$GT$3new* + ... +} +{ + Leak in libfontconfig1 in Debian 8 and 9. See bug 1636003. + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcGetPrgname + ... +} + +################# +# Other leaks # +################# +{ + Following frame pointers can lead us to uninitialized stack space + Memcheck:Cond + fun:DoFramePointerStackWalk +} diff --git a/build/valgrind/i386-pc-linux-gnu.sup b/build/valgrind/i386-pc-linux-gnu.sup new file mode 100644 index 0000000000..cfdc37bb00 --- /dev/null +++ b/build/valgrind/i386-pc-linux-gnu.sup @@ -0,0 +1,53 @@ +# Full list is tracked through meta bug 793882 + +#################################### +# Leaks in third party libraries # +#################################### + +{ + Bug 793537 + Memcheck:Leak + ... + obj:/usr/lib/libpango-1.0.so.0.2800.1 + ... +} +{ + Bug 793598 + Memcheck:Leak + ... + obj:/lib/libdbus-1.so.3.4.0 + ... +} +{ + Bug 794366 + Memcheck:Leak + ... + obj:/usr/lib/libgtk-x11-2.0.so.0.1800.9 + ... +} +{ + Bug 794368 + Memcheck:Leak + ... + obj:/usr/lib/libXrandr.so.2.2.0 + ... +} +{ + Bug 794373 + Memcheck:Leak + ... + obj:/lib/libgobject-2.0.so.0.2200.5 + ... +} + +################################### +# Leaks in short lived precesses # +################################### + +{ + Bug 984196 + Memcheck:Leak + ... + fun:glxtest + ... +} diff --git a/build/valgrind/mach_commands.py b/build/valgrind/mach_commands.py new file mode 100644 index 0000000000..047e489e00 --- /dev/null +++ b/build/valgrind/mach_commands.py @@ -0,0 +1,262 @@ +# 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/. + +import json +import logging +import os +import time + +import mozinfo +from mach.decorators import Command, CommandArgument +from mozbuild.base import BinaryNotFoundException +from mozbuild.base import MachCommandConditions as conditions + + +def is_valgrind_build(cls): + """Must be a build with --enable-valgrind and --disable-jemalloc.""" + defines = cls.config_environment.defines + return "MOZ_VALGRIND" in defines and "MOZ_MEMORY" not in defines + + +@Command( + "valgrind-test", + category="testing", + conditions=[conditions.is_firefox_or_thunderbird, is_valgrind_build], + description="Run the Valgrind test job (memory-related errors).", +) +@CommandArgument( + "--suppressions", + default=[], + action="append", + metavar="FILENAME", + help="Specify a suppression file for Valgrind to use. Use " + "--suppression multiple times to specify multiple suppression " + "files.", +) +def valgrind_test(command_context, suppressions): + """ + Run Valgrind tests. + """ + + from mozfile import TemporaryDirectory + from mozhttpd import MozHttpd + from mozprofile import FirefoxProfile, Preferences + from mozprofile.permissions import ServerLocations + from mozrunner import FirefoxRunner + from mozrunner.utils import findInPath + from six import string_types + from valgrind.output_handler import OutputHandler + + build_dir = os.path.join(command_context.topsrcdir, "build") + + # XXX: currently we just use the PGO inputs for Valgrind runs. This may + # change in the future. + httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo")) + httpd.start(block=False) + + with TemporaryDirectory() as profilePath: + # TODO: refactor this into mozprofile + profile_data_dir = os.path.join( + command_context.topsrcdir, "testing", "profiles" + ) + with open(os.path.join(profile_data_dir, "profiles.json"), "r") as fh: + base_profiles = json.load(fh)["valgrind"] + + prefpaths = [ + os.path.join(profile_data_dir, profile, "user.js") + for profile in base_profiles + ] + prefs = {} + for path in prefpaths: + prefs.update(Preferences.read_prefs(path)) + + interpolation = { + "server": "%s:%d" % httpd.httpd.server_address, + } + for k, v in prefs.items(): + if isinstance(v, string_types): + v = v.format(**interpolation) + prefs[k] = Preferences.cast(v) + + quitter = os.path.join( + command_context.topsrcdir, "tools", "quitter", "quitter@mozilla.org.xpi" + ) + + locations = ServerLocations() + locations.add_host( + host="127.0.0.1", port=httpd.httpd.server_port, options="primary" + ) + + profile = FirefoxProfile( + profile=profilePath, + preferences=prefs, + addons=[quitter], + locations=locations, + ) + + firefox_args = [httpd.get_url()] + + env = os.environ.copy() + env["G_SLICE"] = "always-malloc" + env["MOZ_FORCE_DISABLE_E10S"] = "1" + env["MOZ_CC_RUN_DURING_SHUTDOWN"] = "1" + env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" + env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" + env["XPCOM_DEBUG_BREAK"] = "warn" + + outputHandler = OutputHandler(command_context.log) + kp_kwargs = { + "processOutputLine": [outputHandler], + "universal_newlines": True, + } + + valgrind = "valgrind" + if not os.path.exists(valgrind): + valgrind = findInPath(valgrind) + + valgrind_args = [ + valgrind, + "--sym-offsets=yes", + "--smc-check=all-non-file", + "--vex-iropt-register-updates=allregs-at-mem-access", + "--gen-suppressions=all", + "--num-callers=36", + "--leak-check=full", + "--show-possibly-lost=no", + "--track-origins=yes", + "--trace-children=yes", + "--trace-children-skip=*/dbus-launch", + "-v", # Enable verbosity to get the list of used suppressions + # Avoid excessive delays in the presence of spinlocks. + # See bug 1309851. + "--fair-sched=yes", + # Keep debuginfo after library unmap. See bug 1382280. + "--keep-debuginfo=yes", + # Reduce noise level on rustc and/or LLVM compiled code. + # See bug 1365915 + "--expensive-definedness-checks=yes", + # Compensate for the compiler inlining `new` but not `delete` + # or vice versa. + "--show-mismatched-frees=no", + ] + + for s in suppressions: + valgrind_args.append("--suppressions=" + s) + + supps_dir = os.path.join(build_dir, "valgrind") + supps_file1 = os.path.join(supps_dir, "cross-architecture.sup") + valgrind_args.append("--suppressions=" + supps_file1) + + if mozinfo.os == "linux": + machtype = { + "x86_64": "x86_64-pc-linux-gnu", + "x86": "i386-pc-linux-gnu", + }.get(mozinfo.processor) + if machtype: + supps_file2 = os.path.join(supps_dir, machtype + ".sup") + if os.path.isfile(supps_file2): + valgrind_args.append("--suppressions=" + supps_file2) + + exitcode = None + timeout = 2400 + binary_not_found_exception = None + try: + runner = FirefoxRunner( + profile=profile, + binary=command_context.get_binary_path(), + cmdargs=firefox_args, + env=env, + process_args=kp_kwargs, + ) + start_time = time.monotonic() + runner.start(debug_args=valgrind_args) + exitcode = runner.wait(timeout=timeout) + end_time = time.monotonic() + if "MOZ_AUTOMATION" in os.environ: + data = { + "framework": {"name": "build_metrics"}, + "suites": [ + { + "name": "valgrind", + "value": end_time - start_time, + "lowerIsBetter": True, + "shouldAlert": False, + "subtests": [], + } + ], + } + if "TASKCLUSTER_INSTANCE_TYPE" in os.environ: + # Include the instance type so results can be grouped. + data["suites"][0]["extraOptions"] = [ + "taskcluster-%s" % os.environ["TASKCLUSTER_INSTANCE_TYPE"], + ] + command_context.log( + logging.INFO, + "valgrind-perfherder", + {"data": json.dumps(data)}, + "PERFHERDER_DATA: {data}", + ) + except BinaryNotFoundException as e: + binary_not_found_exception = e + finally: + errs = outputHandler.error_count + supps = outputHandler.suppression_count + if errs != supps: + status = 1 # turns the TBPL job orange + command_context.log( + logging.ERROR, + "valgrind-fail-parsing", + {"errs": errs, "supps": supps}, + "TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors " + "seen, but {supps} generated suppressions seen", + ) + + elif errs == 0: + status = 0 + command_context.log( + logging.INFO, + "valgrind-pass", + {}, + "TEST-PASS | valgrind-test | valgrind found no errors", + ) + else: + status = 1 # turns the TBPL job orange + # We've already printed details of the errors. + + if binary_not_found_exception: + status = 2 # turns the TBPL job red + command_context.log( + logging.ERROR, + "valgrind-fail-errors", + {"error": str(binary_not_found_exception)}, + "TEST-UNEXPECTED-FAIL | valgrind-test | {error}", + ) + command_context.log( + logging.INFO, + "valgrind-fail-errors", + {"help": binary_not_found_exception.help()}, + "{help}", + ) + elif exitcode is None: + status = 2 # turns the TBPL job red + command_context.log( + logging.ERROR, + "valgrind-fail-timeout", + {"timeout": timeout}, + "TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out " + "(reached {timeout} second limit)", + ) + elif exitcode != 0: + status = 2 # turns the TBPL job red + command_context.log( + logging.ERROR, + "valgrind-fail-errors", + {"exitcode": exitcode}, + "TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code " + "from Valgrind: {exitcode}", + ) + + httpd.stop() + + return status diff --git a/build/valgrind/output_handler.py b/build/valgrind/output_handler.py new file mode 100644 index 0000000000..613f7f8c1f --- /dev/null +++ b/build/valgrind/output_handler.py @@ -0,0 +1,117 @@ +# 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/. + +import logging +import re + + +class OutputHandler(object): + """ + A class for handling Valgrind output. + + Valgrind errors look like this: + + ==60741== 40 (24 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 2,746 of 5,235 + ==60741== at 0x4C26B43: calloc (vg_replace_malloc.c:593) + ==60741== by 0x63AEF65: PR_Calloc (prmem.c:443) + ==60741== by 0x69F236E: PORT_ZAlloc_Util (secport.c:117) + ==60741== by 0x69F1336: SECITEM_AllocItem_Util (secitem.c:28) + ==60741== by 0xA04280B: ffi_call_unix64 (in /builds/slave/m-in-l64-valgrind-000000000000/objdir/toolkit/library/libxul.so) + ==60741== by 0xA042443: ffi_call (ffi64.c:485) + + For each such error, this class extracts most or all of the first (error + kind) line, plus the function name in each of the first few stack entries. + With this data it constructs and prints a TEST-UNEXPECTED-FAIL message that + TBPL will highlight. + + It buffers these lines from which text is extracted so that the + TEST-UNEXPECTED-FAIL message can be printed before the full error. + + Parsing the Valgrind output isn't ideal, and it may break in the future if + Valgrind changes the format of the messages, or introduces new error kinds. + To protect against this, we also count how many lines containing + "<insert_a_suppression_name_here>" are seen. Thanks to the use of + --gen-suppressions=yes, exactly one of these lines is present per error. If + the count of these lines doesn't match the error count found during + parsing, then the parsing has missed one or more errors and we can fail + appropriately. + """ # NOQA: E501 + + def __init__(self, logger): + # The regexps in this list match all of Valgrind's errors. Note that + # Valgrind is English-only, so we don't have to worry about + # localization. + self.logger = logger + self.re_error = ( + r"==\d+== (" + + r"(Use of uninitialised value of size \d+)|" + + r"(Conditional jump or move depends on uninitialised value\(s\))|" + + r"(Syscall param .* contains uninitialised byte\(s\))|" + + r"(Syscall param .* points to (unaddressable|uninitialised) byte\(s\))|" + + r"((Unaddressable|Uninitialised) byte\(s\) found during client check request)|" + + r"(Invalid free\(\) / delete / delete\[\] / realloc\(\))|" + + r"(Mismatched free\(\) / delete / delete \[\])|" + + r"(Invalid (read|write) of size \d+)|" + + r"(Jump to the invalid address stated on the next line)|" + + r"(Source and destination overlap in .*)|" + + r"(.* bytes in .* blocks are .* lost)" + + r")" + ) + # Match identifer chars, plus ':' for namespaces, and '\?' in order to + # match "???" which Valgrind sometimes produces. + self.re_stack_entry = r"^==\d+==.*0x[A-Z0-9]+: ([A-Za-z0-9_:\?]+)" + self.re_suppression = r" *<insert_a_suppression_name_here>" + self.error_count = 0 + self.suppression_count = 0 + self.number_of_stack_entries_to_get = 0 + self.curr_error = None + self.curr_location = None + self.buffered_lines = None + + def log(self, line): + self.logger(logging.INFO, "valgrind-output", {"line": line}, "{line}") + + def __call__(self, line): + if self.number_of_stack_entries_to_get == 0: + # Look for the start of a Valgrind error. + m = re.search(self.re_error, line) + if m: + self.error_count += 1 + self.number_of_stack_entries_to_get = 4 + self.curr_error = m.group(1) + self.curr_location = "" + self.buffered_lines = [line] + else: + self.log(line) + + else: + # We've recently found a Valgrind error, and are now extracting + # details from the first few stack entries. + self.buffered_lines.append(line) + m = re.match(self.re_stack_entry, line) + if m: + self.curr_location += m.group(1) + else: + self.curr_location += "?!?" + + self.number_of_stack_entries_to_get -= 1 + if self.number_of_stack_entries_to_get != 0: + self.curr_location += " / " + else: + # We've finished getting the first few stack entries. Print the + # failure message and the buffered lines, and then reset state. + self.logger( + logging.ERROR, + "valgrind-error-msg", + {"error": self.curr_error, "location": self.curr_location}, + "TEST-UNEXPECTED-FAIL | valgrind-test | {error} at {location}", + ) + for b in self.buffered_lines: + self.log(b) + self.curr_error = None + self.curr_location = None + self.buffered_lines = None + + if re.match(self.re_suppression, line): + self.suppression_count += 1 diff --git a/build/valgrind/x86_64-pc-linux-gnu.sup b/build/valgrind/x86_64-pc-linux-gnu.sup new file mode 100644 index 0000000000..0887290e5d --- /dev/null +++ b/build/valgrind/x86_64-pc-linux-gnu.sup @@ -0,0 +1,1068 @@ +# Full list is tracked through meta bug 793882 + +#################################### +# Leaks in third party libraries # +#################################### + +{ + Bug 793537 + Memcheck:Leak + ... + obj:/usr/lib64/libpango-1.0.so.0.2800.1 + ... +} +{ + Bug 793598 + Memcheck:Leak + ... + obj:/lib64/libdbus-1.so.3.4.0 + ... +} +# Fontconfig is going fancy with its cache structure and that confuses valgrind. +# https://bugs.freedesktop.org/show_bug.cgi?id=8215 +# https://bugs.freedesktop.org/show_bug.cgi?id=8428 +{ + Bug 1187649 + Memcheck:Leak + match-leak-kinds: definite + fun:realloc + fun:FcPatternObjectInsertElt + ... +} +{ + Bug 1187649 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcPatternObjectInsertElt + ... +} +{ + Bug 1533462 (comment 9) + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcNameParseCharSet + fun:FcNameConvert + fun:FcNameParse + ... +} +# With older versions of fontconfig (e.g. 2.8.0 on taskcluster systems), +# there's an uninitialized memory usage and leak when loading app fonts. +{ + Bug 1231701 + Memcheck:Param + write(buf) + ... + fun:FcDirCacheWrite + fun:FcDirCacheScan + fun:FcConfigAddDirList + ... +} +{ + Bug 1231701 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcDirScanConfig + fun:FcDirCacheScan + fun:FcConfigAddDirList + ... +} +{ + Bug 1231701 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcDirScanConfig + fun:FcDirScanConfig + fun:FcDirCacheScan + fun:FcConfigAddDirList + ... +} +{ + Bug 1231701 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcDirScanConfig + obj:/usr/lib/x86_64-linux-gnu/libfontconfig.so.1.5.0 + fun:FcDirCacheScan + fun:FcConfigAddDirList + ... +} +# Leaks due to either Gtk+3 or cairo, but Gecko is not directly involved with +# those cairo interactions. One suspected cause is Gecko not closing the +# display to work around a bug in old Gtk+3 versions. See also bug 1228724. +{ + Bug 1187649 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:_cairo_freelist_alloc + fun:_cairo_xlib_display_queue_resource + fun:_cairo_xlib_surface_finish + ... +} +# The following leak is deep in Gtk+3, and it doesn't seem we're doing +# anything wrong on our end with the container objects. This suppression +# is purposefully verbose so as to avoid catching actual leaks due to +# Gecko code. +# Note: valgrind doesn't support more than 24 elements in a suppression stack. +{ + Bug 1187649 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_list_prepend + fun:gtk_combo_box_get_path_for_child + fun:gtk_container_get_path_for_child + fun:gtk_widget_get_path + fun:_gtk_widget_update_path + fun:reset_style_recurse + fun:gtk_widget_reset_style + fun:gtk_widget_set_parent + fun:gtk_combo_box_add + fun:g_cclosure_marshal_VOID__OBJECTv + fun:_g_closure_invoke_va + fun:g_signal_emit_valist + fun:g_signal_emit + fun:gtk_combo_box_constructor + fun:g_object_newv + fun:g_object_new_valist + fun:g_object_new + ... +} +# set_color() in gtkstyle.c of GTK version 3.4.4 only can leak GdkRGBA +# allocations when the theme has transparent colors: +# https://git.gnome.org/browse/gtk+/tree/gtk/deprecated/gtkstyle.c?h=3.4.4#n676 +{ + Bug 1250704 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_slice_copy + fun:boxed_proxy_lcopy_value + fun:gtk_style_context_get_valist + fun:gtk_style_context_get + fun:set_color + fun:gtk_style_update_from_context + fun:gtk_style_constructed + fun:g_object_newv + fun:g_object_new_valist + fun:g_object_new + ... +} +{ + Bug 794366 + Memcheck:Leak + ... + obj:/usr/lib64/libgtk-x11-2.0.so.0.1800.9 + ... +} +{ + Bug 794368 + Memcheck:Leak + ... + obj:/usr/lib64/libXrandr.so.2.2.0 + ... +} +{ + Bug 794373 + Memcheck:Leak + ... + obj:/lib64/libgobject-2.0.so.0.2200.5 + ... +} +{ + Bug 966673 + Memcheck:Leak + fun:malloc + obj:/lib/x86_64-linux-gnu/libresolv-2.13.so + ... + fun:gaih_inet + fun:getaddrinfo + fun:PR_GetAddrInfoByName + ... +} +{ + Bug 979242 + Memcheck:Leak + fun:calloc + fun:xcb_connect_to_fd + fun:xcb_connect_to_display_with_auth_info + fun:_XConnectXCB + fun:XOpenDisplay + fun:gdk_display_open + ... +} +{ + _g_io_module_get_default + Memcheck:Leak + ... + fun:g_io_module_new + fun:g_io_modules_scan_all_in_directory_with_scope + fun:_g_io_modules_ensure_loaded + fun:_g_io_module_get_default +} +{ + dlopen leak triggered by bug 1492121 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + ... + fun:dl_open_worker + fun:_dl_catch_exception + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_exception + fun:_dl_catch_error + fun:_dlerror_run + ... + fun:dlopen@@GLIBC_* + ... +} +{ + gtk leak triggered by bug 1707957. Relatively minor, and seems fixed in newer GTK versions. + Memcheck:Leak + match-leak-kinds: definite + ... + fun:gtk_css_keyframes_new + ... + fun:settings_update_theme + ... +} +{ + gtk leaks from not using gdk_display_close because it causes crashes in _gtk_settings_get_style_cascade + Memcheck:Leak + match-leak-kinds: definite + ... + fun:__glXInitialize + fun:GetGLXPrivScreenConfig + fun:glXQueryServerString + fun:epoxy_glx_version + fun:gdk_x11_screen_init_gl + fun:_gdk_x11_screen_update_visuals_for_gl + fun:_gdk_x11_screen_init_visuals + fun:_gdk_x11_screen_new + fun:_gdk_x11_display_open + fun:gdk_display_manager_open_display + fun:_ZN7XREMain15XRE_mainStartupEPb + fun:_ZN7XREMain8XRE_mainEiPPcRKN7mozilla15BootstrapConfigE + fun:_Z8XRE_mainiPPcRKN7mozilla15BootstrapConfigE + fun:do_main + fun:main +} +{ + gtk3/X11 leaks x11 child GdkWindow internals (Bug 1864382) + Memcheck:Leak + match-leak-kinds: definite + ... + fun:g_object_new + fun:_gdk_x11_display_create_window_impl + fun:gdk_window_ensure_native + fun:gdk_x11_window_get_xid + fun:GetX11Window + ... + fun:gtk_widget_map + fun:gtk_window_map + ... + fun:gtk_widget_map + fun:gtk_window_show + ... + fun:gtk_widget_show + ... +} + +################################### +# Leaks in short lived processes # +################################### + +{ + Bug 984196 + Memcheck:Leak + ... + fun:childgltest + ... +} + +######################################### +# Uninitialised value false positives # +######################################### + +# This concerns a false positive pertaining to Memcheck's overly- +# conservative instrumentation of CPUID. See bug 1288618 comments +# 119 through 127. +{ + Bug 1288618 comments 119 through 127 + Memcheck:Cond + fun:_ZN6SkOptsL4initEv + fun:sk_once_no_arg_adaptor +} + +{ + Bug 1288618 comments 119 through 127 part 2 + Memcheck:Cond + fun:__get_cpuid + fun:cpuid + fun:_ZN6SkOptsL4initEv + fun:sk_once_no_arg_adaptor +} + +# More stuff to do with CPUID and Skia. Apparently we could get rid of +# these if we could patch our in-tree Skia, but that's not favoured. +# +# Conditional jump or move depends on uninitialised value(s) +# at 0xFDD1D97: SkCpu::CacheRuntimeFeatures() +# by 0xFE8A66E: SkGraphics::Init() +# by 0xE757308: gfxPlatform::Init() +# by 0xE75772C: gfxPlatform::GetPlatform() +{ + Skia and CPUID, Jan 2017, #1 + Memcheck:Cond + fun:_ZN5SkCpu20CacheRuntimeFeaturesEv + fun:_ZN10SkGraphics4InitEv + fun:_ZN11gfxPlatform4InitEv + fun:_ZN11gfxPlatform11GetPlatformEv +} + +# Conditional jump or move depends on uninitialised value(s) +# at 0xFD5B218: SkOpts::Init() +# by 0xE757308: gfxPlatform::Init() +# by 0xE75772C: gfxPlatform::GetPlatform() +# by 0xF1A3691: mozilla::dom::ContentProcess::Init() +# or mozilla::dom::ContentChild::RecvSetXPCOMProcessAttributes() +{ + Skia and CPUID, Jan 2017, #2 + Memcheck:Cond + fun:_ZN6SkOpts4InitEv + fun:_ZN11gfxPlatform4InitEv + fun:_ZN11gfxPlatform11GetPlatformEv + fun:_ZN7mozilla3dom*Content* +} + +# False positives triggered by rust 1.20.0 (at least) builds of stylo. +# See bug 1394696. The diagnosis is an llvm optimization transforming +# `if A && B` to `if B && A` if is can be proven that A is false +# whenever B is uninitialized. Confusing, but valid. +# +# Conditional jump or move depends on uninitialised value(s) +# at 0x113ED01E: selectors::matching::matches_complex_selector_internal (option.rs:421) +# by 0x113ECF19: selectors::matching::matches_complex_selector (matching.rs:501) +# by 0x113EBAC0: <style::selector_map::SelectorMap<style::stylist::Rule>>::get_matching_rules (matching.rs:397) +{ + Bug 1394696 Stylo selector, Sept 2017, part 1 + Memcheck:Cond + fun:_ZN9selectors8matching33matches_complex_selector_internal* + fun:_ZN9selectors8matching24matches_complex_selector* + ... + fun:_ZN69_$LT$style..selector_map..SelectorMap$LT$style..stylist..Rule$GT$$GT$18get_matching_rules* +} + +# Conditional jump or move depends on uninitialised value(s) +# at 0x113EFFDE: selectors::matching::matches_complex_selector_internal (option.rs:421) +# by 0x113EFED9: selectors::matching::matches_complex_selector (matching.rs:501) +# by 0x113DFE55: style::stylist::Stylist::match_revalidation_selectors::{{closure}} (matching.rs:397) +{ + Bug 1394696 Stylo selector, Sept 2017, part 2 + Memcheck:Cond + fun:_ZN9selectors8matching33matches_complex_selector_internal* + fun:_ZN9selectors8matching24matches_complex_selector* + ... + fun:_ZN5style9traversal13compute_style* + fun:recalc_style_at<style::gecko::wrapper::GeckoElement,style::gecko::traversal::RecalcStyleOnly,closure> +} + +# Similar issue triggered by rust 1.23.0 on builds of stylo. +# +# at 0x11819B3E: std::sync::once::Once::call_once::{{closure}} (raw_vec.rs:225) +# by 0x118FDCCC: std::sync::once::Once::call_inner (once.rs:341) +# by 0x1139C761: UnknownInlinedFun (once.rs:228) +{ + Bug 1418083 Servo::TraverseSubtree, January 2018 + Memcheck:Cond + fun:*ZN3std4sync4once4Once9call_once* + fun:*ZN3std4sync4once4Once10call_inner* + ... + fun:Servo_TraverseSubtree +} + +# Issue triggered by rust 1.23.0 on builds of stylo. +{ + Bug 1418083 SelectorList::parse, January 2018 + Memcheck:Cond + fun:_ZN36_$LT$smallvec..SmallVec* + fun:_ZN52_$LT$selectors..parser..SelectorList* +} + +# Conditional jump or move depends on uninitialised value(s) +# at 0x118720EA: <core::slice::Iter<'a, T> as core::iter::iterator::Iterator>::all::{{closure}} (mod.rs:1173) +# by 0x11871EF6: style::media_queries::MediaList::evaluate (mod.rs:1277) +{ + Bug 1430608 nsMediaFeatures, January 2018 + Memcheck:Cond + fun:_ZN91_$LT$core..slice..Iter$LT$$u27$a$C$$u20$T$GT$$u20$as$u20$core..iter..iterator..Iterator$GT$3all* + fun:_ZN5style13media_queries9MediaList8evaluate* +} + +# Several issues triggered by enabling stylo-chrome. + +# Conditional jump or move depends on uninitialised value(s) +# at 0x11F88693: style::properties::LonghandId::parse_value (heap.rs:0) +# by 0x1203BBAB: style::properties::UnparsedValue::substitute_variables (parser.rs:594) +# by 0x11CFCE33: style::properties::cascade (properties.rs:135672) +{ + Bug 1437796 LonghandId::parse_value, January 2018 + Memcheck:Cond + fun:_ZN5style10properties10LonghandId11parse_value* + fun:_ZN5style10properties13UnparsedValue20substitute_variables* + fun:_ZN5style10properties7cascade* +} + +# Conditional jump or move depends on uninitialised value(s) +# at 0x11DF7AF6: <smallvec::SmallVec<A>>::grow (raw_vec.rs:0) +# by 0x11DF6ED0: Servo_InvalidateStyleForDocStateChanges (lib.rs:475) +# by 0x10394B7E: mozilla::ServoStyleSet::InvalidateStyleForDocumentStateChanges(mozilla::EventStates) (ServoStyleSet.cpp:248) +{ + Bug 1437796 SmallVec::grow in Servo_InvalidateStyleForDocStateChanges, January 2018 + Memcheck:Cond + fun:_ZN36_$LT$smallvec..SmallVec$LT$A$GT$$GT$4grow* + fun:Servo_InvalidateStyleForDocStateChanges + fun:_ZN7mozilla13ServoStyleSet38InvalidateStyleForDocumentStateChangesENS_11EventStatesE +} + + +############################################################################## +## BEGIN suppressions for Stylo as compiled by rustc 1.25.0 +# Even more similar issues, resulting from transitioning to rustc 1.25.0. +# See bug 1447137. + + +# Suppressions rooted at *style*values*specified*color*Color*style*parser*Parse*parse* + +{ + bug1447137 + Memcheck:Cond + fun:*style*values*specified*color*Color*style*parser*Parse*parse* +} + +########################################## +# Suppressions rooted at *selectors*parser*SelectorList*Impl*parse* + +{ + bug1454511 + Memcheck:Cond + fun:*selectors*parser*SelectorList*Impl*parse* +} + +########################################## +# Suppressions rooted at *style*properties*shorthands* + +{ + bug1447137-17 + Memcheck:Cond + fun:*style*properties*shorthands* + fun:*style*properties*PropertyDeclaration*parse_into* + fun:*style*parse_value* + fun:*cssparser*Iterator*next* +} + +## END suppressions for Stylo as compiled by rustc 1.25.0 +############################################################################## + + +# Another suppression for Stylo, August 2018. See bug 1479055. +# +# Conditional jump or move depends on uninitialised value(s) +# at style::[..]::clip_path::cascade_property (gecko_properties.rs:17152) +# by style::properties::cascade_rules (properties.rs:83642) +# by [..]::cascade_style_and_visited (properties.rs:83129) +# by [..]::cascade_primary_style (style/style_resolver.rs:216) +{ + Bug 1479055: style::properties::longhands::clip_path::cascade_property + Memcheck:Cond + fun:_ZN5style10properties9longhands9clip_path16cascade_property* + fun:_ZN5style10properties13cascade_rules* + fun:_ZN109_$LT$style*style_resolver*cascade_style_and_visited* + fun:_ZN109_$LT$style*cascade_primary_style* +} + +# Another suppression for Stylo, October 2018. See bug 1496486. +# Conditional jump or move depends on uninitialised value(s) +# at 0x108E2931: style::properties::longhands::font_language_override::cascade_property+81 (font.rs:2095) +# by 0x107E95B4: style::properties::cascade::Cascade::apply_properties+580 (cascade.rs:463) +# by 0x107E82D8: style::properties::cascade::cascade_rules+2440 (cascade.rs:303) +# by 0x107E7206: <style::style_resolver::StyleResolverForElement<'a, 'ctx, 'le, E>>::cascade_style_and_visited+310 (cascade.rs:93) +# Uninitialised value was created by a stack allocation +# at 0x10A42A40: style::properties::shorthands::font::parse_value (font.rs:376) +{ + Bug 1496486: style::properties::longhands::font_language_override::cascade_property + Memcheck:Cond + fun:_ZN5style10properties9longhands22font_language_override16cascade_property* + fun:_ZN5style10properties7cascade7Cascade16apply_properties* + fun:_ZN5style10properties7cascade13cascade_rules* +} + +################################################### +# For valgrind-mochitest ("tc-M-V [tier 2]") runs on taskcluster. +# See bug 1248365. +# These are specific to Ubuntu 12.04.5, 64-bit. +################################################### + + +# Not sure what this is. Is it the well-known +# Memcheck-being-confused-by-zlib thing? I suspect so. +# +# Conditional jump or move depends on uninitialised value(s) +# at 0xB6154E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4) +# by 0xB6155D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4) +# by 0xADDE253: png_create_read_struct_2 +# (in /lib/x86_64-linux-gnu/libpng12.so.0.46.0) +# Uninitialised value was created by a heap allocation +# at 0x4C2D027: malloc (coregrind/m_replacemalloc/vg_replace_malloc.c:298) +# by 0xADE960F: png_malloc (in /lib/x86_64-linux-gnu/libpng12.so.0.46.0) +# by 0xADD1B95: ??? (in /lib/x86_64-linux-gnu/libpng12.so.0.46.0) +# by 0xB6155B6: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4) +# by 0xADDE253: png_create_read_struct_2 +# (in /lib/x86_64-linux-gnu/libpng12.so.0.46.0) +# by 0x15707869: ??? (in /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/ +# loaders/libpixbufloader-png.so) +{ + Bug 1248365: mochitest-libz-1 + Memcheck:Cond + fun:inflateReset2 + fun:inflateInit2_ + fun:png_create_read_struct_2 +} + + +# I don't know what this is. +# +# Conditional jump or move depends on uninitialised value(s) +# at 0x39608257: ??? (in /usr/lib/x86_64-linux-gnu/librsvg-2.so.2.36.1) +# by 0x39608E96: rsvg_handle_get_pixbuf_sub (in /usr/lib/x86_64-linux-gnu/l +# by 0x37D00D2A: ??? (in /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/lo +# by 0x88FF740: gdk_pixbuf_loader_close (in /usr/lib/x86_64-linux-gnu/libgd +# by 0x88FBA48: ??? (in /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.26 +# by 0x88FD290: gdk_pixbuf_new_from_stream_at_scale (in /usr/lib/x86_64-lin +# by 0x6EF96A7: ??? (in /usr/lib/x86_64-linux-gnu/libgtk-3.so.0.400.2) +# by 0x6EFC2B1: gtk_icon_info_load_icon (in /usr/lib/x86_64-linux-gnu/libgt +# Uninitialised value was created by a stack allocation +# at 0xAB786B0: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) +{ + Bug 1248365: mochitest-librsvg-1 + Memcheck:Cond + obj:/*/librsvg-2.so.2.36* + fun:rsvg_handle_get_pixbuf_sub + obj:/*/libpixbufloader-svg.so* + fun:gdk_pixbuf_loader_close +} + + +# There now follow some suppressions to do with libpixman. There are two +# variants, one for errors in the system libpixman, and one for errors in +# our in-tree copy. I suspect that all of these sse2 compositing reports +# are Memcheck false positives, possibly to do with inaccurate +# instrumentation of the function combine1() in +# gfx/cairo/libpixman/src/pixman-sse2.c. +# +# Conditional jump or move depends on uninitialised value(s) +# at 0xAB93A10: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) +# by 0xAB78927: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) +# by 0xAB40B0B: pixman_image_composite32 (in /usr/lib/x86_64-linux-gnu/libp +# by 0x865C95C: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2) +# by 0x865E3CB: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2) +# by 0x865F6EA: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2) +# by 0x865F968: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2) +# by 0x867D7C3: ??? (in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11000.2) +# Uninitialised value was created by a stack allocation +# at 0xAB786B0: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) +{ + Bug 1248365: mochitest-libpixman-1 + Memcheck:Cond + obj:/*/libpixman-1.so.0.30* + obj:/*/libpixman-1.so.0.30* + fun:pixman_image_composite32 +} + + +# Conditional jump or move depends on uninitialised value(s) +# at 0xF9EA219: sse2_composite_over_8888_8888 +# by 0xF9F5B5F: _moz_pixman_image_composite32 +# by 0xF96E29E: _clip_and_composite_boxes +# by 0xF96F79D: _cairo_image_surface_fill +# by 0xF98790C: _cairo_surface_fill +# by 0xF96FE2E: _cairo_gstate_fill +# by 0xF98B3D9: _moz_cairo_fill_preserve +# by 0xE4CF383: mozilla::gfx::DrawTargetCairo::DrawPattern(mozilla::gfx: +# Uninitialised value was created by a stack allocation +# at 0xB8E46B0: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2) +{ + Bug 1248365: mochitest-libpixman-2 + Memcheck:Cond + fun:sse2_composite_over_8888_8888 + fun:_moz_pixman_image_composite32 + fun:_clip_and_composite_boxes + fun:_cairo_image_surface_fill +} + + +# Conditional jump or move depends on uninitialised value(s) +# at 0xF9D56AE: sse2_combine_over_u (in /builds/worker/workspace/build/applic +# by 0xF9D05D4: general_composite_rect (in /builds/worker/workspace/build/app +# by 0xF9F5B5F: _moz_pixman_image_composite32 (in /builds/worker/workspace/bu +# by 0xF96CF63: _clip_and_composite (in /builds/worker/workspace/build/applic +# by 0xF96D656: _clip_and_composite_boxes.part.32 (in /builds/worker/workspac +# by 0xF96E328: _clip_and_composite_boxes (in /builds/worker/workspace/build/ +# by 0xF96F79D: _cairo_image_surface_fill (in /builds/worker/workspace/build/ +# by 0xF98790C: _cairo_surface_fill (in /builds/worker/workspace/build/applic +# Uninitialised value was created by a stack allocation +# at 0xF9D024D: general_composite_rect (in /builds/worker/workspace/build/app +# +{ + Bug 1248365: mochitest-libpixman-3 + Memcheck:Cond + fun:sse2_combine_over_u + fun:general_composite_rect + fun:_moz_pixman_image_composite32 + fun:_clip_and_composite* +} + + +# Not sure what this. I can't reproduce it locally despite much trying. +# Syscall param sendmsg(msg.msg_iov[0]) points to uninitialised byte(s) +# at 0x4E4533D: ??? (syscall-template.S:82) +# by 0xE12C0A7: IPC::Channel::ChannelImpl::ProcessOutgoingMessages() (in /h +# by 0xE142FD0: RunnableMethod<IPC::Channel, bool (IPC::Channel::*)(IPC::Me +# by 0xE1240EA: MessageLoop::RunTask(Task*) (in /builds/worker/workspace/buil +# by 0xE128A46: MessageLoop::DeferOrRunPendingTask(MessageLoop::PendingTask +# by 0xE128B6D: MessageLoop::DoWork() (in /builds/worker/workspace/build/appl +# by 0xE12272C: base::MessagePumpLibevent::Run(base::MessagePump::Delegate* +# by 0xE124155: MessageLoop::Run() (in /builds/worker/workspace/build/applica +{ + Bug 1248365: mochitest-sendmsg-1 + Memcheck:Param + sendmsg(msg.msg_iov[0]) + obj:/lib/x86_64-linux-gnu/libpthread-2.15.so + fun:_ZN3IPC7Channel11ChannelImpl23ProcessOutgoingMessagesEv + fun:_ZN14RunnableMethodIN3IPC7ChannelEMS1_FbPNS0_7MessageEEN7mozilla5Tuple* +} + + +# I can't repro this either. +# Conditional jump or move depends on uninitialised value(s) +# at 0x418E7E7C: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.53.35.0) +# by 0x4192D620: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.53.35.0) +# by 0x4192E717: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.53.35.0) +# by 0x41711BC4: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.53.35.0) +# by 0x41B08B6A: avcodec_open2 (in /usr/lib/x86_64-linux-gnu/libavcodec.so. +# by 0xEEAD89C: mozilla::FFmpegDataDecoder<53>::InitDecoder() (in /home/wor +# by 0xEEAE42B: mozilla::FFmpegVideoDecoder<53>::Init() (in /builds/worker/wo +# by 0xEEA4C07: mozilla::H264Converter::Init() (in /builds/worker/workspace/b +# Uninitialised value was created by a heap allocation +# at 0x4C2D11F: realloc (vg_replace_malloc.c:785) +# by 0x406196: moz_xrealloc (in /builds/worker/workspace/build/application/fi +# by 0xDEB43AC: nsTArrayInfallibleAllocator::ResultTypeProxy nsTArray_base< +# by 0xEEAD850: mozilla::FFmpegDataDecoder<53>::InitDecoder() (in /home/wor +# by 0xEEAE42B: mozilla::FFmpegVideoDecoder<53>::Init() (in /builds/worker/wo +{ + Bug 1248365: mochitest-libavcodec-1-c + Memcheck:Cond + obj:/*/libavcodec.so.53* + obj:/*/libavcodec.so.53* + obj:/*/libavcodec.so.53* + obj:/*/libavcodec.so.53* +} +{ + Bug 1248365: mochitest-libavcodec-1-v8 + Memcheck:Value8 + obj:/*/libavcodec.so.53* + obj:/*/libavcodec.so.53* + obj:/*/libavcodec.so.53* + obj:/*/libavcodec.so.53* +} + + +# Not sure what this is, but I am inclined to think it is also probably a +# SSE2-induced false positive similar to mochitest-libpixman-2 above. +# Use of uninitialised value of size 8 +# at 0xE4F3E89: FastConvertYUVToRGB32Row (in /builds/worker/workspace/build/a +# by 0xE4F4A6D: mozilla::gfx::ConvertYCbCrToRGB32(unsigned char const*, uns +# by 0xE4F4B17: mozilla::gfx::ConvertYCbCrToRGB(mozilla::layers::PlanarYCbC +# by 0xE5227CB: mozilla::layers::PlanarYCbCrImage::GetAsSourceSurface() (in +# by 0xE5B2465: mozilla::layers::SharedPlanarYCbCrImage::GetAsSourceSurface +# by 0xE52FE44: mozilla::layers::BasicImageLayer::Paint(mozilla::gfx::DrawT +# by 0xE5618A1: mozilla::layers::BasicLayerManager::PaintSelfOrChildren(moz +# by 0xE560F83: mozilla::layers::BasicLayerManager::PaintLayer(gfxContext*, +# Uninitialised value was created by a stack allocation +# at 0x434B36B2: ??? (in /usr/lib/x86_64-linux-gnu/libavcodec.so.53.35.0) +{ + Bug 1248365: FastConvertYUVToRGB32Row-1 + Memcheck:Value8 + fun:FastConvertYUVToRGB32Row + fun:_ZN7mozilla3gfx19ConvertYCbCrToRGB32* + fun:_ZN7mozilla3gfx17ConvertYCbCrToRGB* + fun:_ZN7mozilla6layers16PlanarYCbCrImage18GetAsSourceSurface* +} + +# Similarly: +# Conditional jump or move depends on uninitialised value(s) +# at 0xFDAD1D1: sse41::blit_row_s32a_opaque(unsigned int*, unsigned int con +# by 0xFD60FA9: Sprite_D32_S32::blitRect(int, int, int, int) (in /home/work +# by 0xFEB9E0D: SkScan::FillIRect(SkIRect const&, SkRegion const*, SkBlitte +# by 0xFEBDDF3: SkScan::FillIRect(SkIRect const&, SkRasterClip const&, SkBl +{ + SKIA and SSE4, Jan 2017 + Memcheck:Cond + fun:_ZN5sse41L20blit_row_s32a_opaque* + fun:_ZN14Sprite_D32_S328blitRect* + fun:_ZN6SkScan9FillIRect* + fun:_ZN6SkScan9FillIRect* +} + +# This is probably a V false positive, due to an insufficiently accurate +# description of the ioctl(SIOCETHTOOL) behavior. +# Syscall param ioctl(SIOCETHTOOL) points to uninitialised byte(s) +# at 0x5D5CBF7: ioctl (syscall-template.S:82) +# by 0xF58EB67: nr_stun_get_addrs (in /builds/worker/workspace/build/applica +# by 0xF594791: nr_stun_find_local_addresses (in /builds/worker/workspace/bu +# by 0xF58A237: nr_ice_get_local_addresses (in /builds/worker/workspace/buil +# by 0xF58ADDE: nr_ice_gather (in /builds/worker/workspace/build/application +# by 0xE43F35F: mozilla::NrIceCtx::StartGathering() (in /builds/worker/works +# by 0xE419560: mozilla::PeerConnectionMedia::EnsureIceGathering_s() (in / +# by 0xE41A11C: mozilla::runnable_args_memfn<RefPtr<mozilla::PeerConnectio +# Address 0x1cc3fb48 is on thread 6's stack +# in frame #1, created by nr_stun_get_addrs (???:) +{ + Bug 1248365: mochitest-ioctl(SIOCETHTOOL)-1 + Memcheck:Param + ioctl(SIOCETHTOOL) + fun:ioctl + fun:nr_stun_get_addrs + fun:nr_stun_find_local_addresses +} + + +# This looks like uninitialised padding bytes in a structure owned +# by libfontconfig. So there's nothing we can do about it. +# Syscall param write(buf) points to uninitialised byte(s) +# at 0x4E44CCD: ??? (syscall-template.S:82) +# by 0x9F1FF56: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4) +# by 0x9F2679B: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4) +# by 0x9F22B98: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4) +# by 0x9F22C5F: FcConfigAppFontAddDir (in /usr/lib/x86_64-linux-gnu/libfon +# by 0xE850173: gfxFcPlatformFontList::ActivateBundledFonts() (in /home/wo +# by 0xE852258: gfxFcPlatformFontList::InitFontListForPlatform() (in /home +# by 0xE895E21: gfxPlatformFontList::InitFontList() (in /builds/worker/works +# Address 0x2316663c is 156 bytes inside a block of size 1,448 alloc'd +# at 0x4C2CF71: malloc (vg_replace_malloc.c:299) +# by 0x9F1FD1D: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4) +# by 0x9F26788: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4) +# by 0x9F22B98: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4) +# by 0x9F22C5F: FcConfigAppFontAddDir (in /usr/lib/x86_64-linux-gnu/libfon +# by 0xE850173: gfxFcPlatformFontList::ActivateBundledFonts() (in /home/wo +# by 0xE852258: gfxFcPlatformFontList::InitFontListForPlatform() (in /home +# by 0xE895E21: gfxPlatformFontList::InitFontList() (in /builds/worker/works +{ + Bug 1248365: libfontconfig-1 + Memcheck:Param + write(buf) + obj:/*/libpthread*.so* + obj:/*/libfontconfig.so* + ... + obj:/*/libfontconfig.so* + fun:FcConfigAppFontAddDir +} + + +# There's nothing we can do about these short of throwing in +# --show-mismatched-frees=no, but that's a bit drastic, so for now, +# just suppress them. A typical error is: +# +# Mismatched free() / delete / delete [] +# at 0x4C2BE97: free (vg_replace_malloc.c:530) +# by 0xFCD09EC: ots::ots_post_free(ots::Font*) (in /builds/worker/workspace/ +# by 0xFCC600E: ots::Font::~Font() (in /builds/worker/workspace/build/applic +# by 0xFCCBFA5: ots::OTSContext::Process(ots::OTSStream*, unsigned char co +# by 0xE7D7C8D: gfxUserFontEntry::SanitizeOpenTypeData(unsigned char const +# by 0xE7E371D: gfxUserFontEntry::LoadPlatformFont(unsigned char const*, u +# by 0xE7E48AA: gfxUserFontEntry::FontDataDownloadComplete(unsigned char c +# by 0xF49D25B: nsFontFaceLoader::OnStreamComplete(nsIStreamLoader*, nsISu +# Address 0x15671f00 is 0 bytes inside a block of size 490 alloc'd +# at 0x4C2CAEE: operator new(unsigned long) (vg_replace_malloc.c:332) +# by 0xF6AB737: std::vector<unsigned short, std::allocator<unsigned short> +# by 0xFCD0FDE: ots::ots_post_parse(ots::Font*, unsigned char const*, unsi +# by 0xFCCA3D9: (anonymous namespace)::ProcessGeneric(ots::OpenTypeFile*, +# by 0xFCCB17E: (anonymous namespace)::ProcessTTF(ots::OpenTypeFile*, ots: +# by 0xFCCBA54: ots::OTSContext::Process(ots::OTSStream*, unsigned char co +# by 0xE7D7C8D: gfxUserFontEntry::SanitizeOpenTypeData(unsigned char const +# by 0xE7E371D: gfxUserFontEntry::LoadPlatformFont(unsigned char const*, u +{ + Bug 1248365: ots::Font::~Font()-1 + Memcheck:Free + fun:free + fun:_ZN3ots13ots_post_free* + fun:_ZN3ots4FontD1Ev + fun:_ZN3ots10OTSContext7Process* +} + +# and various similar: +{ + ots mismatched frees, Jan 2017, #1 + Memcheck:Free + fun:_ZdlPv + fun:_ZN3ots14ots_glyf_parse* + fun:_ZN12_GLOBAL__N_114ProcessGenericEPN3ots12OpenTypeFile* + fun:_ZN12_GLOBAL__N_110ProcessTTFEPN3ots12OpenTypeFile* +} +{ + ots mismatched frees, Jan 2017, #2 + Memcheck:Free + fun:_ZdlPv + fun:_ZN3ots13ots_cff_parse* + fun:_ZN12_GLOBAL__N_114ProcessGenericEPN3ots12OpenTypeFile* + fun:_ZN3ots10OTSContext7ProcessEPNS_9OTSStream* +} +{ + ots mismatched frees, Jan 2017, #3 + Memcheck:Free + fun:_ZdlPv + fun:_ZN3ots13ots_cff_parse* + fun:_ZN12_GLOBAL__N_114ProcessGenericEPN3ots12OpenTypeFile* + fun:_ZN12_GLOBAL__N_110Process* +} +{ + ots mismatched frees, Jan 2017, #4 + Memcheck:Free + fun:_ZdlPv + fun:_ZN3ots12ots_cff_free* + fun:_ZN3ots4FontD1Ev* + fun:_ZN3ots10OTSContext7Process* +} +{ + ots mismatched frees, Jan 2017, #5 + Memcheck:Free + fun:_ZdlPv + fun:_ZN3ots13ots_loca_free* + fun:_ZN3ots4FontD1Ev* + fun:_ZN3ots10OTSContext7Process* +} +{ + ots mismatched frees, Jan 2017, #6 + Memcheck:Free + fun:_ZdlPv + fun:_ZN3ots14ots_glyf_parse* + fun:_ZN12_GLOBAL__N_114ProcessGenericEPN3ots12OpenTypeFile* + fun:_ZN3ots10OTSContext7ProcessEPNS_9OTSStream* +} + +{ + map_or<selectors::parser::Combinator,bool,closure> #1 (see bug 1365915) + Memcheck:Cond + fun:map_or<selectors::parser::Combinator,bool,closure> + fun:_ZN9selectors8matching33matches_complex_selector_internal* + fun:_ZN9selectors8matching24matches_complex_selector* + fun:matches_selector<style::gecko::wrapper::GeckoElement,closure> +} + +{ + map_or<selectors::parser::Combinator,bool,closure> #2 (see bug 1365915) + Memcheck:Cond + fun:map_or<selectors::parser::Combinator,bool,closure> + fun:_ZN9selectors8matching33matches_complex_selector_internal* + fun:_ZN9selectors8matching24matches_complex_selector* + fun:{{closure}}<closure> +} + +# more leaks in libLLVM-3.6-mesa.so, August 2017. See bug 1338651. +{ + static-object-leaks-in-libLLVM-3.6-mesa.so. See bug 1338651. + Memcheck:Leak + match-leak-kinds: definite + fun:_Znwm + obj:/*/lib*/libLLVM-3.6-mesa.so + obj:/*/lib*/libLLVM-3.6-mesa.so +} + +{ + bug 1632735 + Memcheck:Cond + fun:_ZN9selectors6parser25parse_one_simple_selector17h* + fun:_ZN9selectors6parser14parse_selector17h* + fun:_ZN9selectors6parser24SelectorList$LT$Impl$GT$16parse_with_state17h* +} + +{ + bug 1632735 + Memcheck:Cond + fun:_ZN9selectors6parser25parse_one_simple_selector17h* + fun:_ZN9selectors6parser29parse_functional_pseudo_class17h* + fun:_ZN9selectors6parser25parse_one_simple_selector17h* + fun:_ZN9selectors6parser14parse_selector17h* + fun:_ZN9selectors6parser24SelectorList$LT$Impl$GT$16parse_with_state17h* +} + +{ + bug 1632735 + Memcheck:Cond + fun:_ZN9selectors6parser25parse_one_simple_selector17h* + fun:_ZN9selectors6parser14parse_selector17h* + fun:_ZN9cssparser6parser18parse_until_before17h* + fun:_ZN5style5gecko15selector_parser94_$LT$impl$u20$selectors..parser..Parser$u20$for$u20$style..selector_parser..SelectorParser$GT$36parse_non_ts_functional_pseudo_class17h* + fun:_ZN9selectors6parser29parse_functional_pseudo_class17h* + fun:_ZN9selectors6parser25parse_one_simple_selector17* + fun:_ZN9selectors6parser14parse_selector17h* + fun:_ZN9selectors6parser24SelectorList$LT$Impl$GT$16parse_with_state17h* +} + +{ + bug 1632735 + Memcheck:Cond + fun:_ZN9selectors6parser25parse_one_simple_selector17h* + fun:_ZN9selectors6parser14parse_selector17h* + fun:_ZN9selectors6parser29parse_functional_pseudo_class17h* + fun:_ZN9selectors6parser25parse_one_simple_selector17* + fun:_ZN9selectors6parser14parse_selector17h* + fun:_ZN9selectors6parser24SelectorList$LT$Impl$GT$16parse_with_state17h* +} + +{ + Starting with rust 1.52 + Memcheck:Cond + ... + fun:_ZN5style10properties10shorthands4font10parse_into* + fun:_ZN5style10properties19PropertyDeclaration10parse_into* + fun:_ZN5style10properties17declaration_block31parse_property_declaration_list* + fun:_ZN124_$LT$style..stylesheets..rule_parser..NestedRuleParser$u20$as$u20$cssparser..rules_and_declarations..QualifiedRuleParser$GT$11parse_block* +} + +# Suppression for Software WebRender, June 2021. See bug 1715267. +# +# Conditional jump or move depends on uninitialised value(s) +# at 0x162B199F: webrender::renderer::upload::upload_to_texture_cache+10639 (mod.rs:2045) +# by 0x162A7567: webrender::renderer::Renderer::update_texture_cache+5191 (mod.rs:2241) +# by 0x1629EF2F: webrender::renderer::Renderer::render_impl+3647 (mod.rs:1874) +# Uninitialised value was created by a stack allocation +# at 0x162AF01D: webrender::renderer::upload::upload_to_texture_cache+13 (upload.rs:50) +{ + Bug 1715267: webrender::renderer::upload::upload_to_texture_cache + Memcheck:Cond + fun:_ZN9webrender8renderer6upload23upload_to_texture_cache17h* + fun:_ZN9webrender8renderer8Renderer20update_texture_cache17h* + fun:_ZN9webrender8renderer8Renderer11render_impl17h* +} + +# Suppression for Software WebRender, June 2021. See bug 1715290. +# +# 24 bytes in 1 blocks are definitely lost in loss record 3,311 of 10,861 +# at 0x4C28FC0: malloc+112 (vg_replace_malloc.c:307) +# by 0x162F6CC9: wr_thread_pool_new+2729 (library/std/src/sys/unix/alloc.rs:14) +# by 0x11EB0814: WebRenderThreadPool (checkouts/gecko/gfx/webrender_bindings/RenderThread.cpp:1037) +# by 0x11EB0814: RenderThread (checkouts/gecko/gfx/webrender_bindings/RenderThread.cpp:64) +# by 0x11EB0814: mozilla::wr::RenderThread::Start()+116 (checkouts/gecko/gfx/webrender_bindings/RenderThread.cpp:96) +{ + Bug 1715290: wr_thread_pool_new / WebRenderThreadPool / RenderThread + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + ... + fun:wr_thread_pool_new + fun:WebRenderThreadPool + fun:RenderThread + fun:_ZN7mozilla2wr12RenderThread5StartEj +} + +{ + Bug 1715523 / 1715533 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:moz_xmalloc + fun:operator new + fun:MakeNotNull<RefPtr<mozilla::ProfilingStackOwner>> + fun:RacyRegisteredThread + fun:_ZN16RegisteredThreadC1EP10ThreadInfoP9nsIThreadPv +} + +{ + Bug 1728618 / 1716579 + Memcheck:Cond + fun:_ZN9webrender8renderer8Renderer20update_texture_cache* + fun:_ZN9webrender8renderer8Renderer11render_impl* +} + +# Suppression for a dynamic-atom leak apparently related to shutdown timing/race. See bug 1748520. +# +# 20 bytes in 1 blocks are definitely lost in loss record 3,754 of 20,244 +# at 0x48397B5: malloc+117 (vg_replace_malloc.c:381) +# by 0x12CD30: moz_xmalloc+16 (checkouts/gecko/memory/mozalloc/mozalloc.cpp:52) +# by 0xAEE7F3C: nsDynamicAtom::Create(nsTSubstring<char16_t> const&, unsigned int)+140 (checkouts/gecko/xpcom/ds/nsAtomTable.cpp:90) +# by 0xAEE8DC9: nsAtomTable::Atomize(nsTSubstring<char> const&)+265 (checkouts/gecko/xpcom/ds/nsAtomTable.cpp:566) +# by 0xAFD5857: nsLanguageAtomService::LookupLanguage(nsTSubstring<char> const&)+87 (checkouts/gecko/intl/locale/nsLanguageAtomService.cpp:102) +# by 0xBCE209E: gfxFcPlatformFontList::TryLangForGroup(nsTSubstring<char> const&, nsAtom*, nsTSubstring<char>&, bool)+382 (checkouts/gecko/gfx/thebes/gfxFcPlatformFontList.cpp:2504) +# by 0xBCDD57E: gfxFcPlatformFontList::GetSampleLangForGroup(nsAtom*, nsTSubstring<char>&, bool)+734 (checkouts/gecko/gfx/thebes/gfxFcPlatformFontList.cpp:2569) +# by 0xBCE03A1: gfxFcPlatformFontList::FindGenericFamilies(nsPresContext*, nsTString<char> const&, nsAtom*)+113 (checkouts/gecko/gfx/thebes/gfxFcPlatformFontList.cpp:2299) +# by 0xBCE02F4: gfxFcPlatformFontList::GetDefaultFontForPlatform(nsPresContext*, gfxFontStyle const*, nsAtom*)+68 (checkouts/gecko/gfx/thebes/gfxFcPlatformFontList.cpp:1991) +# by 0xBD2E807: gfxPlatformFontList::GetDefaultFont(nsPresContext*, gfxFontStyle const*)+39 (checkouts/gecko/gfx/thebes/gfxPlatformFontList.cpp:2319) +# by 0xBD2CBBF: gfxPlatformFontList::InitFontList()+1279 (checkouts/gecko/gfx/thebes/gfxPlatformFontList.cpp:573) +# by 0xBD2C5C8: gfxPlatformFontList::Initialize(gfxPlatformFontList*)+72 (checkouts/gecko/gfx/thebes/gfxPlatformFontList.cpp:259) +# by 0xBCE8F8E: gfxPlatform::Init()+3070 (checkouts/gecko/gfx/thebes/gfxPlatform.cpp:963) +{ + Bug 1748520 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:moz_xmalloc + fun:operator new + fun:_ZN13nsDynamicAtom6Create* + fun:_ZN11nsAtomTable7Atomize* + fun:_ZN21nsLanguageAtomService14LookupLanguage* + ... + fun:_ZN11gfxPlatform4InitEv +} + +# Suppression for a dynamic-atom leak related to DOMLocalization. See bug 1762046. +# +# 28 bytes in 1 blocks are definitely lost in loss record 5,420 of 21,361 +# at 0x48397B5: malloc+117 (vg_replace_malloc.c:381) +# by 0x12DB70: moz_xmalloc+16 (checkouts/gecko/memory/mozalloc/mozalloc.cpp:52) +# by 0xAF7808C: nsDynamicAtom::Create(nsTSubstring<char16_t> const&, unsigned int)+140 (checkouts/gecko/xpcom/ds/nsAtomTable.cpp:90) +# by 0xAF7915B: nsAtomTable::Atomize(nsTSubstring<char16_t> const&)+315 (checkouts/gecko/xpcom/ds/nsAtomTable.cpp:595) +# by 0xBE6E0F2: nsAttrValue::ParseAtom(nsTSubstring<char16_t> const&)+34 (checkouts/gecko/dom/base/nsAttrValue.cpp:1169) +# by 0xBDE6F18: mozilla::dom::Element::ParseAttribute(int, nsAtom*, nsTSubstring<char16_t> const&, nsIPrincipal*, nsAttrValue&)+88 (checkouts/gecko/dom/base/Element.cpp:0) +# by 0xBDE3A8C: mozilla::dom::Element::SetAttr(int, nsAtom*, nsAtom*, nsTSubstring<char16_t> const&, nsIPrincipal*, bool)+412 (checkouts/gecko/dom/base/Element.cpp:2432) +# by 0xD919226: SetAttr (dist/include/mozilla/dom/Element.h:947) +# by 0xD919226: SetAttr (dist/include/mozilla/dom/Element.h:943) +# by 0xD919226: mozilla::dom::DOMLocalization::SetRootInfo(mozilla::dom::Element*)+230 (checkouts/gecko/dom/l10n/DOMLocalization.cpp:456) +# by 0xD91AE40: mozilla::dom::DocumentL10n::InitialTranslationCompleted(bool)+48 (checkouts/gecko/dom/l10n/DocumentL10n.cpp:314) +# by 0xD91F579: L10nReadyHandler::ResolvedCallback(JSContext*, JS::Handle<JS::Value>, mozilla::ErrorResult&)+25 (checkouts/gecko/dom/l10n/DocumentL10n.cpp:75) +# by 0xD6EBCAD: mozilla::dom::(anonymous namespace)::PromiseNativeHandlerShim::ResolvedCallback(JSContext*, JS::Handle<JS::Value>, mozilla::ErrorResult&)+29 (checkouts/gecko/dom/promise/Promise.cpp:407) +# by 0xD6EBFB9: mozilla::dom::NativeHandlerCallback(JSContext*, unsigned int, JS::Value*)+441 (dist/include/js/RootingAPI.h:0) +# by 0xEF9D780: js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason)+768 (checkouts/gecko/js/src/vm/Interpreter.cpp:425) +# by 0xEF9E27C: js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason)+156 (checkouts/gecko/js/src/vm/Interpreter.cpp:572) +{ + Bug 1762046 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:moz_xmalloc + fun:operator new + fun:_ZN13nsDynamicAtom6CreateERK12nsTSubstringIDsEj* + fun:_ZN11nsAtomTable7AtomizeERK12nsTSubstringIDsE* + fun:_ZN11nsAttrValue9ParseAtomERK12nsTSubstringIDsE* + ... + fun:_ZN7mozilla3dom7Element7SetAttrEiP6nsAtomS3_RK12nsTSubstringIDsEP12nsIPrincipalb +} + +{ + False positive from new optimizations in rustc 1.73 + Memcheck:Cond + ... + fun:drop_in_place<hashbrown::raw::RawIntoIter<(webrender_api::image::ImageFormat, (webrender::texture_pack::guillotine::GuillotineAllocator, alloc::vec::Vec<webrender::renderer::upload::BatchUploadBuffer, alloc::alloc::Global>)), alloc::alloc::Global>> + ... + fun:upload_to_texture_cache +} diff --git a/build/variables.py b/build/variables.py new file mode 100644 index 0000000000..357e05c37b --- /dev/null +++ b/build/variables.py @@ -0,0 +1,111 @@ +# 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/. + +import os +import subprocess +import sys +from datetime import datetime + +SOURCESTAMP_FILENAME = "sourcestamp.txt" + + +def buildid_header(output): + buildid = os.environ.get("MOZ_BUILD_DATE") + if buildid and len(buildid) != 14: + print("Ignoring invalid MOZ_BUILD_DATE: %s" % buildid, file=sys.stderr) + buildid = None + if not buildid: + buildid = datetime.now().strftime("%Y%m%d%H%M%S") + output.write("#define MOZ_BUILDID %s\n" % buildid) + + +def get_program_output(*command): + try: + with open(os.devnull) as stderr: + return subprocess.check_output( + command, stderr=stderr, universal_newlines=True + ) + except Exception: + return "" + + +def get_hg_info(workdir): + repo = get_program_output("hg", "-R", workdir, "path", "default") + if repo: + repo = repo.strip() + if repo.startswith("ssh://"): + repo = "https://" + repo[6:] + repo = repo.rstrip("/") + + changeset = get_hg_changeset(workdir) + + return repo, changeset + + +def get_hg_changeset(path): + return get_program_output("hg", "-R", path, "parent", "--template={node}") + + +def get_info_from_sourcestamp(sourcestamp_path): + """Read the repository and changelog information from the sourcestamp + file. This assumes that the file exists and returns the results as a list + (either strings or None in case of error). + """ + + # Load the content of the file. + lines = None + with open(sourcestamp_path) as f: + lines = f.read().splitlines() + + # Parse the repo and the changeset. The sourcestamp file is supposed to + # contain two lines: the first is the build id and the second is the source + # URL. + if len(lines) != 2 or not lines[1].startswith("http"): + # Just return if the file doesn't contain what we expect. + return None, None + + # Return the repo and the changeset. + return lines[1].split("/rev/") + + +def source_repo_header(output): + # We allow the source repo and changeset to be specified via the + # environment (see configure) + import buildconfig + + repo = buildconfig.substs.get("MOZ_SOURCE_REPO") + changeset = buildconfig.substs.get("MOZ_SOURCE_CHANGESET") + source = "" + + if not repo: + sourcestamp_path = os.path.join(buildconfig.topsrcdir, SOURCESTAMP_FILENAME) + if os.path.exists(os.path.join(buildconfig.topsrcdir, ".hg")): + repo, changeset = get_hg_info(buildconfig.topsrcdir) + elif os.path.exists(sourcestamp_path): + repo, changeset = get_info_from_sourcestamp(sourcestamp_path) + elif not changeset: + changeset = get_hg_changeset(buildconfig.topsrcdir) + if not changeset: + raise Exception( + "could not resolve changeset; " "try setting MOZ_SOURCE_CHANGESET" + ) + + if changeset: + output.write("#define MOZ_SOURCE_STAMP %s\n" % changeset) + + if repo and buildconfig.substs.get("MOZ_INCLUDE_SOURCE_INFO"): + source = "%s/rev/%s" % (repo, changeset) + output.write("#define MOZ_SOURCE_REPO %s\n" % repo) + output.write("#define MOZ_SOURCE_URL %s\n" % source) + + +def main(args): + if len(args): + func = globals().get(args[0]) + if func: + return func(sys.stdout, *args[1:]) + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/build/vs/generate_yaml.py b/build/vs/generate_yaml.py new file mode 100755 index 0000000000..0427804806 --- /dev/null +++ b/build/vs/generate_yaml.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# 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/. + +import sys + +import yaml +from mozbuild.shellutil import quote as shellquote +from vsdownload import ( + getArgsParser, + getManifest, + getPackages, + getSelectedPackages, + lowercaseIgnores, + setPackageSelection, +) + +if __name__ == "__main__": + parser = getArgsParser() + parser.add_argument("-o", dest="output", required=True, help="Output file") + parser.add_argument( + "--exclude", default=[], nargs="+", help="Patterns of file names to exclude" + ) + args = parser.parse_args() + lowercaseIgnores(args) + + packages = getPackages(getManifest(args)) + setPackageSelection(args, packages) + selected = getSelectedPackages(packages, args) + reduced = [] + # Filter-out data we won't be using. + for s in selected: + type = s["type"] + if type == "Component" or type == "Workload" or type == "Group": + continue + if type == "Vsix" or s["id"].startswith(("Win10SDK", "Win11SDK")): + filtered = {k: v for k, v in s.items() if k in ("type", "id", "version")} + filtered["payloads"] = [ + { + k: v + for k, v in payload.items() + if k in ("fileName", "sha256", "size", "url") + } + for payload in s["payloads"] + if payload["fileName"].endswith((".cab", ".msi", ".vsix")) + and not any(e in payload["fileName"] for e in args.exclude) + ] + reduced.append(filtered) + with open(args.output, "w") as out: + print("# Generated with:", file=out) + print( + "# ./mach python --virtualenv build build/vs/generate_yaml.py \\", file=out + ) + for i, arg_ in enumerate(sys.argv[1:]): + arg = shellquote(arg_) + if i < len(sys.argv) - 2: + print("# ", arg, "\\", file=out) + else: + print("# ", arg, file=out) + print(yaml.dump(reduced), file=out) diff --git a/build/vs/vs2019.yaml b/build/vs/vs2019.yaml new file mode 100644 index 0000000000..5d12a66b81 --- /dev/null +++ b/build/vs/vs2019.yaml @@ -0,0 +1,1853 @@ +# Generated with: +# ./mach python --virtualenv build build/vs/generate_yaml.py \ +# --major \ +# 16 \ +# Microsoft.VisualCpp.CRT.ARM64.Desktop \ +# Microsoft.VisualCpp.CRT.ARM64.Store \ +# Microsoft.VisualCpp.CRT.Headers \ +# Microsoft.VisualCpp.CRT.Redist.ARM64 \ +# Microsoft.VisualCpp.CRT.Redist.X64 \ +# Microsoft.VisualCpp.CRT.Redist.X86 \ +# Microsoft.VisualCpp.CRT.x64.Desktop \ +# Microsoft.VisualCpp.CRT.x64.Store \ +# Microsoft.VisualCpp.CRT.x86.Desktop \ +# Microsoft.VisualCpp.CRT.x86.Store \ +# Microsoft.VisualCpp.DIA.SDK \ +# Microsoft.VisualCpp.Tools.HostX64.TargetARM64 \ +# Microsoft.VisualCpp.Tools.HostX64.TargetX64 \ +# Microsoft.VisualCpp.Tools.HostX64.TargetX86 \ +# Microsoft.VisualStudio.Component.VC.ATL.ARM64 \ +# Microsoft.VisualStudio.Component.VC.ATLMFC \ +# Microsoft.VisualStudio.Component.VC.MFC.ARM64 \ +# Win10SDK_10.0.19041 \ +# -o \ +# build/vs/vs2019.yaml \ +# --exclude \ +# Contracts \ +# 'App Certification Kit Native Components' \ +# Intellisense +- id: Microsoft.VisualCpp.CRT.ARM64.Desktop + payloads: + - fileName: Microsoft.VisualCpp.CRT.ARM64.Desktop.vsix + sha256: e816df1935b5a01db94c2594482ce458cfd64cf9725a902c1672c3b8c06bcad0 + size: 1076 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/e816df1935b5a01db94c2594482ce458cfd64cf9725a902c1672c3b8c06bcad0/Microsoft.VisualCpp.CRT.ARM64.Desktop.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.ARM64.Desktop.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.ARM64.Desktop.base.vsix + sha256: 136b8349982030489394e3ac1bdb490a2ba1fa93597d53d0da6fb94f4af10f62 + size: 53888641 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/136b8349982030489394e3ac1bdb490a2ba1fa93597d53d0da6fb94f4af10f62/Microsoft.VC.14.29.16.11.CRT.ARM64.Desktop.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.ARM64.Desktop.debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.ARM64.Desktop.debug.base.vsix + sha256: 9dd7bf94132ba11f2d88b01bac0463de8007e63deaed7623ccfe41b244bc068a + size: 47277534 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/9dd7bf94132ba11f2d88b01bac0463de8007e63deaed7623ccfe41b244bc068a/Microsoft.VC.14.29.16.11.CRT.ARM64.Desktop.debug.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Props.ARM64 + payloads: + - fileName: Microsoft.VC.14.29.16.11.Props.ARM64.vsix + sha256: 6c44879670d416a7298c860d61a3cfe2de5285164424e7036eb7d19f3a25ab93 + size: 2266 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/6c44879670d416a7298c860d61a3cfe2de5285164424e7036eb7d19f3a25ab93/Microsoft.VC.14.29.16.11.Props.ARM64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Props + payloads: + - fileName: Microsoft.VC.14.29.16.11.Props.vsix + sha256: 96323474b850886b125f1cfe70eb6cbe256480d86f7ec38b34e39064cd395869 + size: 3934 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/96323474b850886b125f1cfe70eb6cbe256480d86f7ec38b34e39064cd395869/Microsoft.VC.14.29.16.11.Props.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.ARM64.Store + payloads: + - fileName: Microsoft.VisualCpp.CRT.ARM64.Store.vsix + sha256: c621e7db7b2cac7baa8d9f8a7e5066d3f55c4f09653846ff554fc3375dba95ab + size: 1074 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/c621e7db7b2cac7baa8d9f8a7e5066d3f55c4f09653846ff554fc3375dba95ab/Microsoft.VisualCpp.CRT.ARM64.Store.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.ARM64.Store.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.ARM64.Store.base.vsix + sha256: 5eaee5eb9ecb82f7034ff868c482a8723bcc2138b9b1158605e0fb79ab5ef889 + size: 51721919 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/5eaee5eb9ecb82f7034ff868c482a8723bcc2138b9b1158605e0fb79ab5ef889/Microsoft.VC.14.29.16.11.CRT.ARM64.Store.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.Headers + payloads: + - fileName: Microsoft.VisualCpp.CRT.Headers.vsix + sha256: ec863affc71c7d0a678b7cfb150bd9d1b3e592caf9036873a4f72035854e92ef + size: 1070 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/ec863affc71c7d0a678b7cfb150bd9d1b3e592caf9036873a4f72035854e92ef/Microsoft.VisualCpp.CRT.Headers.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.CRT.Headers.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.Headers.base.vsix + sha256: 1e712a94953ed46fa8074972ed72a1c789724e801e2a6a7dca534505377208f6 + size: 3437995 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/1e712a94953ed46fa8074972ed72a1c789724e801e2a6a7dca534505377208f6/Microsoft.VC.14.29.16.11.CRT.Headers.base.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.Servicing.CrtHeaders + payloads: + - fileName: Microsoft.VC.14.29.16.11.Servicing.CrtHeaders.vsix + sha256: 59ed7e9386dbbcfb8e37669278d7e12eca6cc778d06addce593ce54b555cf836 + size: 2009 + url: https://download.visualstudio.microsoft.com/download/pr/5aa29bdc-6bb2-4c9c-b0e8-286fd4bd4cee/59ed7e9386dbbcfb8e37669278d7e12eca6cc778d06addce593ce54b555cf836/Microsoft.VC.14.29.16.11.Servicing.CrtHeaders.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.Servicing + payloads: + - fileName: Microsoft.VC.14.29.16.11.Servicing.vsix + sha256: 62ff045d0b9846003524f52f5cb769f0a763fd135c799b0ac3fd499c3747a58e + size: 2204 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/62ff045d0b9846003524f52f5cb769f0a763fd135c799b0ac3fd499c3747a58e/Microsoft.VC.14.29.16.11.Servicing.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.Redist.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.ARM64.vsix + sha256: e2e2b3b207a35122a7f9a27e94ff27583124fb1aa9639b7335da62aa24e6d225 + size: 22526228 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/e2e2b3b207a35122a7f9a27e94ff27583124fb1aa9639b7335da62aa24e6d225/Microsoft.VisualCpp.CRT.Redist.ARM64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.Redist.ARM64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.Redist.ARM64.base.vsix + sha256: 83901070cdce1ed33d9f310993705b67c66a85a35f69cb15e338d9ecb160dd67 + size: 5237346 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/83901070cdce1ed33d9f310993705b67c66a85a35f69cb15e338d9ecb160dd67/Microsoft.VC.14.29.16.11.CRT.Redist.ARM64.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.Redist.Resources + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.Resources.enu.vsix + sha256: b55e0b3fdc55c1860799ba25acfe55e5c9c548f02bffc61adb247603969ce130 + size: 1059 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/b55e0b3fdc55c1860799ba25acfe55e5c9c548f02bffc61adb247603969ce130/Microsoft.VisualCpp.CRT.Redist.Resources.enu.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.Redist.X64 + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.X64.vsix + sha256: db639a7aade3ce017be0159aefa111aca01b654574a43129e4873303d4317ef5 + size: 100010996 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/db639a7aade3ce017be0159aefa111aca01b654574a43129e4873303d4317ef5/Microsoft.VisualCpp.CRT.Redist.X64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.Redist.X64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.Redist.X64.base.vsix + sha256: d8cb27a1086947db4256bcff101d0439d4ff8df2497dcac16d2fd2a27bf834fd + size: 3448811 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/d8cb27a1086947db4256bcff101d0439d4ff8df2497dcac16d2fd2a27bf834fd/Microsoft.VC.14.29.16.11.CRT.Redist.X64.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.Redist.X86 + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.X86.vsix + sha256: 17b7645dc9bdb69d2953c0e39e77f9be465d99ce8ad8dfc373e78eb71feae428 + size: 54297308 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/17b7645dc9bdb69d2953c0e39e77f9be465d99ce8ad8dfc373e78eb71feae428/Microsoft.VisualCpp.CRT.Redist.X86.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.Redist.X86.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.Redist.X86.base.vsix + sha256: 93427310e0b9cefb1c9fae1fd60fc0cc9e8d90f64c360e9483fe71e307f1a295 + size: 2961562 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/93427310e0b9cefb1c9fae1fd60fc0cc9e8d90f64c360e9483fe71e307f1a295/Microsoft.VC.14.29.16.11.CRT.Redist.X86.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.x64.Desktop + payloads: + - fileName: Microsoft.VisualCpp.CRT.x64.Desktop.vsix + sha256: 63d76f049bf86ee1c7e57d9c5568c2a16daf9ac8fa977e72c9c4443c40c57dbb + size: 1073 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/63d76f049bf86ee1c7e57d9c5568c2a16daf9ac8fa977e72c9c4443c40c57dbb/Microsoft.VisualCpp.CRT.x64.Desktop.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.x64.Desktop.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.x64.Desktop.base.vsix + sha256: 87127c5d18c9359d3e6c950ac7fd84ac49e229d4a356d80ed7b198500cbd3d9b + size: 42021723 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/87127c5d18c9359d3e6c950ac7fd84ac49e229d4a356d80ed7b198500cbd3d9b/Microsoft.VC.14.29.16.11.CRT.x64.Desktop.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.x64.Store + payloads: + - fileName: Microsoft.VisualCpp.CRT.x64.Store.vsix + sha256: 83e33550c9ed10ea116de26f6dc6b407fb3d330747e3721c7fba9d3704f81827 + size: 1071 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/83e33550c9ed10ea116de26f6dc6b407fb3d330747e3721c7fba9d3704f81827/Microsoft.VisualCpp.CRT.x64.Store.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.x64.Store.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.x64.Store.base.vsix + sha256: 9373ff18e5ae6a10a25defa380b5a73f1610766c3d6d44dc68bf4271ede3db44 + size: 19404083 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/9373ff18e5ae6a10a25defa380b5a73f1610766c3d6d44dc68bf4271ede3db44/Microsoft.VC.14.29.16.11.CRT.x64.Store.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.x86.Desktop + payloads: + - fileName: Microsoft.VisualCpp.CRT.x86.Desktop.vsix + sha256: c3512f91f378566246d32249a175907a519aea8817c715a5269a31737bc25797 + size: 1073 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/c3512f91f378566246d32249a175907a519aea8817c715a5269a31737bc25797/Microsoft.VisualCpp.CRT.x86.Desktop.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.x86.Desktop.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.x86.Desktop.base.vsix + sha256: 9ef2053c99f876b2c52b55a2586c673436f775a1d8e634bf80a0b14b55b0cc58 + size: 65528398 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/9ef2053c99f876b2c52b55a2586c673436f775a1d8e634bf80a0b14b55b0cc58/Microsoft.VC.14.29.16.11.CRT.x86.Desktop.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.CRT.x86.Store + payloads: + - fileName: Microsoft.VisualCpp.CRT.x86.Store.vsix + sha256: 8150ce3d657baec4aeec201e9e1be51edf735bc80a2f8da7205afe9cc6a5179c + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/8150ce3d657baec4aeec201e9e1be51edf735bc80a2f8da7205afe9cc6a5179c/Microsoft.VisualCpp.CRT.x86.Store.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.CRT.x86.Store.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.CRT.x86.Store.base.vsix + sha256: f5dfb9db88faaf6bc78b4b0cd25180daec08428e0ce21ab938136188d5631b11 + size: 18939298 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/f5dfb9db88faaf6bc78b4b0cd25180daec08428e0ce21ab938136188d5631b11/Microsoft.VC.14.29.16.11.CRT.x86.Store.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.DIA.SDK + payloads: + - fileName: Microsoft.VisualCpp.DIA.SDK.vsix + sha256: a231fc9d27492a57fd3730a5e6168e7ee2f5a90a48e07e66abfb5cb1c26656b2 + size: 6487893 + url: https://download.visualstudio.microsoft.com/download/pr/e4ed28b5-7428-4442-99c3-df5fa4ab6460/a231fc9d27492a57fd3730a5e6168e7ee2f5a90a48e07e66abfb5cb1c26656b2/Microsoft.VisualCpp.DIA.SDK.vsix + type: Vsix + version: 14.29.30152 +- id: Microsoft.VisualCpp.Servicing.DIASDK + payloads: + - fileName: Microsoft.VisualCpp.Servicing.DIASDK.vsix + sha256: 29c52e5a4db48831f1bf24c56c6cc110ded8b43852fd47f83717f1631756b3ca + size: 2003 + url: https://download.visualstudio.microsoft.com/download/pr/e4ed28b5-7428-4442-99c3-df5fa4ab6460/29c52e5a4db48831f1bf24c56c6cc110ded8b43852fd47f83717f1631756b3ca/Microsoft.VisualCpp.Servicing.DIASDK.vsix + type: Vsix + version: 14.29.30152 +- id: Microsoft.VisualCpp.Tools.HostX64.TargetARM64 + payloads: + - fileName: Microsoft.VisualCpp.Tools.HostX64.TargetARM64.vsix + sha256: f84c526cf9641f3d5d6a39a8e398c2397ff1ac1c86a5a7775f1b700f8618c440 + size: 2297 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/f84c526cf9641f3d5d6a39a8e398c2397ff1ac1c86a5a7775f1b700f8618c440/Microsoft.VisualCpp.Tools.HostX64.TargetARM64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetARM64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetARM64.base.vsix + sha256: ed76de1d4b4c48b088b6ce802e6690b7d7ea633078237e26db68fb68839b6c48 + size: 17416238 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/ed76de1d4b4c48b088b6ce802e6690b7d7ea633078237e26db68fb68839b6c48/Microsoft.VC.14.29.16.11.Tools.HostX64.TargetARM64.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetARM64.Res.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetARM64.Res.base.enu.vsix + sha256: 31a0aacb7c0db031b0a6e5a1830a936a38511c7c9ea2e5723e663c5544225444 + size: 216025 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/31a0aacb7c0db031b0a6e5a1830a936a38511c7c9ea2e5723e663c5544225444/Microsoft.VC.14.29.16.11.Tools.HostX64.TargetARM64.Res.base.enu.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Servicing.Compilers + payloads: + - fileName: Microsoft.VC.14.29.16.11.Servicing.Compilers.vsix + sha256: ecc26a58b5673ed923fcd09ab585bde1ddf4336c4e3472e9b264bd2050dd710b + size: 2003 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/ecc26a58b5673ed923fcd09ab585bde1ddf4336c4e3472e9b264bd2050dd710b/Microsoft.VC.14.29.16.11.Servicing.Compilers.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.Tools.HostX64.TargetX64 + payloads: + - fileName: Microsoft.VisualCpp.Tools.HostX64.TargetX64.vsix + sha256: b0a42f87830e1fc5569f2ba424105e90b30d6c5cff07295d4865694fa4c8af88 + size: 2246 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/b0a42f87830e1fc5569f2ba424105e90b30d6c5cff07295d4865694fa4c8af88/Microsoft.VisualCpp.Tools.HostX64.TargetX64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX64.base.vsix + sha256: c67458a1719d10f41750f58861241acd35d31d7732fdd94616ae31a25dab6beb + size: 18238717 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/c67458a1719d10f41750f58861241acd35d31d7732fdd94616ae31a25dab6beb/Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX64.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX64.Res.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX64.Res.base.enu.vsix + sha256: 5f9c8fdc7a0d74f791d698d55cda886839999c09790cc5564eb49b455012d836 + size: 215951 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/5f9c8fdc7a0d74f791d698d55cda886839999c09790cc5564eb49b455012d836/Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX64.Res.base.enu.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Props.x64 + payloads: + - fileName: Microsoft.VC.14.29.16.11.Props.x64.vsix + sha256: b580af879ba68e692690b167eb232fdfd5da2f320c1d2360e669765dafe44492 + size: 2340 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/b580af879ba68e692690b167eb232fdfd5da2f320c1d2360e669765dafe44492/Microsoft.VC.14.29.16.11.Props.x64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.Tools.HostX64.TargetX86 + payloads: + - fileName: Microsoft.VisualCpp.Tools.HostX64.TargetX86.vsix + sha256: 16bc2966d85ea7bdb1f7054dfa6940e5b920b72fa3c6c3964aebe778944bf5ac + size: 2283 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/16bc2966d85ea7bdb1f7054dfa6940e5b920b72fa3c6c3964aebe778944bf5ac/Microsoft.VisualCpp.Tools.HostX64.TargetX86.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX86.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX86.base.vsix + sha256: 58d29d6be41b28d2c46618cecbded76a4ea8808934cbabe9d2aedf8d90175ba3 + size: 18170072 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/58d29d6be41b28d2c46618cecbded76a4ea8808934cbabe9d2aedf8d90175ba3/Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX86.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX86.Res.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX86.Res.base.enu.vsix + sha256: c13649dcc13e7d3ace9626be600b267779e1868c9a0b1dbefcd063a3e884ac17 + size: 215953 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/c13649dcc13e7d3ace9626be600b267779e1868c9a0b1dbefcd063a3e884ac17/Microsoft.VC.14.29.16.11.Tools.HostX64.TargetX86.Res.base.enu.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.Props.x86 + payloads: + - fileName: Microsoft.VC.14.29.16.11.Props.x86.vsix + sha256: 4e3dda156cf57917961979934a35081bd375e07353378e2c241ac33b27eb8c07 + size: 2299 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/4e3dda156cf57917961979934a35081bd375e07353378e2c241ac33b27eb8c07/Microsoft.VC.14.29.16.11.Props.x86.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.ATL.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.ATL.ARM64.vsix + sha256: 86650aa335852da56cb3cd575a35ebe1b0f1cf1d8b09f8b9e0d198fdaa0f4d00 + size: 1071 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/86650aa335852da56cb3cd575a35ebe1b0f1cf1d8b09f8b9e0d198fdaa0f4d00/Microsoft.VisualCpp.ATL.ARM64.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.ATL.ARM64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.ATL.ARM64.base.vsix + sha256: 4e1223bf19d67077a33e15294cc402b48b4bbfe991d514372025eccb476ba9fd + size: 1258543 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/4e1223bf19d67077a33e15294cc402b48b4bbfe991d514372025eccb476ba9fd/Microsoft.VC.14.29.16.11.ATL.ARM64.base.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.Servicing.ATL + payloads: + - fileName: Microsoft.VC.14.29.16.11.Servicing.ATL.vsix + sha256: 77013d14944519e858b59ad97351a9076413e28cfb7ff89ae927c4f0e1421b20 + size: 1981 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/77013d14944519e858b59ad97351a9076413e28cfb7ff89ae927c4f0e1421b20/Microsoft.VC.14.29.16.11.Servicing.ATL.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.Props.ATLMFC + payloads: + - fileName: Microsoft.VC.14.29.16.11.Props.ATLMFC.vsix + sha256: 041b30bf1dfcb1fd126646fe67ff252f535547fc8ed1d3581a91ae7abf2f8c9d + size: 2178 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/041b30bf1dfcb1fd126646fe67ff252f535547fc8ed1d3581a91ae7abf2f8c9d/Microsoft.VC.14.29.16.11.Props.ATLMFC.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VisualCpp.ATL.Headers + payloads: + - fileName: Microsoft.VisualCpp.ATL.Headers.vsix + sha256: 889c5ae905e7b4e7f763fc91b7579083fdd74c36cda9846d66d6707bd34c40ae + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/889c5ae905e7b4e7f763fc91b7579083fdd74c36cda9846d66d6707bd34c40ae/Microsoft.VisualCpp.ATL.Headers.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.ATL.Headers.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.ATL.Headers.base.vsix + sha256: 4ff2cd9690514698d9542110766fbc2dff9c84a0c39f124adbebe8714cb8b64e + size: 571431 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/4ff2cd9690514698d9542110766fbc2dff9c84a0c39f124adbebe8714cb8b64e/Microsoft.VC.14.29.16.11.ATL.Headers.base.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VisualCpp.ATL.Source + payloads: + - fileName: Microsoft.VisualCpp.ATL.Source.vsix + sha256: 53693602a9137fb6ce9933d45e98ceb046af45f032134afdc1e8acb896be3f79 + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/53693602a9137fb6ce9933d45e98ceb046af45f032134afdc1e8acb896be3f79/Microsoft.VisualCpp.ATL.Source.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.ATL.Source.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.ATL.Source.base.vsix + sha256: 6364ad5d251c1aaf941b2af1e910ff4971715cf0bb7e6def2f14d3fc640860a7 + size: 8622 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/6364ad5d251c1aaf941b2af1e910ff4971715cf0bb7e6def2f14d3fc640860a7/Microsoft.VC.14.29.16.11.ATL.Source.base.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VisualStudio.VC.Ide.ATL + payloads: + - fileName: payload.vsix + sha256: 5292b2fe846dded0859a498cae2dffbea6d7b747be02e294892d414c985eff9b + size: 12122 + url: https://download.visualstudio.microsoft.com/download/pr/698b1517-117a-4f4b-b6e2-2e61c894fc29/5292b2fe846dded0859a498cae2dffbea6d7b747be02e294892d414c985eff9b/payload.vsix + type: Vsix + version: 16.10.31205.180 +- id: Microsoft.VisualStudio.VC.Ide.ATL.Resources + payloads: + - fileName: payload.vsix + sha256: 5e2e0db47336354ad44b8b138e3ca7ed6197d40711357f0856686f686d2d4159 + size: 45579 + url: https://download.visualstudio.microsoft.com/download/pr/af620239-98ad-431d-8a3d-f04ac1b3dc34/5e2e0db47336354ad44b8b138e3ca7ed6197d40711357f0856686f686d2d4159/payload.vsix + type: Vsix + version: 16.10.31306.167 +- id: Microsoft.VisualCpp.ATL.X64 + payloads: + - fileName: Microsoft.VisualCpp.ATL.X64.vsix + sha256: 01c75ae0a45c9095a740c35655738e9f7701a65baef4aa41edd48f452174a579 + size: 1071 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/01c75ae0a45c9095a740c35655738e9f7701a65baef4aa41edd48f452174a579/Microsoft.VisualCpp.ATL.X64.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.ATL.X64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.ATL.X64.base.vsix + sha256: 9c334ff48217f79a00857d359f734e3dbbaba63ee976b27e3cba7157a8fb2b10 + size: 740841 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/9c334ff48217f79a00857d359f734e3dbbaba63ee976b27e3cba7157a8fb2b10/Microsoft.VC.14.29.16.11.ATL.X64.base.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VisualCpp.ATL.X86 + payloads: + - fileName: Microsoft.VisualCpp.ATL.X86.vsix + sha256: afde9e22e5f46cb18af1e369284fec19829fac27cb8ed4739eed9e30c4f1394a + size: 1071 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/afde9e22e5f46cb18af1e369284fec19829fac27cb8ed4739eed9e30c4f1394a/Microsoft.VisualCpp.ATL.X86.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VC.14.29.16.11.ATL.X86.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.ATL.X86.base.vsix + sha256: 455919063c3859889022f26dab5742b1b6eab19b34b4ec84d2b8774dcf7eb5e1 + size: 784442 + url: https://download.visualstudio.microsoft.com/download/pr/6bd9aa8c-916b-47c0-a30d-7f8d3e7d7423/455919063c3859889022f26dab5742b1b6eab19b34b4ec84d2b8774dcf7eb5e1/Microsoft.VC.14.29.16.11.ATL.X86.base.vsix + type: Vsix + version: 14.29.30145 +- id: Microsoft.VisualCpp.MFC.Headers + payloads: + - fileName: Microsoft.VisualCpp.MFC.Headers.vsix + sha256: bcdc1a62488d3cbdf0c5b7ff212d85dfdd348724f8a1c757ab4ac1859f61ec4b + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/bcdc1a62488d3cbdf0c5b7ff212d85dfdd348724f8a1c757ab4ac1859f61ec4b/Microsoft.VisualCpp.MFC.Headers.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.Headers.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.Headers.base.vsix + sha256: 55e71c93053677ac7c5d84eb99f76ce457c799f2b4771b8381bf996d074c3b50 + size: 2366310 + url: https://download.visualstudio.microsoft.com/download/pr/5aa29bdc-6bb2-4c9c-b0e8-286fd4bd4cee/55e71c93053677ac7c5d84eb99f76ce457c799f2b4771b8381bf996d074c3b50/Microsoft.VC.14.29.16.11.MFC.Headers.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.Servicing.MFC + payloads: + - fileName: Microsoft.VC.14.29.16.11.Servicing.MFC.vsix + sha256: 09d086ea55f8f32457e85d858deed99e1e5dfc9c4b25335e59d61db08f936e87 + size: 1982 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/09d086ea55f8f32457e85d858deed99e1e5dfc9c4b25335e59d61db08f936e87/Microsoft.VC.14.29.16.11.Servicing.MFC.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.MBCS + payloads: + - fileName: Microsoft.VisualCpp.MFC.MBCS.vsix + sha256: ce98eee859f69f5aa0f09a4bfe8632106da4489d9fe4a96697672b032e6ffcc1 + size: 1070 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/ce98eee859f69f5aa0f09a4bfe8632106da4489d9fe4a96697672b032e6ffcc1/Microsoft.VisualCpp.MFC.MBCS.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.MBCS.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.MBCS.base.vsix + sha256: 3727251f42d3b73b20d6261f6ed241f04dfcea78e22b494d96d036e9cdcacd8c + size: 26812235 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/3727251f42d3b73b20d6261f6ed241f04dfcea78e22b494d96d036e9cdcacd8c/Microsoft.VC.14.29.16.11.MFC.MBCS.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.MBCS.Debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.MBCS.Debug.base.vsix + sha256: 4ff37e84f233d5a3a1295c26186a700ea0d51f42b8e1a78c5b1bfc5f6c82a388 + size: 28661584 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/4ff37e84f233d5a3a1295c26186a700ea0d51f42b8e1a78c5b1bfc5f6c82a388/Microsoft.VC.14.29.16.11.MFC.MBCS.Debug.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.MBCS.X64.Debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.MBCS.X64.Debug.base.vsix + sha256: f8022f9e133293855be58009efc0185520bd08f5b5341c33d56892fe8a548bb6 + size: 32629695 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/f8022f9e133293855be58009efc0185520bd08f5b5341c33d56892fe8a548bb6/Microsoft.VC.14.29.16.11.MFC.MBCS.X64.Debug.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.MBCS.X64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.MBCS.X64.base.vsix + sha256: 819c7e14ea676b5b66ff44fefc50d3d6e1ee6345ab1bd4fe61870a26a20c2ae0 + size: 29849196 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/819c7e14ea676b5b66ff44fefc50d3d6e1ee6345ab1bd4fe61870a26a20c2ae0/Microsoft.VC.14.29.16.11.MFC.MBCS.X64.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.MBCS.X64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.MBCS.X64.vsix + sha256: 45af778f1f6ae0d05176e440bd281511dbfbf479b3bc1b6af3c9a66a2d67b2d1 + size: 1074 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/45af778f1f6ae0d05176e440bd281511dbfbf479b3bc1b6af3c9a66a2d67b2d1/Microsoft.VisualCpp.MFC.MBCS.X64.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.Redist.X64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.Redist.X64.vsix + sha256: ebb38eb54877b36c9f3c92de9da555ad97ab94d635a99c5f858c99f3f32bd03d + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/ebb38eb54877b36c9f3c92de9da555ad97ab94d635a99c5f858c99f3f32bd03d/Microsoft.VisualCpp.MFC.Redist.X64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.MFC.Redist.X64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.Redist.X64.base.vsix + sha256: 5346236767c3554fb46a681d6bafce4fd580a017beafd1cd15d25ab36d971fb6 + size: 13730780 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/5346236767c3554fb46a681d6bafce4fd580a017beafd1cd15d25ab36d971fb6/Microsoft.VC.14.29.16.11.MFC.Redist.X64.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.MFC.Redist.X86 + payloads: + - fileName: Microsoft.VisualCpp.MFC.Redist.X86.vsix + sha256: 8a288baeea2aedd94d4b251d4ca922673b5b8b78db6f180a78abe62d3d43ee16 + size: 1073 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/8a288baeea2aedd94d4b251d4ca922673b5b8b78db6f180a78abe62d3d43ee16/Microsoft.VisualCpp.MFC.Redist.X86.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.MFC.Redist.X86.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.Redist.X86.base.vsix + sha256: ef9b33522b54a914a7f0cb50d05843f42cd66f8457d9ba4059e008129de33b74 + size: 13272352 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/ef9b33522b54a914a7f0cb50d05843f42cd66f8457d9ba4059e008129de33b74/Microsoft.VC.14.29.16.11.MFC.Redist.X86.base.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VisualCpp.MFC.Source + payloads: + - fileName: Microsoft.VisualCpp.MFC.Source.vsix + sha256: 0b978380d8a4fed5a825a4f713cd472607bf88b9603614c04bfd526bd898c4a1 + size: 1071 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/0b978380d8a4fed5a825a4f713cd472607bf88b9603614c04bfd526bd898c4a1/Microsoft.VisualCpp.MFC.Source.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.Source.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.Source.base.vsix + sha256: 4a4e38d505f64bab5c719ae10566a2171ee9863c7d1aa0a28bf90d93d432c527 + size: 2294054 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/4a4e38d505f64bab5c719ae10566a2171ee9863c7d1aa0a28bf90d93d432c527/Microsoft.VC.14.29.16.11.MFC.Source.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.X64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.X64.vsix + sha256: a219eb0892ed22d06770011227e9c143b4972856424d57a0db15faf3b5f957e2 + size: 1070 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/a219eb0892ed22d06770011227e9c143b4972856424d57a0db15faf3b5f957e2/Microsoft.VisualCpp.MFC.X64.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.X64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.X64.base.vsix + sha256: 56281b6b365024ff42bcf328d6bf10f6aba8b4a113efbad7c02fcfff7286c900 + size: 32188461 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/56281b6b365024ff42bcf328d6bf10f6aba8b4a113efbad7c02fcfff7286c900/Microsoft.VC.14.29.16.11.MFC.X64.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.X64.Debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.X64.Debug.base.vsix + sha256: 1e2c5e9c239a92ca0a552bc3a00cb60ba2f3e481aee4b54d884e604172150373 + size: 34588024 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/1e2c5e9c239a92ca0a552bc3a00cb60ba2f3e481aee4b54d884e604172150373/Microsoft.VC.14.29.16.11.MFC.X64.Debug.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.X86 + payloads: + - fileName: Microsoft.VisualCpp.MFC.X86.vsix + sha256: fa36658a39ffbd3872e67c9fff1c54c8e9a74ddb430f44c1c4e9c62b6182a373 + size: 1070 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/fa36658a39ffbd3872e67c9fff1c54c8e9a74ddb430f44c1c4e9c62b6182a373/Microsoft.VisualCpp.MFC.X86.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.X86.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.X86.base.vsix + sha256: d691c2e2631d8d742ed86ad74606f8de0dcbdfd7616017d032feb8896fb9781e + size: 29236919 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/d691c2e2631d8d742ed86ad74606f8de0dcbdfd7616017d032feb8896fb9781e/Microsoft.VC.14.29.16.11.MFC.X86.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.X86.Debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.X86.Debug.base.vsix + sha256: b11c5670c45ebced0c877df9df9b524ab79d0106017604288547efba741c1343 + size: 30863163 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/b11c5670c45ebced0c877df9df9b524ab79d0106017604288547efba741c1343/Microsoft.VC.14.29.16.11.MFC.X86.Debug.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualStudio.VC.Ide.MFC + payloads: + - fileName: payload.vsix + sha256: 840b5385f7df054f4e9f190c9dad385e78aeb828d36e28a4ff1e11ceac7e1718 + size: 13904 + url: https://download.visualstudio.microsoft.com/download/pr/698b1517-117a-4f4b-b6e2-2e61c894fc29/840b5385f7df054f4e9f190c9dad385e78aeb828d36e28a4ff1e11ceac7e1718/payload.vsix + type: Vsix + version: 16.10.31205.180 +- id: Microsoft.VisualStudio.VC.Ide.MFC.Resources + payloads: + - fileName: payload.vsix + sha256: 1557742ea669d9966f3d86664ed1da245ff64c3a61135c9293c5b2c1b8db328c + size: 343541 + url: https://download.visualstudio.microsoft.com/download/pr/803ce97b-5d5c-403f-a7c9-ffd9e99c0bb7/1557742ea669d9966f3d86664ed1da245ff64c3a61135c9293c5b2c1b8db328c/payload.vsix + type: Vsix + version: 16.11.31603.221 +- id: Microsoft.VisualCpp.MFC.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.ARM64.vsix + sha256: 988ebdb1734d6c753b84279fe11962b818ae612cd9a93c087aba26e141b65fb1 + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/988ebdb1734d6c753b84279fe11962b818ae612cd9a93c087aba26e141b65fb1/Microsoft.VisualCpp.MFC.ARM64.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.ARM64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.ARM64.base.vsix + sha256: b1772b9044a2694df1cedd80a554f5e455bbf14da775e95ce2bf22f446779506 + size: 65287645 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/b1772b9044a2694df1cedd80a554f5e455bbf14da775e95ce2bf22f446779506/Microsoft.VC.14.29.16.11.MFC.ARM64.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.ARM64.Debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.ARM64.Debug.base.vsix + sha256: c1f0dd219f2701762c3b37e0c7ab84664e631a48fb6bdf6adf3ea647531c46a3 + size: 70839775 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/c1f0dd219f2701762c3b37e0c7ab84664e631a48fb6bdf6adf3ea647531c46a3/Microsoft.VC.14.29.16.11.MFC.ARM64.Debug.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.MBCS.arm64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.MBCS.arm64.vsix + sha256: 294c3e925c1e7967aaba1428609df40fce28d61fd37434548a5881334e50b5b0 + size: 1075 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/294c3e925c1e7967aaba1428609df40fce28d61fd37434548a5881334e50b5b0/Microsoft.VisualCpp.MFC.MBCS.arm64.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.MBCS.arm64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.MBCS.arm64.base.vsix + sha256: 9ea5ceb6b149beadd3502ef26ffab7614d8a009d7747a6535ee36ec03a1ebb7b + size: 62634341 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/9ea5ceb6b149beadd3502ef26ffab7614d8a009d7747a6535ee36ec03a1ebb7b/Microsoft.VC.14.29.16.11.MFC.MBCS.arm64.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VC.14.29.16.11.MFC.MBCS.arm64.Debug.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.MBCS.arm64.Debug.base.vsix + sha256: 91dd250ca23a54c540fa0364e3599e4296259de00b7063c4bfecd6b9d5960aff + size: 68984101 + url: https://download.visualstudio.microsoft.com/download/pr/a5caea7c-7f6b-4d48-9b80-c77732421206/91dd250ca23a54c540fa0364e3599e4296259de00b7063c4bfecd6b9d5960aff/Microsoft.VC.14.29.16.11.MFC.MBCS.arm64.Debug.base.vsix + type: Vsix + version: 14.29.30136 +- id: Microsoft.VisualCpp.MFC.Redist.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.Redist.ARM64.vsix + sha256: 10414c0a3c96777dcfbfca4461c448733029eb55d8e224b00e70bdac0d84b1c6 + size: 1075 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/10414c0a3c96777dcfbfca4461c448733029eb55d8e224b00e70bdac0d84b1c6/Microsoft.VisualCpp.MFC.Redist.ARM64.vsix + type: Vsix + version: 14.29.30153 +- id: Microsoft.VC.14.29.16.11.MFC.Redist.ARM64.base + payloads: + - fileName: Microsoft.VC.14.29.16.11.MFC.Redist.ARM64.base.vsix + sha256: 906929e3d2ccd1d7747cd3b93cbe65ad854ad804a9006c680e4e04cbf960735f + size: 22867984 + url: https://download.visualstudio.microsoft.com/download/pr/ed573b12-f211-4911-834c-c3e3a87d7e58/906929e3d2ccd1d7747cd3b93cbe65ad854ad804a9006c680e4e04cbf960735f/Microsoft.VC.14.29.16.11.MFC.Redist.ARM64.base.vsix + type: Vsix + version: 14.29.30153 +- id: Win10SDK_10.0.19041 + payloads: + - fileName: Installers\e680f23450a21a27b2077dbdc08ca430.cab + sha256: C0D52C77E727442CF613E2B93E210FE71C4B4BB8F78560CAFBC555884F86398F + size: 5016970 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/cc1fb626414a2ef378f089bed0da2690/e680f23450a21a27b2077dbdc08ca430.cab + - fileName: Installers\6e86d5003787b5a44d77f0142b20f2ff.cab + sha256: 18F19018FB8BE7DC96A520AB68392FEFD02586A9106ABC694CF840992230F56C + size: 101001 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2eefb95643b1c522e447d3772feb8ee6/6e86d5003787b5a44d77f0142b20f2ff.cab + - fileName: Installers\e87de81a902e0c8cde9e1355c3ff5f3f.cab + sha256: FD8D05883AB4F60C047E5085B73DFBAA4231BE2BA52B18BD18F313EC282586FB + size: 1687385 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b5fe57144dc97956bc55456db66f4dc2/e87de81a902e0c8cde9e1355c3ff5f3f.cab + - fileName: Installers\0253f7df0974f9d7169b410d812a5385.cab + sha256: BB572FE32B8EDBAF55CF0850D080B0A29B4C3E029D5E392BA2E6206ABECF5556 + size: 8234084 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/113aa8dbc9d69c1dbbf042b816218a7e/0253f7df0974f9d7169b410d812a5385.cab + - fileName: Installers\e8bc712abeffd7c9711ee3f55d4aa99b.cab + sha256: 990A96F3BEC365176B4A3E083AC9E346FF75E41EDA10E32A6AE3CDBE437C7FF0 + size: 1059969 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f970cf8826b3e6a388dffbd3ce5f35db/e8bc712abeffd7c9711ee3f55d4aa99b.cab + - fileName: Installers\e98fa5eb5fee6ce17a7a69d585870b7c.cab + sha256: 7EA7C9582EFE60DE84F125DFDAF2C19AA40E21CB0794E54011B0EC8E0F734C7A + size: 1416860 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c14ca0274f5f590614cb878e4ad7cb20/e98fa5eb5fee6ce17a7a69d585870b7c.cab + - fileName: Installers\ec0637c03f99046936d32d51e13a392a.cab + sha256: C8CBA0B20503F328C7D147779C6982DF826AE9CDC8E336AEB5BAC2F6C67FB373 + size: 14234 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/850959f05420de15ed6fdc75b48e59d3/ec0637c03f99046936d32d51e13a392a.cab + - fileName: Installers\6ee7bbee8435130a869cf971694fd9e2.cab + sha256: E5629CBDC37A33ADEBF2EB6C117104ACEF06140B9C398618E3D12790A320AC05 + size: 22141076 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/06e8bd6e1f267529fe5831f27d3d5fe3/6ee7bbee8435130a869cf971694fd9e2.cab + - fileName: Installers\03fbc2dfe9d3e7bb2389c7ed18c6ad3e.cab + sha256: EBCC395657E3E0FAD9FAEB9FB4E61C46E3781D0C2E3FF678A57A6690900AFEA7 + size: 746786 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/29cbf4b864894b80ad40d2755a34f8b6/03fbc2dfe9d3e7bb2389c7ed18c6ad3e.cab + - fileName: Installers\05047a45609f311645eebcac2739fc4c.cab + sha256: F759124EDC64C9BA31054E8A05ED777FFF56A1E1B5397446F992DCE32B50419E + size: 243424 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3667e761369e557be3d33e8ed737e9f9/05047a45609f311645eebcac2739fc4c.cab + - fileName: Installers\ec9ab4bbb809719605d27da343b909e8.cab + sha256: 96F160FD762FF58F193DC98D4FFD1809FDD07CA7A11365EF27334A8CD259F612 + size: 98902 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b43d143e7cad6ad2439079f20fc0f3c2/ec9ab4bbb809719605d27da343b909e8.cab + - fileName: Installers\703316c9de0a32acf316d03b1cffc559.cab + sha256: 543C408CB1CE437E0940E4D58043E2A3BE8764C974224DA2AD0CD231626F6914 + size: 3996018 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/db2464dc3d237e8171780622525df9ca/703316c9de0a32acf316d03b1cffc559.cab + - fileName: Installers\ec9d39539c27e8cf5ad39bffce00c34e.cab + sha256: 175A3F1F9421AA65903CAA03C76B5F977EC579305F25D6AC5E3EB011BCDFF241 + size: 212492 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/439f03f4add8d824414dc959ea5f9ecd/ec9d39539c27e8cf5ad39bffce00c34e.cab + - fileName: Installers\7178f554c01f912c749b622564106b02.cab + sha256: 724E720CE3B3715A8746DF9316C7F4E9294DF6B414BE6A8D0C033D58ADFAB838 + size: 1141278 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/061af5895766d8eeb0f1e9e8c2560d4b/7178f554c01f912c749b622564106b02.cab + - fileName: Installers\eca0aa33de85194cd50ed6e0aae0156f.cab + sha256: F7B9549E548B2BA7D0965BA03B73D979AD08615FFFF62365CA689AB729C8F96F + size: 37517 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2aa8af76a32e2985282c11031f867c5b/eca0aa33de85194cd50ed6e0aae0156f.cab + - fileName: Installers\05254f60ea43b4e3959b17cdb03268c0.cab + sha256: 86A3CA95105520D28CD80B3BFA997D187B2280ADC67F3AD7E9B9164A448D5D51 + size: 597767 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/9a0a22936f5546fc1cbaa58370665578/05254f60ea43b4e3959b17cdb03268c0.cab + - fileName: Installers\ed4d1c6b9811d81e3cebc553ae604f0d.cab + sha256: C947524E4A153E6BA6491B1D23626DAE3B8C75957BA34389D28AB2864179570C + size: 14383 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7a78c5ee84e6cb5494c0c69290e13487/ed4d1c6b9811d81e3cebc553ae604f0d.cab + - fileName: Installers\ed5aa2f399092df3084cce671f072cac.cab + sha256: BCBB1DA145CAB0F57927D2906A28004FEBB1F9C15FB63D3C67312D1E62FCD625 + size: 1499005 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b4de39ae2a7ecfb3e6ec0fbb303c2d1d/ed5aa2f399092df3084cce671f072cac.cab + - fileName: Installers\72bda6e16f5c7a040361c1304b4b5b36.cab + sha256: 4B390B7C8F3D270B0D19923A980F9D177107CBAD9A4EF2070353FD1ECA365CD5 + size: 7808472 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3c8ac3d543fb9b1393253fb062e123ba/72bda6e16f5c7a040361c1304b4b5b36.cab + - fileName: Installers\73b80f421d7f3df5a71bd772f56bf3ae.cab + sha256: 099F340A46E4E2DBB0AF9BF809A438387BFBCF1F73AD890D41218F6E2866752C + size: 94504 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6ac987919fbf2eb7d6406dca9dcf303c/73b80f421d7f3df5a71bd772f56bf3ae.cab + - fileName: Installers\07a57cdb41ba28cced14005f087267be.cab + sha256: 890F3D64A27C5216ACF5AA82BA495D0023B5E65EA4963D1D34682AAB7FAB4265 + size: 98141 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d53d78d9f16b49f17a59bce07c4e2b4c/07a57cdb41ba28cced14005f087267be.cab + - fileName: Installers\ef4472fd7552490fd759075186ed2ec8.cab + sha256: 5C09D4A91DC0DF3E9E09A5D7F56CD29F04571CCD5055461C005616DDB92FFDF9 + size: 234582 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bb8682e7e70ce5059d9519e5084cbad2/ef4472fd7552490fd759075186ed2ec8.cab + - fileName: Installers\f105a73f98cfc88c7b64d8f7b39a474c.cab + sha256: DC8FD6D827CB85DB9A00F940DEFD5FF33DE82F5676076D7D8A7EDD66C52F2967 + size: 54986 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4e0d950b1b9fec1b6281a6617a0a7e71/f105a73f98cfc88c7b64d8f7b39a474c.cab + - fileName: Installers\75122a9de1700f465c29b6cc76fa6372.cab + sha256: FAB8286150248690F1C9CE9717C8CE0E83ED5095E609762A6D74286249BDD427 + size: 14246 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f1b763db6a00e387456571746f62efa2/75122a9de1700f465c29b6cc76fa6372.cab + - fileName: Installers\08e9468089f54c8455f59fd9bb48fcec.cab + sha256: EA06CF759412928F2FD6C4741CA49AD09432162DCBD48752E43CEE2ADE60C1DA + size: 65814 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/05679847412146f1c0702a3b10e88e5b/08e9468089f54c8455f59fd9bb48fcec.cab + - fileName: Installers\0b2a4987421d95d0cb37640889aa9e9b.cab + sha256: 1C6674EA886BC1B62903505A359D8214184027DBD9822A80D82990BBF2B797E4 + size: 229227 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bed11bac311f3d6c8a663e324aceb14b/0b2a4987421d95d0cb37640889aa9e9b.cab + - fileName: Installers\75b302463eed0d9b6ef9f29ebb655ef9.cab + sha256: 1595A4A5D3D3E9EDE5B3122DA5661AB53A19D2EE931EDCDF33D57BB6C91BF7DC + size: 271043 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/fbb66eb5e72b4a57d2da919a4c91e23b/75b302463eed0d9b6ef9f29ebb655ef9.cab + - fileName: Installers\f4661eda3692e166927c14c96164150a.cab + sha256: 9F163A651DBE721F2DD87A3C53A679FF323F81BAA41F71F5FD5EB88FFE4B9E76 + size: 944509 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/06e1366d4b00a55f89d581149b9b0811/f4661eda3692e166927c14c96164150a.cab + - fileName: Installers\114c321d61ae77816824fed67cd25704.cab + sha256: 689B3E15F57E11E9ADBF0F69B8631966DEBA24824A43C9564FBE84DEA72A152C + size: 369041 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4ac5ed9736c1249ef7275407538542b0/114c321d61ae77816824fed67cd25704.cab + - fileName: Installers\12613ba26e037e99a874a64c1084f880.cab + sha256: 700B4B646BB8D9E141081E93FF52826D86DFBD23E28F75AF6A3212E95CBF6739 + size: 510264 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0083d5ba0641bafa585a66da65bca5d5/12613ba26e037e99a874a64c1084f880.cab + - fileName: Installers\f524b9054edb102e11fe3850fc6796ca.cab + sha256: AA3E1A7C2D3F2FA124F896F4381EFE7C393174BBF949C745A0FF639F3342DBCC + size: 418407 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2c013e69a34d0971499242d09541f85b/f524b9054edb102e11fe3850fc6796ca.cab + - fileName: Installers\766c0ffd568bbb31bf7fb6793383e24a.cab + sha256: 1CC8AE5D28F55BA511DCDC3BEAF212AA92E6FD3A3166ECAEED604F2C78033E46 + size: 7514872 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4fe487a7134fc91aa357deefbda8479b/766c0ffd568bbb31bf7fb6793383e24a.cab + - fileName: Installers\f7b25543b47329ef932ad391c72c4ab7.cab + sha256: 064EE1E6B2B736EDEEA41158ACBE1125423FFDEAACCBF1573C7702767D03231E + size: 69445 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/86194630b4b296b4b166cc9fd55a2f45/f7b25543b47329ef932ad391c72c4ab7.cab + - fileName: Installers\f87007e985bc5453a0f01ed1a5510abe.cab + sha256: 0B9CED5D46B4348915B3A0DDDBAA7B6FB69C9B1A041417E630DB6CA2A79DACF8 + size: 16889 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5ac97520c92b3509d2f935d68fdbd1f7/f87007e985bc5453a0f01ed1a5510abe.cab + - fileName: Installers\126c039acc6f1c0a9426a128efb713e7.cab + sha256: 693797D09E384D70E6246B7CEB4B362E866E9B69F9BBF90EF4E4E22836789082 + size: 1542390 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e39dcc0182201434ceac51e95f27a673/126c039acc6f1c0a9426a128efb713e7.cab + - fileName: Installers\12a529d45b148a2d28290a8a7535b37b.cab + sha256: A33139CB94759B105A0A02A1532E48B3C9972B0416F259B25E9665DD5F176724 + size: 516626 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6e483794da184dc0ef3a3ddb6e2e4479/12a529d45b148a2d28290a8a7535b37b.cab + - fileName: Installers\f9b24c8280986c0683fbceca5326d806.cab + sha256: B250A1AC6D4BDA1BA1E6D7AC7A5DD728308BFCC802D4A6E6C02BD7F6FCEFA69E + size: 9077640 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a1024057988bed764cfb6656e0a0e913/f9b24c8280986c0683fbceca5326d806.cab + - fileName: Installers\77db8ab55a0b236db83c55ced6e8a9a3.cab + sha256: F454E82FA5E76CDD0063F23DBBE18702FBA7409F36F9FE475F96FED0F88FE8D5 + size: 18120272 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3715ec9a8fe57cafb5df089af8787576/77db8ab55a0b236db83c55ced6e8a9a3.cab + - fileName: Installers\13bf5f9b75a9d1c9f44ba5d34a14227f.cab + sha256: B9C2CE3308EF960BC9FADA7EF7E8839F822555F55CBF7B5839A925FA16E8AC2E + size: 91580 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f18d5cf877a256b648c1720719d09bcf/13bf5f9b75a9d1c9f44ba5d34a14227f.cab + - fileName: Installers\f9ff50431335056fb4fbac05b8268204.cab + sha256: ED0F2ECD1032D1FE5E245F7BA84FE549072C9F7247DFE138A7E0C322BD026D7A + size: 14668 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f8b2bd21faabc1001ef2a0276055edae/f9ff50431335056fb4fbac05b8268204.cab + - fileName: Installers\13d68b8a7b6678a368e2d13ff4027521.cab + sha256: 3B1A09CAD7CC128F59AE1AF60762C8AF5E6DB15241E2CD85616B880CD9EE5A5B + size: 229909 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7db16d62055329d38011c8e19e9fc4be/13d68b8a7b6678a368e2d13ff4027521.cab + - fileName: Installers\fe38b2fd0d440e3c6740b626f51a22fc.cab + sha256: 4820E99DBAF1E6CC93C03F8643A17A1D618692702299D92AF252F79CD5A061E5 + size: 14840 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/37179ae8a6ce48f3060ad7a64c6e49df/fe38b2fd0d440e3c6740b626f51a22fc.cab + - fileName: Installers\15bc5316e373960d82abc253bceaa25d.cab + sha256: 162224ED7F03089273619996409E8E814AD42C42144510FBCBF81142535A3F8A + size: 31917 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e10dd0eae72a4cf4dccd8b48efdc9e2a/15bc5316e373960d82abc253bceaa25d.cab + - fileName: Installers\1623efce9d1a46396798f44a7bc769e9.cab + sha256: 8748211295147245D54050D9144DDB8EA897A00DF4F2EC528A30B1CDA977194D + size: 444883 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6f2b83c0281f8e40e6029ffe3a7b9650/1623efce9d1a46396798f44a7bc769e9.cab + - fileName: Installers\16ab2ea2187acffa6435e334796c8c89.cab + sha256: 2E0A5A4675BF39A5A183274068E3307E1CEC05975CD2AE91B46C067D2CD54692 + size: 597755 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/705d35794f7d95cd1ab5f1d2b3501b16/16ab2ea2187acffa6435e334796c8c89.cab + - fileName: Installers\78fa3c824c2c48bd4a49ab5969adaaf7.cab + sha256: A06402646A3230B24C5ED16814B0B514DE00A1D3E36F92B548A6392118781FAC + size: 21985008 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d3b6a58d583b54f00a19b12ba1727a1d/78fa3c824c2c48bd4a49ab5969adaaf7.cab + - fileName: Installers\fe80f1b6d4cf60c919f4b3a0cd2f4306.cab + sha256: 7F00499B7B279714187EF275A098B088D7D8B14AFF340E258777F800AD7981C7 + size: 2150562 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/48f82b248a3def413d7205f50deaa37a/fe80f1b6d4cf60c919f4b3a0cd2f4306.cab + - fileName: Installers\79e9b68a34bc84ab465fe1b79b84a325.cab + sha256: 366817856550D778173B691CBDCF1E9C447846378B246674F74D5B814ADC1D45 + size: 792978 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6c23461b864f04993d2ee4aa16435809/79e9b68a34bc84ab465fe1b79b84a325.cab + - fileName: Installers\19248fabbb2098a7b88c4a2786066bcc.cab + sha256: FEA540BBC4F392926F6A10F2F1CFC88A5E3C72D32F56F24D5FD451757B8950E5 + size: 777812 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/439dd6ae17da841c836c2948ab8bde6e/19248fabbb2098a7b88c4a2786066bcc.cab + - fileName: Installers\fef2cfedd6135e0ed85290b83f3682c3.cab + sha256: 99FCD22638A1A801E166A0E46066E9F677A5A6E9651457F1FFCEF753975B8345 + size: 671908 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7106fc4eff01eb68281db0df7a3b1abc/fef2cfedd6135e0ed85290b83f3682c3.cab + - fileName: Installers\1a296530f0182ff1e94f088c27d05da0.cab + sha256: EF18AD37006B9F9E82C0AC305A6A9BF799DA1D1E6FE16E83952C16668413AD50 + size: 14240 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/00808ac1c561f467a14e543c90abaaef/1a296530f0182ff1e94f088c27d05da0.cab + - fileName: Installers\7afc7b670accd8e3cc94cfffd516f5cb.cab + sha256: 6B95487C259541CC5ABBFEFDC07321FEE4DB2E2C3D4349DB3F9A974E59E4E70C + size: 516608 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b2f2ec770e3a221b95fdbaf228014a55/7afc7b670accd8e3cc94cfffd516f5cb.cab + - fileName: Installers\ff8dd5a961e46b5d05906ac4b7a5ba37.cab + sha256: 2D4086EEC0BAF4CCA8FCD3BE3A5F2360F180B077173A979D5DF29BBED1AFF383 + size: 14209 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bc2f83eba11fc59aee18c3ae1e35d831/ff8dd5a961e46b5d05906ac4b7a5ba37.cab + - fileName: Installers\7b7c7382fe1ea268787e911da88eb37e.cab + sha256: 5C9AC25035F8FAC1E612818B3418DE35157800C570FE0982FB5F4E8B13C02E70 + size: 147321 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/79d9d9e8ed069ca1fd467676099e1c3d/7b7c7382fe1ea268787e911da88eb37e.cab + - fileName: Installers\Kits Configuration Installer-x86_en-us.msi + sha256: 0B7E64A4B13E15FEC81BCF077217D2C0447EE7C01F1B63E0950899EAAB371EC3 + size: 380928 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/35cc1594adab2f626294fc794fcda8e6/kits%20configuration%20installer-x86_en-us.msi + - fileName: Installers\1a822224523be67061edcc97f6c0e36a.cab + sha256: A305D9F486DA1363665DED87F070EE8B871F3317F0455D0A18059C140F814831 + size: 910220 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f01b938ca48dfa834ce263f939ba7982/1a822224523be67061edcc97f6c0e36a.cab + - fileName: Installers\7ba8bd916cfe6a56d86eaab1543d1205.cab + sha256: D05F48E54D1E5045190BA6E97F906304B11B635913320BCBC855BBDB49D68D9D + size: 3021501 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/28bfe84f629617f7cfb88cb346eb52ac/7ba8bd916cfe6a56d86eaab1543d1205.cab + - fileName: Installers\MSI Development Tools-x86_en-us.msi + sha256: FF723A0E4A3CD9423FBA5BBAB1D42DD44D1FBD4E6A4D6FF4F5B13DE3F9B63211 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f9d62a3fac5e8b7c4f03f3b8b7b0d98c/msi%20development%20tools-x86_en-us.msi + - fileName: Installers\7cb1ba9318f4b586c6a3bdd541e7f3ad.cab + sha256: 816F42ED985807AF437F2DF3691A3EF26A721A9BBD3FD2CFBB38E2B909FD32D0 + size: 16511 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/261bc9ca5e1d5f396ed1a5404ba85003/7cb1ba9318f4b586c6a3bdd541e7f3ad.cab + - fileName: Installers\MsiVal2-x86_en-us.msi + sha256: F20C8DF9198605EDD20F54885371DB1FD31318FCAE99820774BCF76CB5399087 + size: 589824 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d861f77f5ee0c33f0b2ca212abd8d655/msival2-x86_en-us.msi + - fileName: Installers\8016f7584c8fbeff0b032c65f4173e78.cab + sha256: 33DDA4E528DEA23BD4021D5FFB6877437BE195C37C55A3A21E754835813FF425 + size: 36830 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d3deb75c7a6a8fda452ef65d348598f1/8016f7584c8fbeff0b032c65f4173e78.cab + - fileName: Installers\Orca-x86_en-us.msi + sha256: 79DDC0131E0859DFD0C1C41B51C922B0AA20DF011EDB1FF4C9B4566F0474A726 + size: 589824 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c3e2746687af6cde9fc76402cd1cd72e/orca-x86_en-us.msi + - fileName: Installers\SDK ARM Additions-x86_en-us.msi + sha256: D5A6094F0C075ADC09AC253FFAEB6F1AD9F159377E4AB27F8DE157A1137A3B1C + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f257e3e76f41a7c41b51ad5dbc2212c4/sdk%20arm%20additions-x86_en-us.msi + - fileName: Installers\802a07e87c65fbd441584c31e8bb0ea7.cab + sha256: CD3678A81D1FB2F34832921A1569218E422B4B51B8A0C54504DC632F98943794 + size: 56641 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d46265bce37fbebe84cb4a4d9ec1066c/802a07e87c65fbd441584c31e8bb0ea7.cab + - fileName: Installers\1de82860db02f762c5f65a73daa31f3e.cab + sha256: BE417E2E74F396CDB5E1A2398C20CB68B7627CB786893F1C7C07D447124DFF20 + size: 14393023 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2632cb254a13fce18a1fd45684d0a698/1de82860db02f762c5f65a73daa31f3e.cab + - fileName: Installers\1f32e9acf0bb1e6a5f485cd8670cd8e1.cab + sha256: 3E02992C919B033C9D07E30CB2E088FC12B65CC5C802E3F32BB3C872A7286555 + size: 17329 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/9dce629e3d0faf4a794a3bb9c60551ee/1f32e9acf0bb1e6a5f485cd8670cd8e1.cab + - fileName: Installers\SDK ARM Redistributables-x86_en-us.msi + sha256: 198DD27B38E6CD67558CC2DE83679360BB6736D9E6BBDD2168DCFC777477BC3E + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/536460fb7f348496250c2525cd5f5d5f/sdk%20arm%20redistributables-x86_en-us.msi + - fileName: Installers\SDK Debuggers-x86_en-us.msi + sha256: 263EA5A2E64E3DB5B5C60F0DDDD4EB9C708B60137C7980FF13E7D590F5DA7141 + size: 606208 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e8e98df3eab5cb652127edce12f2a0af/sdk%20debuggers-x86_en-us.msi + - fileName: Installers\Universal CRT Extension SDK-x86_en-us.msi + sha256: 137D28744AC38BF3C45948AE5595E020855DCE7F4D759F33F67DD7953CA65A47 + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/92e817d3a640b7a176653fbc7d014677/universal%20crt%20extension%20sdk-x86_en-us.msi + - fileName: Installers\220daf459e79c5d26366654b1b482e87.cab + sha256: 72B9C0883E43D0D9DB4614FA8ED1779FEDC679BBE22D049C6A42BC3D3FB1C376 + size: 93902 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c1631037db5a95d5931e8cb94b6593dc/220daf459e79c5d26366654b1b482e87.cab + - fileName: Installers\80dcdb79b8a5960a384abe5a217a7e3a.cab + sha256: C5D559E004E76D2242BCA77424EE2531135A97DA2C337E0455B0999E34CEA9F7 + size: 22432314 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4133032c4c6bea95499d817486ab10e9/80dcdb79b8a5960a384abe5a217a7e3a.cab + - fileName: Installers\Universal CRT Headers Libraries and Sources-x86_en-us.msi + sha256: E98CA9B34E1BA9D4CD5E0A6BE5758B81084B43601D6B193284A18BEF752DFC59 + size: 512000 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ccb17f6b911d6b0e1af01d126a7d5852/universal%20crt%20headers%20libraries%20and%20sources-x86_en-us.msi + - fileName: Installers\Universal CRT Redistributable-x86_en-us.msi + sha256: 3E258B6E4F45E652A8E44DE9E127D9F063E2C44068AFEFF9A136B5E4F0528359 + size: 413696 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d7a70fc699b85b8ce89cd9ef8f0dd017/universal%20crt%20redistributable-x86_en-us.msi + - fileName: Installers\8125ee239710f33ea485965f76fae646.cab + sha256: 1D9E9E004674A902BE9C35DC1E0CD0935CD8FE7ACE14383F8AD2CCF464A0B7A4 + size: 5387577 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d49ec52fb68834080bd287d38eaf9ed6/8125ee239710f33ea485965f76fae646.cab + - fileName: Installers\Universal CRT Tools x64-x64_en-us.msi + sha256: 0636FE7C8CBDB1E349CDBFF6CF5D9EC3C3D0432A998E1C21C962BB18BE286843 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/94b4b6b8c034a097de7a0459ca950627/universal%20crt%20tools%20x64-x64_en-us.msi + - fileName: Installers\Universal CRT Tools x86-x86_en-us.msi + sha256: 257B247AF9C6CB11FE3596F9F0108A3D2417C888E4B789E3CD30C95548961C07 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/fc9c3fa7288dcb7f807c0264e95befe8/universal%20crt%20tools%20x86-x86_en-us.msi + - fileName: Installers\262fa3187c00a1f695e0c3eeb7ecf423.cab + sha256: 953784617653AF255DCDE06AE33DBC344E51A1A1A75F6B1DA187D3EA590E7E3D + size: 1586008 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/68c9450233abf1522d261e6e6a83c109/262fa3187c00a1f695e0c3eeb7ecf423.cab + - fileName: Installers\818d2d3634f0efb6e64d7e7c8ca5f98b.cab + sha256: F98EDBBCF7C903E50380D7D199D1305FCE464EBC7D371EFB0CC750C91E3FD5A2 + size: 110562 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ee506e525279c1617ccd471871be964a/818d2d3634f0efb6e64d7e7c8ca5f98b.cab + - fileName: Installers\838060235bcd28bf40ef7532c50ee032.cab + sha256: 80270239F2D155889771031C53119F43F405766DA483597C4FA59E0C0037A1C0 + size: 14875 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/575aaa35f1be950536eafc666fe45d6c/838060235bcd28bf40ef7532c50ee032.cab + - fileName: Installers\89d9bbd87f7a5560bafa520a4ebfdf17.cab + sha256: 7C139334AEACE44A13FB17CE244E548895EC22AF3DC02121866E3E2F81313714 + size: 87784 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6b5091e388381ad53dc11f7efc4f4ce7/89d9bbd87f7a5560bafa520a4ebfdf17.cab + - fileName: Installers\Universal General MIDI DLS Extension SDK-x86_en-us.msi + sha256: 351E74A848EA27BB311CE0F76D62ED959A4BE8D5AACE831A44F5BA0890BF3886 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/39f4d9afe01cd3163917bb996118b1e0/universal%20general%20midi%20dls%20extension%20sdk-x86_en-us.msi + - fileName: Installers\8c44e508e7582f9362c66a2e47a19b5e.cab + sha256: B3D91C3D46147D9FA7D1E5AB86550880F473893B83B88BD0BAFFA9E1E6A712F1 + size: 34951 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/19efa8f50f9504c47249b3afec902c87/8c44e508e7582f9362c66a2e47a19b5e.cab + - fileName: Installers\WinAppDeploy-x86_en-us.msi + sha256: 1DD1A3EDB541FB0B3DB6C4D2DB23FCDD80D352767B9DCD8F6E421BCA87A39663 + size: 839680 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7cecea1a787cceda9e61e5225933c126/winappdeploy-x86_en-us.msi + - fileName: Installers\2630bae9681db6a9f6722366f47d055c.cab + sha256: 3CB7750D58C4A0C0392A6D6840C3B63DEE88C788B385ADBBBA052D8A480E883B + size: 6426286 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/293779186d2722d6cd7985c392f2cf98/2630bae9681db6a9f6722366f47d055c.cab + - fileName: Installers\8da73ae89e24f0b5cdf1787799c2a65f.cab + sha256: F68B889467038C25750954702AE4F80D95734728171A69577580F4B5A5BBE865 + size: 1484666 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f6557262571cebd3b003309fe4c7b1bd/8da73ae89e24f0b5cdf1787799c2a65f.cab + - fileName: Installers\263104e5ce3a72f68151a93d88a3f22f.cab + sha256: 653299C312ACF530D94B2A9B0F501BA9FE09DDA45D5E29A7280AC0FCDF6BFA5E + size: 14881 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/8c7001618d330b7dfcc714753a0542aa/263104e5ce3a72f68151a93d88a3f22f.cab + - fileName: Installers\8daf1f236e631041cdaa802ddb9ccc3d.cab + sha256: 5C392A1D327F48331FFC2C8ABAFB0E93DC99FA94E1C5575CF553E274E34DCAAE + size: 81826 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/414b82dada7da7305fd822f96964af6b/8daf1f236e631041cdaa802ddb9ccc3d.cab + - fileName: Installers\2868a02217691d527e42fe0520627bfa.cab + sha256: 95A6E0AD13CB7984ECB8FAEB2CABF65D8E3B2F7DF1BDE22A58DC277AA8DAAF14 + size: 510262 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/055b700a57a984df74f8e15906d23bcf/2868a02217691d527e42fe0520627bfa.cab + - fileName: Installers\8e4755178e6b5bcba8d3538c3630b7a5.cab + sha256: 0F31D0212D68DA9485755DAEBAF15665692D26C4596E7EE38C9297E65EBB4F9D + size: 1107948 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/597eba304214e17c7078629174e9574e/8e4755178e6b5bcba8d3538c3630b7a5.cab + - fileName: Installers\Windows App Certification Kit SupportedApiList ARM-arm_en-us.msi + sha256: 5D7DB22BCE116D593820B925D0E14B80572BDC7D59B5AC1F80D3185EEDD9E926 + size: 368640 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3a97a2458efd4436fcda1cfde13992a3/windows%20app%20certification%20kit%20supportedapilist%20arm-arm_en-us.msi + - fileName: Installers\2c1331a0f4ecc46dfa39f43a575305e0.cab + sha256: B4EAB16C2ADED6E01F6C9BAB216376BF39B77878C117450B54A99CABF2C5BA26 + size: 1082994 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/da25c7d7ad07745658ac2670e5603ac1/2c1331a0f4ecc46dfa39f43a575305e0.cab + - fileName: Installers\Windows App Certification Kit SupportedApiList x86-x86_en-us.msi + sha256: 4D17D3B6130708FB8E87D93727763B49F180BB03DEAD29429B009A20087F7593 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/35467f40e22ef40cb7cd58886935ffb7/windows%20app%20certification%20kit%20supportedapilist%20x86-x86_en-us.msi + - fileName: Installers\2c1817d3f3f33cd01376c5ec441cc636.cab + sha256: 22C9A3C719EA8045AB29E8FB3381BF29B055CACD4D366E66B6DA8F17CD2E7567 + size: 24711 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/8b391c36fe3ac92fd8bed4846cc4120c/2c1817d3f3f33cd01376c5ec441cc636.cab + - fileName: Installers\8eb01de6160e8924be8582861808a9b5.cab + sha256: 78996ABD53C993425BD04159087507584F6E0A9946031774B96D44C94E612297 + size: 276698 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3096f80a9c08295b8921f291aaf4d538/8eb01de6160e8924be8582861808a9b5.cab + - fileName: Installers\2cd67f5657d2cee1a106c4fdab506e58.cab + sha256: D6A419E66C3B23130144B7827BF73B7AD605400C5DBEBAA9AE2F40A5655BF189 + size: 229076 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/315183e435eea45dbe8b424f02f7975a/2cd67f5657d2cee1a106c4fdab506e58.cab + - fileName: Installers\Windows App Certification Kit x64-x86_en-us.msi + sha256: 8C12B817F9CE1E4EB11FF16955EE6AE8A3A3E2621F959864E3A4F7F178B47871 + size: 520192 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/655bdae0676b3598b7caa1d3cac94abf/windows%20app%20certification%20kit%20x64-x86_en-us.msi + - fileName: Installers\8eec88833ea319aaa1061d6528c77b93.cab + sha256: 399971DB195FA0F21D4ABDEB65E2F9887E097D722C40C8F4D798876B0D4CC5D6 + size: 174369 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/23b048d03063e4b3a806bb43f7c8ea6d/8eec88833ea319aaa1061d6528c77b93.cab + - fileName: Installers\2dd914bb5abd9365f932d15eede09c52.cab + sha256: 7DE7D6F02BEC8FCBCFAF89B651A7A957414C9F4E4D20CCEB283DA20B246F0E61 + size: 1335575 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ee3fbabef6c166580f5a0a8843c671e2/2dd914bb5abd9365f932d15eede09c52.cab + - fileName: Installers\Windows App Certification Kit x86-x86_en-us.msi + sha256: 4D482F0836EAD4D0327DC2E15ABC8A60B4A711E2B13E38D409BD98F7EE704B0F + size: 520192 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0b816dc2eaba112d780f43898c9f9dcb/windows%20app%20certification%20kit%20x86-x86_en-us.msi + - fileName: Installers\8f636cea16f07b14f423402afc69cf83.cab + sha256: 3554F41F8DDD33DBB29F28E6227DC56413AD56BF6274A738BC6E90F21C2B72A4 + size: 2307898 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e652adeb453d0e20e781987125c20bdd/8f636cea16f07b14f423402afc69cf83.cab + - fileName: Installers\2e876dd22fa5e6785f137e3422dd50ec.cab + sha256: B58C3774E3F88EC9313EE6AE67A46D27980132B00290F34C334595C577B4838A + size: 8876000 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d31f43c02fc9a1291bfa4a76b4e965e0/2e876dd22fa5e6785f137e3422dd50ec.cab + - fileName: Installers\Windows Desktop Extension SDK-x86_en-us.msi + sha256: 5F06EBA847DFBDAF846CBBFB488B0F54642826106099DFC029AC9247FB2DF707 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1c1ca4b6efa1923289eb8a75e32e08ff/windows%20desktop%20extension%20sdk-x86_en-us.msi + - fileName: Installers\8fe3c1ca244ece932599eb0b61855d8f.cab + sha256: 924F734ADE53C7031F7A704B610FDC3F3ADF58B4C1C2225AA3A549E978445FA2 + size: 92065 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c4be344daed7c9d91efa1a2468c4a097/8fe3c1ca244ece932599eb0b61855d8f.cab + - fileName: Installers\2f7b48ba67113253720675dbbbe9df33.cab + sha256: 8BE6643CA3680506B4428BC07368F8746ABCFC52121F9D08B05B91D7A12AB79E + size: 641097 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4317e98f3f8f004e96d1956bb08757d0/2f7b48ba67113253720675dbbbe9df33.cab + - fileName: Installers\90e1202895672ce81992e71be30528cc.cab + sha256: 1B193046B52666C5ADE88E97274D5FC8DF8D8608C3893F28BADD2D08AE8950C8 + size: 345478 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c82de0c6c730653bd2c0941cb1dfb4f5/90e1202895672ce81992e71be30528cc.cab + - fileName: Installers\306e26e920fd32cb02bf538b4e799a0d.cab + sha256: E4C9CB604F3830C944F09AA2DC8D4E6931AB4970CAEE7329F2CE7D7FB215064F + size: 162521 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/db1d946546dc56edee232b1d1b05e3d4/306e26e920fd32cb02bf538b4e799a0d.cab + - fileName: Installers\Windows IoT Extension SDK-x86_en-us.msi + sha256: 58A0809F08C85983CB78BCEA0990BE5F9F3FF3766D57054097B50236AE53A165 + size: 380928 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/fbf71fea4697ef77cbf1f419c621d3d3/windows%20iot%20extension%20sdk-x86_en-us.msi + - fileName: Installers\31ec2a68a04d58dc4a3d639fddc68493.cab + sha256: DD01F2387007F15862B01D606A0002D03088CDB9C294D860D1516BCDCF2ADCB2 + size: 230514 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3c03fd6e18fa599ad49e2bd4777748a6/31ec2a68a04d58dc4a3d639fddc68493.cab + - fileName: Installers\9126f6ff98d955951fe9323f4444c119.cab + sha256: 2E126DD151BEAF7652C4261771D108FCCB772EAEA582F5C922BBA14FA43BE212 + size: 496938 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/dc0e84a68b85ab99124807f231d9e3a6/9126f6ff98d955951fe9323f4444c119.cab + - fileName: Installers\34ee98a7c9420178c55f176f75c3fe10.cab + sha256: 7789CD603B841F7B7618AAFCF0CF36601042BECC4081D905C0604AC40297A76A + size: 2765508 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/51053c5d0e1c12fd7a29a9104ad20ba8/34ee98a7c9420178c55f176f75c3fe10.cab + - fileName: Installers\34ef8c7e30b6852e56ba7a56fb7b3faa.cab + sha256: 4B379C6E0C452BDD4655711D3A6FFE1F067BD8CED5DC5CBD800ED1C9AACA133A + size: 24437 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5211e82b63a95140eb54d904bbfd2403/34ef8c7e30b6852e56ba7a56fb7b3faa.cab + - fileName: Installers\921968b1c32e680f338247ac68950f5a.cab + sha256: 9C3BD58BCDF2AABAFDB8E9A7341A48E784A363E9239FFC196C97BC323C54240E + size: 36136 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/18df94036eb819fbda523b0e139cf879/921968b1c32e680f338247ac68950f5a.cab + - fileName: Installers\353be8f91891a6a5761b9ac157fa2ff1.cab + sha256: 762B950193A6752661380A18A1D8E1DA7AC364B276B8CB47116DA813C58AE569 + size: 63604 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2d6d1dfef729d80914c3e3f3309284fe/353be8f91891a6a5761b9ac157fa2ff1.cab + - fileName: Installers\Windows Mobile Extension SDK-x86_en-us.msi + sha256: ECF30DBABFDDA883F7C93F0110F05577093E5A8157CB65FE36E27320991B7756 + size: 397312 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b879a057b4e199b6ebd7edb1c5e9a535/windows%20mobile%20extension%20sdk-x86_en-us.msi + - fileName: Installers\931721e121ef91707ddcb6cac354d95c.cab + sha256: F4C91E22364207A0C20AC021E41B9D68BCBE09B4D8B572C2F76706BF99023C11 + size: 14368 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1d71b3b98a6f06190126ba551fc34e84/931721e121ef91707ddcb6cac354d95c.cab + - fileName: Installers\Windows SDK ARM Desktop Tools-x86_en-us.msi + sha256: F818E6E18F4F580832E90B3BA98010CA1A1EA1C630D556A5B93ABAAA1B951E92 + size: 393216 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/15498adc9319041e5fa6bf56397624c7/windows%20sdk%20arm%20desktop%20tools-x86_en-us.msi + - fileName: Installers\93a74a1d34a22ae9d2e1ccc5208ad21a.cab + sha256: 2D0FC977097A507B3D1AB0C2A90E45DE595877FC881DB67AB562DBC7B0ACFFE2 + size: 471243 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0291854c1bbebaea5e404838bab10f41/93a74a1d34a22ae9d2e1ccc5208ad21a.cab + - fileName: Installers\Windows SDK Desktop Headers arm-x86_en-us.msi + sha256: 2C405CC2A4FE6FE939F7AB60B0822160D59F3528F012552812122A8D248790FA + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ebc8204c7ac4d100abbb015b24be1133/windows%20sdk%20desktop%20headers%20arm-x86_en-us.msi + - fileName: Installers\3960f55df7c8073f3997269e5e390abc.cab + sha256: 181185A7749D45E225EEE4BBEA9865302B17D97FEEA2A7C4C24367D81F902990 + size: 16501 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1d7e837b02a41e674bcc325cc3136917/3960f55df7c8073f3997269e5e390abc.cab + - fileName: Installers\Windows SDK Desktop Headers arm64-x86_en-us.msi + sha256: 5993EFB4EB9B01D02101B84DC3FBB73542666F3571338A9D128FBF46AF418D66 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6f5d15ebfab811ea88816dd0c7dfe5e2/windows%20sdk%20desktop%20headers%20arm64-x86_en-us.msi + - fileName: Installers\94521fd1a9c57258998d60ce60dc43c3.cab + sha256: 32D64326D577FB4E58D2945974695B992FD5DC1F5707988E62C45CDE9F4E0CAE + size: 1882959 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/512ee49b953176309098f8063c7c6792/94521fd1a9c57258998d60ce60dc43c3.cab + - fileName: Installers\3988e4dfdc3f1d180c47a61a0ca76215.cab + sha256: 320DAE2A46EDB125CF5EDBE6BFCB81981AC54DFDB37259B03171BFD0841625E2 + size: 1182851 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0a7e38789e913d817dc39fd6e07ffe4a/3988e4dfdc3f1d180c47a61a0ca76215.cab + - fileName: Installers\948a611cd2aca64b1e5113ffb7b95d5f.cab + sha256: 86C17297EC41F9511D0A48116D530D144185813B9BAD66F74CF1633C2DBCDBCD + size: 608766 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ce0a92aa1681eb87ca9ec2a6ea679232/948a611cd2aca64b1e5113ffb7b95d5f.cab + - fileName: Installers\Windows SDK Desktop Headers x64-x86_en-us.msi + sha256: F0CD21FA4493F8DAD31112E1B6889B2FA1C310F99DE2FEEB03D318901CD9C6E2 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ffa4db07484515cefaaaab9b0fa6209f/windows%20sdk%20desktop%20headers%20x64-x86_en-us.msi + - fileName: Installers\9494c0c1f781298600a3c07e837acd0f.cab + sha256: FF33937C5F4B09F4190D01F2A71DEC23589EE332E257BCDFEAD48DAAF9C21BF0 + size: 26554 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/24b4e18911b156848e6ab9f5221e00af/9494c0c1f781298600a3c07e837acd0f.cab + - fileName: Installers\Windows SDK Desktop Headers x86-x86_en-us.msi + sha256: 35479649A17D6EA293DB7504748AE20C3D9DCC4088CBF9B83494EEE775582EF4 + size: 761856 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f36af036fb1640b8c6e371a36d30cb90/windows%20sdk%20desktop%20headers%20x86-x86_en-us.msi + - fileName: Installers\96076045170fe5db6d5dcf14b6f6688e.cab + sha256: 8D28EBE1805F3394DF2FB1D195B66E04517AED656D40D8DCB65BBBA4BEC3C5F8 + size: 642762 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bc13d9d8ebff508a5c1657c279ceb73e/96076045170fe5db6d5dcf14b6f6688e.cab + - fileName: Installers\Windows SDK Desktop Libs arm-x86_en-us.msi + sha256: B5938949860A41B7094F9A0EBC9BF1E0B6FF513690461C0EA5452D995CC0E046 + size: 458752 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4bb48b0082b605ef47f451feeb02542d/windows%20sdk%20desktop%20libs%20arm-x86_en-us.msi + - fileName: Installers\3a53dffe0b4548753bc34825894f19bf.cab + sha256: F79B8E02A7CC7B572E64ABE40AE6091762CA485F404F0C7C74F7B9CE018C9CEF + size: 385398 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b856aeb7cf7ae3ddd0ca7d4b68d571a7/3a53dffe0b4548753bc34825894f19bf.cab + - fileName: Installers\96e8f767221532c6446fd1b8dad53b60.cab + sha256: DD38DBFCE78987FD6C74ED5167DFF5E12EDFD388D28565BAC59DBD6F7E062BFA + size: 1181790 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f2bd303353e33bba42ee963f8948cc34/96e8f767221532c6446fd1b8dad53b60.cab + - fileName: Installers\Windows SDK Desktop Libs arm64-x86_en-us.msi + sha256: D2EAF454B90CEFA38CFF62CC390AB6FC3E160E3A0CF09C08B92F9C9D7D19E72C + size: 462848 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f59abec1ce9da16fed4d7f74a930dc3e/windows%20sdk%20desktop%20libs%20arm64-x86_en-us.msi + - fileName: Installers\3bcfd9f5ea63604c64ec7e0f5455a840.cab + sha256: 5FA127FD90BBF5BE84C1D26905ED3A686B3833AB9AA55E27E272B5DE95A60FDD + size: 385682 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/70397c6c6242a11a8572ed03ce314e79/3bcfd9f5ea63604c64ec7e0f5455a840.cab + - fileName: Installers\9a7145bc3b132e5da6d44c0ab4a1af70.cab + sha256: B022AFCE20298100C907F7537C891F73CDC37FE7A375B063DC07BA7F0A67345D + size: 3170146 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/06918eba339c10ab9dab63227dea38e2/9a7145bc3b132e5da6d44c0ab4a1af70.cab + - fileName: Installers\9ba47e440ec2fbe9a3d32a53bf0f68dc.cab + sha256: 36407F24B7965CD2C71D47C5D281DF922FF59E675D18C262954B0315B444E49B + size: 496342 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/67991bea91f53fd0e2d87035b8c6f1bd/9ba47e440ec2fbe9a3d32a53bf0f68dc.cab + - fileName: Installers\3ca392fde3898c3be052ddcddd14bb5f.cab + sha256: 8FF6023DF336B7C740FBEA0263962306B01D2ACAA8678C21463D52248FFFF477 + size: 7512549 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0f07b90f1b268163069d9e006b6d3ac9/3ca392fde3898c3be052ddcddd14bb5f.cab + - fileName: Installers\9bcb3fab78e80d68be28892ea7ad46c3.cab + sha256: 6B1F2B350FFAA1ADA7C4BD0DB512DB02B1E2B9047137B7D18A9D3E8B192984CC + size: 156033 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/41c6e9c39ca419df7763720bceda5b8d/9bcb3fab78e80d68be28892ea7ad46c3.cab + - fileName: Installers\3cf96a08c3b29e9dcf5946d28affb747.cab + sha256: 0E90DC110EB8453AD14277133F543B5A77471FB91AB1F235B568758449193910 + size: 98910 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7aa14ec4f29416f3c31ad9193a91b507/3cf96a08c3b29e9dcf5946d28affb747.cab + - fileName: Installers\9bfca1e044c38e04afe2363d3db899c8.cab + sha256: 004B02F6B91552DA95877EBA540DE6A0D635BC36369063495C9609C30D459D35 + size: 930338 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e6816c9713a2025042ecda7ead6be30e/9bfca1e044c38e04afe2363d3db899c8.cab + - fileName: Installers\9f17b927fd84ebb5ee0df0774c0c568f.cab + sha256: 49A415F159A65D1EA332EF01572F2F3BF571A0AEF6C90D1F82E193D9A04AB2B6 + size: 913632 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0b8bcbbbe3f29a80519e74cabf5448af/9f17b927fd84ebb5ee0df0774c0c568f.cab + - fileName: Installers\Windows SDK Desktop Libs x64-x86_en-us.msi + sha256: 07C00A650BC154B5F57F9D19254A8840A833BA45AAA907E220B478F3FD830D1F + size: 462848 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/59c077f7df8fb8e55a0f6dfcfa6197a7/windows%20sdk%20desktop%20libs%20x64-x86_en-us.msi + - fileName: Installers\9fff62eb37dba61a297941c75287dfec.cab + sha256: A534158F87B67336861DF7795A062292580751F998E7FAA2C55A855208A340D9 + size: 31504 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/103adf4a13f768ebaf9bb9b406209a0d/9fff62eb37dba61a297941c75287dfec.cab + - fileName: Installers\a17683486ace64c3f9a1cacb81ee0260.cab + sha256: 7920F68D3BE1ED3B670D95A372F2BD5692DDA209A4670DCD56EC19DC3E0C4B0A + size: 98365 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/99405d6117676a351bf0536b615135f3/a17683486ace64c3f9a1cacb81ee0260.cab + - fileName: Installers\3e2f7be479e3679d700ce0782e4cc318.cab + sha256: 5248F5E7796E074B28484EACA405A952CF98563B5499F58FABDEF0E1CFA8F332 + size: 18734664 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7efa24af757c548b0ce5e3a652c94498/3e2f7be479e3679d700ce0782e4cc318.cab + - fileName: Installers\Windows SDK Desktop Libs x86-x86_en-us.msi + sha256: 5E4398CF4BE05BD2137999A24A63C4B001FA4181BCE01B1D2F50FDF17BAC16B6 + size: 462848 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d9a2327391c70b80df147897bdaf820b/windows%20sdk%20desktop%20libs%20x86-x86_en-us.msi + - fileName: Installers\4035a83dc8e73244d15d1196d55059c3.cab + sha256: B9534FEB0588E9321F219591BB47436E639AB7FFFCA8CC05189D759054876852 + size: 15101 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c5f76786c4bc13cb703276ed12e70ae7/4035a83dc8e73244d15d1196d55059c3.cab + - fileName: Installers\Windows SDK Desktop Tools arm64-x86_en-us.msi + sha256: 7A43F77BC11AA0B1C5AE4859160C6823A46351C8FE81B8F8FAC05C6AFC689EE2 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6678e1f3cc41d945038b5523333c90eb/windows%20sdk%20desktop%20tools%20arm64-x86_en-us.msi + - fileName: Installers\4040fdfbcd753e650c0e3a5bce3ed7a2.cab + sha256: E738B1238F9436E49C1BB095FE1FC7FCDD3D0F247852C0A775A342BE68B33641 + size: 24142 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/40054e2e934fb88d13fdb7e812f3dc82/4040fdfbcd753e650c0e3a5bce3ed7a2.cab + - fileName: Installers\Windows SDK Desktop Tools x64-x86_en-us.msi + sha256: B6B8B7D145CBA0D0FB3704A313293A50EA1F7F98E298F0B8BB3DC1F93B78145E + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a8fa1e68b6e77fc12a174b9072f0732f/windows%20sdk%20desktop%20tools%20x64-x86_en-us.msi + - fileName: Installers\40d92f424eff54b03db4c51669f9a8d6.cab + sha256: B0D987E83F86599C0FD87EE2355A4FB9162ADC070B6838F2F927937C83719B46 + size: 178997 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5c00702d112e17ab5dbd1f4ddc270f75/40d92f424eff54b03db4c51669f9a8d6.cab + - fileName: Installers\Windows SDK Desktop Tools x86-x86_en-us.msi + sha256: DD20FEA1CCC9202309386C4E5FACB8D73A8C1142DC9991B8900414B1E0020446 + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/375c4660bd5e889bfdf191e0411f6af1/windows%20sdk%20desktop%20tools%20x86-x86_en-us.msi + - fileName: Installers\a1e2a83aa8a71c48c742eeaff6e71928.cab + sha256: 4F1B720286118CB2BFAB2119C29873F2BA96691D213529FFE53BFD3904813177 + size: 22849294 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6ec381fa716a2ed419c2141cc09606ee/a1e2a83aa8a71c48c742eeaff6e71928.cab + - fileName: Installers\412c1caad96b8fe5e8f7f6735585f297.cab + sha256: 45596E91709DC5DE88534CC93D91D9257ACBFC6903B5E307458438A4B8AB445D + size: 198604 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bf09b0e55684149fe2de759fd5cbe0ca/412c1caad96b8fe5e8f7f6735585f297.cab + - fileName: Installers\Windows SDK DirectX ARM Remote-arm_en-us.msi + sha256: 2B6B18B200797A23B9423570ADF5D5FAD85AC2E9D67B69F22961C3A4A9BD8DB2 + size: 368640 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ca0c86becd2d9befaa32f6ea6a95d6ca/windows%20sdk%20directx%20arm%20remote-arm_en-us.msi + - fileName: Installers\a330840cf08ad4d210703c9acd1bf2b8.cab + sha256: B95F967F30B53E0776B0F589795A3956A53CE421A246AD07A3AEFD0A7D9685BC + size: 1043471 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e9dc7e9a0548039025b91fcea1da35a1/a330840cf08ad4d210703c9acd1bf2b8.cab + - fileName: Installers\Windows SDK DirectX x64 Remote-x64_en-us.msi + sha256: 96CA9154DEACED1CF6A166CF12D3B6C1635F5080A549613E927D9D2A0AA734BD + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/20f567748a05f298e5871bbf51451b44/windows%20sdk%20directx%20x64%20remote-x64_en-us.msi + - fileName: Installers\437e52bd67ebe977a8957439db5ecf75.cab + sha256: 1FDFBF85FE94209B03539AE29B096B256C03A84EBE33E0BAD3EA7E57036EEB19 + size: 2795360 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/80ed4e5d15993a771441e179b8fc028f/437e52bd67ebe977a8957439db5ecf75.cab + - fileName: Installers\Windows SDK DirectX x86 Remote-x86_en-us.msi + sha256: AF62759E7471065693E329057C49018CD35B16A207A484A66C8AB4CEB7AC7553 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1f3774d3fc6378aedaee1fb0eda3ecf7/windows%20sdk%20directx%20x86%20remote-x86_en-us.msi + - fileName: Installers\a35cd6c9233b6ba3da66eecaa9190436.cab + sha256: 8792C5278CD13F9A8FDCA629CD82FB5084678B2392C3F62EC5803431189E06A7 + size: 1880411 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d68bac74a3d8377fea5096abd8f4088e/a35cd6c9233b6ba3da66eecaa9190436.cab + - fileName: Installers\a68c0988d16ee124783efd98074dcbf9.cab + sha256: A504DA922996192CA0C985DF367014F9166C6A32F5E8B0D53CF7A3E44F10B421 + size: 14884 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ef89c4e646f9d12fd66f3d5bf20192ad/a68c0988d16ee124783efd98074dcbf9.cab + - fileName: Installers\Windows SDK EULA-x86_en-us.msi + sha256: 768A7357FB7B2963FA6ACA8492509B3601D850FB0005161594B27CDF47C35DAB + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b2f8558e9e81aed70c4930dcf9032bce/windows%20sdk%20eula-x86_en-us.msi + - fileName: Installers\43cc1b2daf931a3f0ea4ad696c2327fb.cab + sha256: FE380CDACCFB5E99D7B1EE015C7DF5DB0ABE1DCAF9881F0B2B4E98DB3AA64AE5 + size: 18109 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ef9a75bc8b11613bb635f9e0eea16d54/43cc1b2daf931a3f0ea4ad696c2327fb.cab + - fileName: Installers\a74408a87a51829b89e5282e73974d74.cab + sha256: FD09B8EA1949C1588D6D9D8560DD580E57C22A6D8FAB17127C411263863353A0 + size: 259462 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/40a2f66ee5c768b0c599b8b0a7c637c1/a74408a87a51829b89e5282e73974d74.cab + - fileName: Installers\43d52fdb99b86048e15fbd34f5b99cb5.cab + sha256: 2BE28C299DDB696255AACE756F9A75A70422063F559B2D645899068B23BFCE5B + size: 247868 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a680b9c0dcd08c6647c4ac2b730254fa/43d52fdb99b86048e15fbd34f5b99cb5.cab + - fileName: Installers\Windows SDK Facade Windows WinMD Versioned-x86_en-us.msi + sha256: A906F0F3A621683AC0160555B399864E1DA5492AAE01BCD81501FC97BB1CAAC8 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4775c09723e3a5118e4a2894366e8841/windows%20sdk%20facade%20windows%20winmd%20versioned-x86_en-us.msi + - fileName: Installers\441901505fcd0b2e997ea7d954f04171.cab + sha256: C2CB985F79E8F7608EF1C6A910971991AA72F751534B008AB1A6B5EBCE1BFFB2 + size: 16924 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6736774756e2f108369c2f70b0c46b9d/441901505fcd0b2e997ea7d954f04171.cab + - fileName: Installers\44472e2321abba45e828de25827264a3.cab + sha256: ECAFA81E7E2950175141463BBB43EAF98BC215BFEDCAD42F677DE1B08663A52E + size: 18876 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a0d61bcf2501c9e681e6c5501e30dfa4/44472e2321abba45e828de25827264a3.cab + - fileName: Installers\a76e4219ecb0f1c0006a6fe080c54ad9.cab + sha256: 00754473F58DD91FD1D2F156A7588B5344CB6CF1947DD0237B4FE9613B71224B + size: 3459336 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/289e51672dca8c8d0c8e7cc5593d4c55/a76e4219ecb0f1c0006a6fe080c54ad9.cab + - fileName: Installers\44ae31259cff28faf5e7015a9b8be5b2.cab + sha256: D84BCCE28BFCE08EB011ACAB8037BA6B225845858FD2ECEFE6B7604B819AC810 + size: 271558 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/68c31c5ff66a60887286b9605fb08c27/44ae31259cff28faf5e7015a9b8be5b2.cab + - fileName: Installers\45821d1fcb842bff411f5f2f8c1d4106.cab + sha256: CE4AF10A93557932DE2EDC8BF17D10DAAA7F6235206F091E9613E71E5FF51898 + size: 14856 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4d1a3472879e4969d2ef5903a0ddfab3/45821d1fcb842bff411f5f2f8c1d4106.cab + - fileName: Installers\aa9c58552bdb82dae4ed48ece081cfe3.cab + sha256: 96BC7A05E65B4F305B08E1466C39DCAF0267257E5C244810A738B6E728693C5D + size: 1555607 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/28126bf6cb5e8e9094c7cec4ccd1a7af/aa9c58552bdb82dae4ed48ece081cfe3.cab + - fileName: Installers\463ad1b0783ebda908fd6c16a4abfe93.cab + sha256: A3C0C360B2C63CD1F83D17D4E1ED2ED3CE9504AA8BDBACE68037E3A745C31447 + size: 229991 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/cc5b5405b11f828a045777690fa72feb/463ad1b0783ebda908fd6c16a4abfe93.cab + - fileName: Installers\Windows SDK for Windows Store Apps DirectX ARM Remote-arm_en-us.msi + sha256: 40FF1A1EB0CCC1CB6FE63CED1F2C0C49878DE8A119F25C0094AE55E93D2C1D39 + size: 372736 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/847521f803b486c60df223619f14419a/windows%20sdk%20for%20windows%20store%20apps%20directx%20arm%20remote-arm_en-us.msi + - fileName: Installers\47133212c2f5ccf49392d7762293a075.cab + sha256: 5A654A908D3DC8F5BC2C90E3F18D2EC037787667DCDC28F2589A5C63DAD91743 + size: 1611825 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/55c0573c5dd1ea56ebc5aac662c7d609/47133212c2f5ccf49392d7762293a075.cab + - fileName: Installers\aac61496dd6fee21a0e5627e4dcd8488.cab + sha256: 1902513305203DC0F59835FEACC54E024C20BE3A11FD09908F3D8A65C7072C42 + size: 2603573 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1f02182199d2948ff8b951773e7af6bc/aac61496dd6fee21a0e5627e4dcd8488.cab + - fileName: Installers\Windows SDK for Windows Store Apps DirectX x64 Remote-x64_en-us.msi + sha256: 10129A41D520D887F5D328A9E75FDEFFEB4F2A5EA5D07E89586240A44DA566A1 + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/07d5f16c368c237e63a85e1cca575ca9/windows%20sdk%20for%20windows%20store%20apps%20directx%20x64%20remote-x64_en-us.msi + - fileName: Installers\ab8c11616091812d6c7137e366ba1d8d.cab + sha256: FE1C06220712C8BFC1D11910119171FD6D64963530C7C5912ED00631F33D1A25 + size: 24403 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/884de99f5722c6199697eb9dbc568588/ab8c11616091812d6c7137e366ba1d8d.cab + - fileName: Installers\4ac48dbdddbc8ce04721f519b9cf1698.cab + sha256: 18FE7E4EEC42A8CBAF5854A960B718986B3A464A7A670EDE4659C8FFAB5452F9 + size: 3278103 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d959a19c1d79eca67029575dee716fa0/4ac48dbdddbc8ce04721f519b9cf1698.cab + - fileName: Installers\ac4ddfcf1101c483559a5f6e36f1ef2d.cab + sha256: 4177BA61946ED6EC7A0B53611ADF85603AD2D9D1CD62833BD72ED737FEB5EFFB + size: 16269 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b7b3eb729c3bd67a985591c31793d605/ac4ddfcf1101c483559a5f6e36f1ef2d.cab + - fileName: Installers\Windows SDK for Windows Store Apps DirectX x86 Remote-x86_en-us.msi + sha256: 3D7FB4B50E8D71C02FA911A25CAFA32941A4F68FF1F05F86582F06CE109263EA + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ef92a4a17c458d2af21898caec2a2b1c/windows%20sdk%20for%20windows%20store%20apps%20directx%20x86%20remote-x86_en-us.msi + - fileName: Installers\Application Verifier arm External Package-arm_en-us.msi + sha256: 22FB02082F18005E2F224F071DB69435552A90BAD86F10EB529D7B92E583B40A + size: 2211840 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2ae750e3c5bec8647357ca6047a89132/application%20verifier%20arm%20external%20package-arm_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Headers-x86_en-us.msi + sha256: F245C437A4D08D9CF4399121D0ADFE3A7CEE0834506AD324C7883A48457E55E6 + size: 970752 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d7c5bffd1d0edb6815625ed858705fd5/windows%20sdk%20for%20windows%20store%20apps%20headers-x86_en-us.msi + - fileName: Installers\4ad4df991deb0eaa1f79f896b959d580.cab + sha256: B44CBEB76672C0F3F2ED10981D7C0C30BB9BE073802A3B8E10CF07FDE221C937 + size: 1527810 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c63666fa4268d6ebdc5ad04024b92fea/4ad4df991deb0eaa1f79f896b959d580.cab + - fileName: Installers\Windows SDK for Windows Store Apps Legacy Tools-x86_en-us.msi + sha256: 3C8C8D6C7EEB610357700129367B16D223FE532A8DDA39F29DEC0F20D61FF89F + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0c3f779d8e99067fa45b412f1e1cb4d0/windows%20sdk%20for%20windows%20store%20apps%20legacy%20tools-x86_en-us.msi + - fileName: Installers\Application Verifier x64 External Package-x64_en-us.msi + sha256: 7B4BCF777AA6131285C1DA13A9F921306DB0F70B98CFFB458EB7EE8C2B7D4221 + size: 3727360 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c7fda7efe6c6440b97b3aa7c6322c517/application%20verifier%20x64%20external%20package-x64_en-us.msi + - fileName: Installers\4c3ef4b2b1dc72149f979f4243d2accf.cab + sha256: FD1753FE16D0DAC3EAE95F3349697CD47F6971463E7443BD12B22D761378ADA5 + size: 543838 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7397e7f1e006b797bcbb2fb4c8af7fa6/4c3ef4b2b1dc72149f979f4243d2accf.cab + - fileName: Installers\Application Verifier x86 External Package-x86_en-us.msi + sha256: EB862D6D97A0962F1D6FD0945419393336DF3092B63EB7A40CD92632E89B86BA + size: 1982464 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/21ac021e190cf2788252b366f3db88bf/application%20verifier%20x86%20external%20package-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Libs-x86_en-us.msi + sha256: C9B0E0DC7B6F5877C5DDE69DAFFCB066E152B272D5E7E05CA920D0DD7089DDC2 + size: 483328 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d1c296c83d7d3011b19e63f0ae65fb86/windows%20sdk%20for%20windows%20store%20apps%20libs-x86_en-us.msi + - fileName: Installers\4c576e9c56c314d28a0e9d10ab87ca67.cab + sha256: EFC5A11EE2C723A4118F4861B195C93987DE4FE2C8FC491925AC1DC3A90B6F59 + size: 2519948 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1781f5d42dfc3cb9c5754f9c950cba3b/4c576e9c56c314d28a0e9d10ab87ca67.cab + - fileName: Installers\Windows SDK for Windows Store Apps Metadata-x86_en-us.msi + sha256: F0E6C7BFEF429F5A3BFA23BE83EF6DACBA294EE97902885FFEE2220040DB4F16 + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bb1798c5fd66107c833fcbd7803a6b67/windows%20sdk%20for%20windows%20store%20apps%20metadata-x86_en-us.msi + - fileName: Installers\4c59234340aaf3a96ec480c1aad8d179.cab + sha256: 300229CAC9325AF5AEE3F6A0DB155509E4C583654B07CDB340F697B84723C51F + size: 559521 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a0912c7e4c84863d2b96a84dbba57dfd/4c59234340aaf3a96ec480c1aad8d179.cab + - fileName: Installers\b1a824e2952532fe8fd0145f5d148d25.cab + sha256: 37FC3A3D619C7CCDCB03AFACBDCE6CE79129F844A0329AB43C54029372B9812A + size: 344566 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d67d3fcec67ead23063425761abfa148/b1a824e2952532fe8fd0145f5d148d25.cab + - fileName: Installers\Windows SDK for Windows Store Apps Tools-x86_en-us.msi + sha256: 44FF9FDA8BF7B152446227D4F9C53B118137FAA008C10F540AF469718D0C4A3F + size: 462848 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/73bdcdab5ba9dbff95f6e655f528cfbb/windows%20sdk%20for%20windows%20store%20apps%20tools-x86_en-us.msi + - fileName: Installers\4dc69cc131b3f4fdde53e76d759509dc.cab + sha256: D579540A46789E5091BD306B537CB239F29B5B0226659D0F6A085301AF88B35B + size: 395826 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/393e71b6892ffa4e661cbaa009b9478a/4dc69cc131b3f4fdde53e76d759509dc.cab + - fileName: Installers\b1a8ecf890b4ffddd05e8c9422f55db7.cab + sha256: 6DCB23827374A74502FEE2A119EA3A210A47EED144BD3FD657027B9341D551B3 + size: 143164 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/91c772caafbf046b4f9653d513de472b/b1a8ecf890b4ffddd05e8c9422f55db7.cab + - fileName: Installers\b2f03f34ff83ec013b9e45c7cd8e8a73.cab + sha256: EC2B6A76A4E6CFD0138D1295C022C078FE94E04474173285E81C165D52851200 + size: 147213 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e57e475e2fa4a72524dad67eb19dc95b/b2f03f34ff83ec013b9e45c7cd8e8a73.cab + - fileName: Installers\Windows SDK for Windows Store Apps-x86_en-us.msi + sha256: 10474A9117EF5316FE0ED6EF9F7FB5F7D6131D0FCB92ECEFDB9D88257B1413C4 + size: 397312 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/4aade48cf90cd8286ec0f0fa779d88cf/windows%20sdk%20for%20windows%20store%20apps-x86_en-us.msi + - fileName: Installers\b4eea6c909a31ab051e6f9b6218beec8.cab + sha256: D4E74A1B2FC995A748E288439E971381AB12638FD447F7CFCB315FE68ACF41FD + size: 367074 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5a0cc216bf4b5a6c05aee7d0a92e7cd8/b4eea6c909a31ab051e6f9b6218beec8.cab + - fileName: Installers\4de7a1422374f98369172705b05d4bf9.cab + sha256: 360832F015E16D82DE1D56E5760F148147E138F1576AAB7ECA6E3CE1F5D3B17B + size: 1144428 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/21dd85656df111cf3be33b1497060d0b/4de7a1422374f98369172705b05d4bf9.cab + - fileName: Installers\b5f177b84c0ec473cbd69557634b27cd.cab + sha256: 4510F2736B57C3DCBDA8116DA97B98CFC5416F0A9AC63BF75D7ED97045EEF274 + size: 14357 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2458f8fa649553d3c34120159e90d65b/b5f177b84c0ec473cbd69557634b27cd.cab + - fileName: Installers\Windows SDK for Windows Store Managed Apps Libs-x86_en-us.msi + sha256: AA31DEC6DD1EF9E93671A2244CCAEAE50434D3CD8202FB5525771224C4894DDD + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/951af64ba0a19d492ea100f90fd8c437/windows%20sdk%20for%20windows%20store%20managed%20apps%20libs-x86_en-us.msi + - fileName: Installers\4e2dea081242e821596b58b31bc22cca.cab + sha256: 6D8104581377F4D5AB7E8B843CA1645B1603BBAD11C4C82E7BEB7A73F28DFA66 + size: 14348 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7e6f44b2a0277c17e641c8179a81514a/4e2dea081242e821596b58b31bc22cca.cab + - fileName: Installers\Windows SDK Modern Non-Versioned Developer Tools-x86_en-us.msi + sha256: 0A83B46D80220EE81EFD882A4FC1C67578A66314E9C8B025E044CADF245CB033 + size: 393216 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/9caae6055fe0e8b866be5850550a7efe/windows%20sdk%20modern%20non-versioned%20developer%20tools-x86_en-us.msi + - fileName: Installers\b80b7321357f7c9f281536f9440dfe68.cab + sha256: 9432E3379A0633AEBD0F63EC01DAAA7B39FF4BBA48BD90C38BBE5F3DABADC84F + size: 14589 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/87198a00fbf8b8fcfe68d464abf2695b/b80b7321357f7c9f281536f9440dfe68.cab + - fileName: Installers\4ec14c5368b7642563c070cd168960a8.cab + sha256: 0E00EC2763958BB98DBA7C3D98932FFB1CBE23608B60AC630B286C747E80816E + size: 1786673 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/59b4b19ae769bf85fe6557f4a350cbec/4ec14c5368b7642563c070cd168960a8.cab + - fileName: Installers\4fe4c8b88812f5339018c0eef95acdb9.cab + sha256: C830A0D703E2BAF8638112E511447272E4A572B832BBCEFE5C334E929FC12C4B + size: 1123290 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/675574d2b18b2d2bb551fbf50419c83c/4fe4c8b88812f5339018c0eef95acdb9.cab + - fileName: Installers\Windows SDK Modern Versioned Developer Tools-x86_en-us.msi + sha256: 20ECA3F355A8ABF1B1103A9C60785152D75359FB2CA90F134E2CF25B0E5D5ADD + size: 397312 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/832119ca28640effa02b3d4bba91b7b8/windows%20sdk%20modern%20versioned%20developer%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK Redistributables-x86_en-us.msi + sha256: 92062CAC5F8402B18854C7EFAF20E045BB20F36C589FA1D7D65324CC42233FDB + size: 389120 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2aba3a73d1f17173031b16d05c2e1695/windows%20sdk%20redistributables-x86_en-us.msi + - fileName: Installers\b82881a61b7477bd4eb5de2cd5037fe2.cab + sha256: 682820AA8B7A9CAC19708180F7D18999AD96935349EC151D1064A24D14D9ECFF + size: 5888840 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/ad7363ba14c717a6ab0e347fdf807d0b/b82881a61b7477bd4eb5de2cd5037fe2.cab + - fileName: Installers\Windows SDK Signing Tools-x86_en-us.msi + sha256: 81669A17F190283F2C9FE44D1C1E166203CB232C066B4457E04B5A3DB34BD678 + size: 397312 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/78fb797e51a96bf72acbc279a0d56d9e/windows%20sdk%20signing%20tools-x86_en-us.msi + - fileName: Installers\50ce7925226cb6ab8e0fe9ad9fd58433.cab + sha256: 3126917068803509E38974C6073CC56F612579D4E1DF1EBF57DB6E950E846D41 + size: 4019998 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/96e05bea353cfa620241f5766a6a0b35/50ce7925226cb6ab8e0fe9ad9fd58433.cab + - fileName: Installers\b913ca15956d14df2d4b1f11ae07885b.cab + sha256: 3B7CE9C77432F47D51FF26A3027896DD2DB69839A430B827B9A5E3EE53446C6E + size: 262471 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2828c6126fa1351780017e0ac909f2e8/b913ca15956d14df2d4b1f11ae07885b.cab + - fileName: Installers\52a8e5203ade8fe7174c590308f2e44a.cab + sha256: F68D5D43491B83DC0764C8F1A7BD5AD87177DDEC844DDEF19E54502409227AE2 + size: 461962 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/15b1c37a231eba17c0aff2a1d9102293/52a8e5203ade8fe7174c590308f2e44a.cab + - fileName: Installers\b98a31e36735eb82b3b238c68f36fbbf.cab + sha256: 815C23AEB74AADD14AB4462678C0FC87A0EA75347812D4E8B6BA03B3D12E72C1 + size: 2529469 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6d0fa3d6c9a3d7436ae08ad50821afe3/b98a31e36735eb82b3b238c68f36fbbf.cab + - fileName: Installers\Windows SDK-x86_en-us.msi + sha256: 08FDDCBD92131AAF596B87F09F229FF55B060B3520AF8F3505EF51E4EA90CD38 + size: 397312 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e82c78d1d8612e5c0b0992e97d475991/windows%20sdk-x86_en-us.msi + - fileName: Installers\ba5d20281a858248e59d96d75c014391.cab + sha256: 67CB3357390966B144C2EBEDD8CBE5C1D4AD9B7761F38F9838796A37631A4063 + size: 1118418 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/51b8c857861888bea951044116ecddf6/ba5d20281a858248e59d96d75c014391.cab + - fileName: Installers\53174a8154da07099db041b9caffeaee.cab + sha256: BB5E5AE83E6976B4B80B6E8451D25B1C70F80B4F8002E4507989159A0702B8B4 + size: 17604513 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/58eb336be95c7b8c9ad0687dde5e8559/53174a8154da07099db041b9caffeaee.cab + - fileName: Installers\Windows Team Extension SDK-x86_en-us.msi + sha256: CA93C4FD7C165E185B66A6604C79471F97083E508758FD2AD3C76A79264CAC01 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/40c40a67557b04eed93a85b6d34cbf6b/windows%20team%20extension%20sdk-x86_en-us.msi + - fileName: Installers\ba60f891debd633ae9c26e1372703e3c.cab + sha256: A3831AB7D7D6EEA2486A3FA1D5037A07F48BC39A2B67804C5A3D30D7E5BE986A + size: 9178973 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/8b1e886bd92fd53875da59977b7b5435/ba60f891debd633ae9c26e1372703e3c.cab + - fileName: Installers\baa2d817ae180ba7e772f1543c3bbdea.cab + sha256: 7F304E91AA4603FF1C31C02DAD435BD247468E2B51DBE1A5D00F858FF11B3123 + size: 411240 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/15e528ac1731984e640c44535f7573cd/baa2d817ae180ba7e772f1543c3bbdea.cab + - fileName: Installers\bd4b6e22633abadb45b75bc86caaa120.cab + sha256: 730451A6C14124F49891861E3454AFF39D86EDF25CF5B85F2445502A8E94CF84 + size: 174143 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/76e916abfa2efe047ab1cbf260d2c85d/bd4b6e22633abadb45b75bc86caaa120.cab + - fileName: Installers\54a71dd657698028e27ce58b8c8f477a.cab + sha256: 53AB31304998100950481CE3012D39FEB1FA8F6176083F22A0B564E5C6D98830 + size: 7264706 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/49827fb24c840320172fcd65e637111a/54a71dd657698028e27ce58b8c8f477a.cab + - fileName: Installers\be06eca425b0c3c2f4de61cbfe9bc7a7.cab + sha256: D09FCC626876DFE01B92439DA03D429C1C8981376D225225F4DB1F55B8B6A288 + size: 262521 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/03ed4b68d04ca522fa800742e6b06397/be06eca425b0c3c2f4de61cbfe9bc7a7.cab + - fileName: Installers\beb5360d2daaa3167dea7ad16c28f996.cab + sha256: 12FB295DC6F2B1890D8999E07BDE19F26C8936624FAB7C76F4C7D4E85EB0A92E + size: 559014 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c908b792203f1c8d3b73043d9ead6247/beb5360d2daaa3167dea7ad16c28f996.cab + - fileName: Installers\5509e4710313421be8d5e7cfbfde4d30.cab + sha256: 02F98281741DBFC5AA5612E8B6B4F5C694DCD8BB14D1738B778F25208595330F + size: 1284455 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0f739e497758a7374055a53cf5b48db0/5509e4710313421be8d5e7cfbfde4d30.cab + - fileName: Installers\c0aa6d435b0851bf34365aadabd0c20f.cab + sha256: CDD0D1D17EEF217EF3BE59B318ABCAE73DAC2B3465E83B712BCEA2559B9AF39C + size: 3844683 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/19a6b19e8ac9836b16e9bb175dc938c9/c0aa6d435b0851bf34365aadabd0c20f.cab + - fileName: Installers\559dbc3a49a69c6adf60b1c87b4df71b.cab + sha256: BAD90B9778E8F3CE6C58012CEC5928F16BCA97510ED0326004440046ACD9361B + size: 14201 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/18ab6c0f12fe8025a5794b598c3245c9/559dbc3a49a69c6adf60b1c87b4df71b.cab + - fileName: Installers\c1be9e93e88be3f6207f5cc074775d81.cab + sha256: B3CDE83374276BCE50CDFC720AFD4812BFF8ECCD73210DE45DCB384E66BF5FD3 + size: 94260 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/424935b709a7d0317e6369b2bf17707b/c1be9e93e88be3f6207f5cc074775d81.cab + - fileName: Installers\563138901adf40a699df4654138ac397.cab + sha256: DA8BA6BB6AC72000791776A003813AC8BD56331F449433C557A61E1B9071B2D4 + size: 1424326 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c1b69504d71b7933b3583dfbcce139ba/563138901adf40a699df4654138ac397.cab + - fileName: Installers\c1c7e442409c0adbf81ae43aa0e4351f.cab + sha256: C36EDFCF3E9487BB5F5201CFD0A265D3BE9D0894455609500DF0E3005C4E8166 + size: 864376 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/59981b04110d07d98b0172ce1d371850/c1c7e442409c0adbf81ae43aa0e4351f.cab + - fileName: Installers\c2aabf6ea5c1d348ec22f3aeb92f8656.cab + sha256: 057A253A8B444F4F645B5B3BE6D8B4E4D5750F2EDE6F2EF928A8EEC3F2FAC96A + size: 14557 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/3c1f05ed57ff46dc277fd07f25a0294d/c2aabf6ea5c1d348ec22f3aeb92f8656.cab + - fileName: Installers\c4d38a2c963178a1a3469ca3d913768e.cab + sha256: F9DB00A678F68BF7F1DFA05AA538971D8EE4F59E1AEF72D6BF5C7BB8D52422A1 + size: 16854 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2db9655a82ebfe2575fd4adecc06e2b7/c4d38a2c963178a1a3469ca3d913768e.cab + - fileName: Installers\caab1106d57ff70cb3cbd8350a77e871.cab + sha256: A765DAD70116A2BC09C13100B3CB020F1E9A3FB8FBD88F7F5D9FE05442250004 + size: 967390 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/fb2e7d921763293efce27813ceb4f025/caab1106d57ff70cb3cbd8350a77e871.cab + - fileName: Installers\5642ea5ea549365f8b2a4f885b407d18.cab + sha256: 441C1F8370D3C07C084D4E31A5CFFA97E911E37D301B5C6AD76E1FB03D51E770 + size: 7808669 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/34af0380a9bead11e0903e8f358353f2/5642ea5ea549365f8b2a4f885b407d18.cab + - fileName: Installers\cd9128b760c06a010e1621af6528432e.cab + sha256: FC59DC596176862DDB002D7E0EA23097F44A65E9A6B75E8A12013E00C22A260A + size: 57767 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5dc2dd9e78934197f5e521e921e0d73c/cd9128b760c06a010e1621af6528432e.cab + - fileName: Installers\5697d8a4098ded6eb49417251c138643.cab + sha256: 59B88594DCFC8ADCFBEB1707B56421B4E92872C5A0C7CF83C7FEBCAF6FB72D58 + size: 793812 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b0eab1d2c6be996ba2152daa3fbb056a/5697d8a4098ded6eb49417251c138643.cab + - fileName: Installers\cdea5502a35d09ddfbcda12e3a391dc0.cab + sha256: AF831203B6003D156F48D3201D7FEB10EA63C6D3CC13BBEE5539A0CFA2F39452 + size: 6296084 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/cd1c02c102062c8a25bb03bfead09899/cdea5502a35d09ddfbcda12e3a391dc0.cab + - fileName: Installers\WPT Redistributables-x86_en-us.msi + sha256: 8E00D62B865917E64204A97DB3912BCA13109B28775B5B01AA13145A57FB99E7 + size: 385024 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6443102e9bee5b9a9fd76da91d46d388/wpt%20redistributables-x86_en-us.msi + - fileName: Installers\d117bb4bc77abadc7c603552e122e513.cab + sha256: DCB375533896D6BCDFBC0875AC97AFEB026700E6485B0636BD4D2AA41D2A046F + size: 578516 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/cd644fdb2cea1b5a34d2e577fb8e50ad/d117bb4bc77abadc7c603552e122e513.cab + - fileName: Installers\56a114848fda9a7e47bad4b3fc4be9a6.cab + sha256: AC08DFE1EA96BDB8A3D049CD014965361CE58EB6C01AD5F53F1EC57CAD095634 + size: 6929136 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/517185751bcf4f3b0b5c2ba712e00bab/56a114848fda9a7e47bad4b3fc4be9a6.cab + - fileName: Installers\d3e405ab232f8aca8c5b6a48a913d6b0.cab + sha256: 2F07E1B09FF07E4273D042129C77075EE38ADF2301BC5C244E65C49771C5A8B1 + size: 175774 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2bb6e0b24f5c2c57795724ce9607db55/d3e405ab232f8aca8c5b6a48a913d6b0.cab + - fileName: Installers\d55d1e003fbb00a12c63b8f618e452bf.cab + sha256: BA68944AB391E4B3DF5156481472935BE97A9D84405CDE4101ED0C38B0D9CCCF + size: 466425 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/cee04d0a0bd5691495203c52da1a5944/d55d1e003fbb00a12c63b8f618e452bf.cab + - fileName: Installers\WPTarm-arm_en-us.msi + sha256: F5CAF9932EA9401780294D75AED3FBE0CFFD03170DD33434688ED1E73801ED53 + size: 13168640 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c511bda167f4dabd615f487cf2103f34/wptarm-arm_en-us.msi + - fileName: Installers\576cff9c50e8085ab8d9c28ee12bac3e.cab + sha256: FF9E073B9430AF5E9BBD8FC69BAAA5CC08C40AD3EA87B077D94DEF3464A8BC8E + size: 597768 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e551141b9cef7d59059c785360ddf578/576cff9c50e8085ab8d9c28ee12bac3e.cab + - fileName: Installers\d67259e233ce975d91c3b02d483becad.cab + sha256: 0607B9897C045EF8D01154CD4830ACDCDCDA763BA33A88DEC70878107A3C3540 + size: 13881743 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/159f4cc5c1b4cde8522a5bc62b818b40/d67259e233ce975d91c3b02d483becad.cab + - fileName: Installers\58314d0646d7e1a25e97c902166c3155.cab + sha256: B1106B03D1C88194B4E0CC11B58EDA9747C71AE8EFAA115AD081D024403F35A8 + size: 18760477 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a793b61ab658464013c60bc1db706fa8/58314d0646d7e1a25e97c902166c3155.cab + - fileName: Installers\dc19fbd16e9708e0bc4d8419e3a7d48d.cab + sha256: FB2E6C05F6791EDF200D4A646C28C3F461258EE1E7A90D861AA59C58B10296BB + size: 16518 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/422ecbedb1ad1b0707f84e12edfdc931/dc19fbd16e9708e0bc4d8419e3a7d48d.cab + - fileName: Installers\WPTarm64-arm_en-us.msi + sha256: C1F0A4999C6F2992C80A3A89693257977EE70D7AB593AFFA76EF2537B775A2B4 + size: 13754368 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/80f27a1e215da33f661b68617fb009ef/wptarm64-arm_en-us.msi + - fileName: Installers\590d28783ff280b8b0016c3492433241.cab + sha256: 66868BAC6C28B9D20587BA2E6ABDA83C795F3231B578DC640D20D12B963952D3 + size: 3691503 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5866e78d708682f8395af5f0b74f7fce/590d28783ff280b8b0016c3492433241.cab + - fileName: Installers\dcb0a55d6cacaa05ead299e1d3de3c6d.cab + sha256: 08045C47FC36707C58C2C52C89BD7F725DE96F3149B75E10836E1ECAC0F5F207 + size: 7808644 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/7d04aaf5361fba8c9b67695ab22aa95c/dcb0a55d6cacaa05ead299e1d3de3c6d.cab + - fileName: Installers\598442d9f84639d200d4f3af477da95c.cab + sha256: 2C396B52135CC47D18DF088626BC5ECF3E37CD2A1133032851E8476338559769 + size: 54719 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2b2abfca060b0709e3a1158bbe1ab964/598442d9f84639d200d4f3af477da95c.cab + - fileName: Installers\de111c3d435b0785b31b28c386ee691f.cab + sha256: 47FA6D9A9BC4D84FE51E3F5727243324517E62874751A2D70392EE9502980D67 + size: 14650 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/487a9297c9a8c5e588a4d55c681dfbef/de111c3d435b0785b31b28c386ee691f.cab + - fileName: Installers\WPTx64-x86_en-us.msi + sha256: DB02CB0802A7C977631BC8160411BDAC029E27E57B952512A3062A5E3AA08AD9 + size: 19165184 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0542862b91269f31d9af0351b5f1d550/wptx64-x86_en-us.msi + - fileName: Installers\e072b3b3d3164e26b63338dce51862a7.cab + sha256: 3763867350D83091C986FD276AC4D0974FE9734312E19CA9B22D661E74386806 + size: 2641099 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/713d40d29d5b9963a7d82411a639ddbf/e072b3b3d3164e26b63338dce51862a7.cab + - fileName: Installers\5a22e5cde814b041749fb271547f4dd5.cab + sha256: 9E621AD95B4DC580AF43DBC116F55ECC88D475C0EADDC71FADD0FAF31E6BAD18 + size: 9227345 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/0db28c810db0dce7f2cba59290c0f8e0/5a22e5cde814b041749fb271547f4dd5.cab + - fileName: Installers\WPTx86-x86_en-us.msi + sha256: 4261A56F7092CA8A2ADABB24C2E148A489881F72DD2FE6D064E909F4DAB13A18 + size: 17661952 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/b5b56a14a0e078e32b9140fd86059e9a/wptx86-x86_en-us.msi + - fileName: Installers\5c2fcb46e03eada0ed0cad44a3f5c71f.cab + sha256: 3B60084104F2F5FD05C8685581E1D457B8E2665BDB0EA95B212EDAA0786F5026 + size: 14238 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/1a3f371c0ed5991631ff122b708cdd9c/5c2fcb46e03eada0ed0cad44a3f5c71f.cab + - fileName: Installers\e10768bb6e9d0ea730280336b697da66.cab + sha256: FD20BD5D13512919CECBA03C2CD0273AD2E42864AABE09C8F5E6F45B52F80968 + size: 9123551 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d6f291c8ef3df4aee5a92e77d04cd321/e10768bb6e9d0ea730280336b697da66.cab + - fileName: Installers\5c9ecffb06ed5f4fe5fb7db86bf7328b.cab + sha256: 7CB7750E9BCFC28340BA545351C86E1BD309D77A0F237B49FAF659F13CB497AF + size: 381655 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/136ea463e88cd573fc17c78d3f1d6435/5c9ecffb06ed5f4fe5fb7db86bf7328b.cab + - fileName: Installers\5cf1d61a223a02ff2f52fe05f058d52e.cab + sha256: 7A58743EB97E34A6A67ACFCD6EF93C8D95EFC0D1B75F1AB5024C2C36AA1F7310 + size: 1525161 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f551e74009ed44c5ac757b81b97580cd/5cf1d61a223a02ff2f52fe05f058d52e.cab + - fileName: Installers\e10f8811d44b50885777f56f8272f66b.cab + sha256: BF307813ECBB1D17569D572C0B418EE180FC752B713DBD41E8AD51AAA69B5863 + size: 559025 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/9202715cfa08be8df6e5498e47d6b1e3/e10f8811d44b50885777f56f8272f66b.cab + - fileName: Installers\5f6cfec263cd265cf3b0d97fd78ddf05.cab + sha256: 225E6449B7A933844654645872BF7325C009C1A2FDDCCC4F5B6D8078C78C938D + size: 3094595 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/8079e9bccf1c643b535c54be4465ccbc/5f6cfec263cd265cf3b0d97fd78ddf05.cab + - fileName: Installers\e10f9740446a96314a1731aa7cb4286a.cab + sha256: 607595E212AD9DF4896D210D7C4F0C24AE3BE551B8A2FEDCBE2C88286C164E4B + size: 2449982 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/63f1d1fb8e74e7ec47b33508a53b58a8/e10f9740446a96314a1731aa7cb4286a.cab + - fileName: Installers\X64 Debuggers And Tools-x64_en-us.msi + sha256: E9EDA93064502A6998DC94C85484B2E46E7C0781041653C28407DF9B6CF4A22D + size: 32108544 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/683c3ee73ff9a0e0f4299856e007d278/x64%20debuggers%20and%20tools-x64_en-us.msi + - fileName: Installers\e24dd258b3bbfa69c0842948fe0dd670.cab + sha256: A3FB0CC7D262CE572CBC03B9955FA146DDB96D333506F3DB621BE945517C411F + size: 879017 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2c43c3eda8f3e1e670139a3fd85c3b2f/e24dd258b3bbfa69c0842948fe0dd670.cab + - fileName: Installers\5f7ef4904f75bf6b3b9b0f8975ad1492.cab + sha256: E900A69AAD41C7395F6D1D6CD9BEE092F0FC9A5EA70D5F1BF61BC4ADED405E1B + size: 845620 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/03b743cdce82a0ebb854b5e6c4d8c81c/5f7ef4904f75bf6b3b9b0f8975ad1492.cab + - fileName: Installers\e3bfdbe21d5f48f62e6347294e6e8492.cab + sha256: FC786EE318C68B428D4CCCEC274FE45E07FE11E0B762544260544F60DBEDA9E6 + size: 99014 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c0b74deb2162af10023fda84dd1ededb/e3bfdbe21d5f48f62e6347294e6e8492.cab + - fileName: Installers\61d57a7a82309cd161a854a6f4619e52.cab + sha256: 2C89E3744D78D69660A7C78B183C4EC8848A987F4F206CC766132D696DCFCEA3 + size: 8228791 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/d13d608d9954070d42a01cd991bd1bae/61d57a7a82309cd161a854a6f4619e52.cab + - fileName: Installers\X86 Debuggers And Tools-x86_en-us.msi + sha256: D02E3641850A87E0ED5D2D3C17A489542479542E8110FBCA69E9C3A6F906BBF4 + size: 28200960 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5b4c6bed7592095d8aa290154b243ad4/x86%20debuggers%20and%20tools-x86_en-us.msi + - fileName: Installers\e3d1b35aecfccda1b4af6fe5988ac4be.cab + sha256: C05560ABB4982867397E725CC222F36B11F1042CF30BB94BB11BED255C588713 + size: 16235286 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/06f510df0497213b765259df3c2527cf/e3d1b35aecfccda1b4af6fe5988ac4be.cab + - fileName: Installers\e5950ce9ba509b3370ebf328742a5f45.cab + sha256: B7E1520EC792A11481A9420A97622EED096C266E503A13291EC77340911BA889 + size: 27989 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/c1dff373235ceb4dadb0114e2e39842a/e5950ce9ba509b3370ebf328742a5f45.cab + - fileName: Installers\65f45ddc30ad5fc4f9873e7791f83dac.cab + sha256: 231F1DE0531D8597173603BCB14914CD48116DCD44832BAE1A8FBEBD7DB99BC0 + size: 16517 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/f30c08e41a7390d8d7e9e7e462be731b/65f45ddc30ad5fc4f9873e7791f83dac.cab + - fileName: Redistributable\10.1.0.0\UAPSDKAddOn-x86.msi + sha256: 7EF21E5DAD1C1B2BACB85465E34DA02D753DBD2151E7D9847502C8F55AFF6323 + size: 212992 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/de37a3cad201a8eb445768600bc4646f/uapsdkaddon-x86.msi + - fileName: Installers\e59830bab4961666e8d8c2af1e5fa771.cab + sha256: 04E177F5A6F7CA6AF024B68DC520888C1DBAB8D41A51D668D6C20EE2161A7F8F + size: 141849 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/fff4a7b3afe88d5c3cb4b59c28ae59e3/e59830bab4961666e8d8c2af1e5fa771.cab + - fileName: Installers\66c7c64126fbf84f47ccec556d149b12.cab + sha256: 8553D65C89DCBA13CDEC82AC6C991A9B5A67B3452FA7ABD665023A4F382628FF + size: 14669 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/2a4f500081e26ea663b4855010f25daa/66c7c64126fbf84f47ccec556d149b12.cab + - fileName: Installers\68de71e3e2fb9941ee5b7c77500c0508.cab + sha256: 4E617EE343859372023FD3E72A96DFBA5A38042BE81D9E5D15ADFD428D7E87CA + size: 31918 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/78e95b5bfa48a75cd461a322863b5bbe/68de71e3e2fb9941ee5b7c77500c0508.cab + - fileName: Installers\e5c4b31ff9997ac5603f4f28cd7df602.cab + sha256: 12D88DC95DCF6B8E351CE79EA58E2B91B50F13BF92F6EB40C7ACC3CAB4A59BE0 + size: 592022 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/03a03f7e10c6fd1cb4901dc869964f62/e5c4b31ff9997ac5603f4f28cd7df602.cab + - fileName: Installers\678f64f35c507af8a9af0532b9b211ec.cab + sha256: 3FD9CBA337FD1D9CBF174835542E9A1BB90918CF95A38CB904D581AC29E844F4 + size: 7808469 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/a2351f79afcbc67598681d62bec18114/678f64f35c507af8a9af0532b9b211ec.cab + - fileName: Installers\67c9fd1fab36154e6e7e429610cd67c8.cab + sha256: 53631040672224C3F0D069A07F95A40D34DBAD1CADD2F6D6AF82788ED7BA8523 + size: 763366 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/176f8d7c6efd03b8f7ff2df71635821b/67c9fd1fab36154e6e7e429610cd67c8.cab + - fileName: Installers\69661e20556b3ca9456b946c2c881ddd.cab + sha256: EB5BDC32032112681F13FC33F986871C2C2AF0AFC92EF7B31E6BDACD6A520256 + size: 19213877 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/bf5eab4ce95908c69c1e4aa9f6695701/69661e20556b3ca9456b946c2c881ddd.cab + - fileName: Installers\6b12414fdb1b4978419abcd383206c09.cab + sha256: 759C59C72E3E998646BD1E92732D4503B9A0477795188DA0E48EC6EBD2A8BCA5 + size: 14237 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/6202753d8f4f36ae0d6409a931f11d3f/6b12414fdb1b4978419abcd383206c09.cab + - fileName: Installers\6b5a91701fdb98ac8bc4af6e238e0390.cab + sha256: 899A202D511D39E36365A8C459F9130CEB1FF01664387338BB01B3E67C359825 + size: 1884879 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/8b6be26a048f34df2aaff51ad76e3b3f/6b5a91701fdb98ac8bc4af6e238e0390.cab + - fileName: Installers\67fb2af3d2219b403e419535a547c019.cab + sha256: 3ABF3C5B30FE0F85F6D4D7CFDC15079F1AF9514A6E76FD45CDA90050B57300F6 + size: 95830 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/e375c5b47fb2ba4467690df254eb99d5/67fb2af3d2219b403e419535a547c019.cab + - fileName: Installers\685f3d4691f444bc382762d603a99afc.cab + sha256: 3CF52BA13A9F3CF5A6A51DECA95E683367DF4D1E54899F60159DFE7FC1B7E0BF + size: 1134872 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/5dba6fa9031c2dc50ed6a51bb073d285/685f3d4691f444bc382762d603a99afc.cab + - fileName: Installers\6bc159aa6f35510d049f0639e0ddb277.cab + sha256: A01490E47C401AD5B9616694B4507303E3A3102B2A9549AC6DD97669E858B990 + size: 3079950 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/860d24bada4211d70393dca73ea6c1d4/6bc159aa6f35510d049f0639e0ddb277.cab + - fileName: Installers\6d946492af1c4bd35fcc60ab2057db4a.cab + sha256: E3AC8E20A9D56208E5B451EDE2704AD85C3CD78624546E95E9DBE8A58EFC64AC + size: 2266544 + url: https://download.visualstudio.microsoft.com/download/pr/5eeaf3c7-015f-442c-8d63-aea17e5e6aef/13c5812eef5f93d41808e4ae0de889e8/6d946492af1c4bd35fcc60ab2057db4a.cab + type: Exe + version: 10.0.19041.1 + diff --git a/build/vs/vs2022.yaml b/build/vs/vs2022.yaml new file mode 100644 index 0000000000..c2f236dea2 --- /dev/null +++ b/build/vs/vs2022.yaml @@ -0,0 +1,1655 @@ +# Generated with: +# ./mach python --virtualenv build build/vs/generate_yaml.py \ +# --major \ +# 17 \ +# Microsoft.VisualCpp.CRT.Headers \ +# Microsoft.VisualCpp.CRT.Redist.ARM64 \ +# Microsoft.VisualCpp.CRT.Redist.X64 \ +# Microsoft.VisualCpp.CRT.Redist.X86 \ +# Microsoft.VisualCpp.CRT.x64.Desktop \ +# Microsoft.VisualCpp.CRT.x64.Store \ +# Microsoft.VisualCpp.CRT.x86.Desktop \ +# Microsoft.VisualCpp.CRT.x86.Store \ +# Microsoft.VisualCpp.DIA.SDK \ +# Microsoft.VisualCpp.Tools.HostX64.TargetARM64 \ +# Microsoft.VisualCpp.Tools.HostX64.TargetX64 \ +# Microsoft.VisualCpp.Tools.HostX64.TargetX86 \ +# Microsoft.VisualStudio.Component.VC.ATL.ARM64 \ +# Microsoft.VisualStudio.Component.VC.ATLMFC \ +# Microsoft.VisualStudio.Component.VC.MFC.ARM64 \ +# Win11SDK_10.0.22621 \ +# -o \ +# build/vs/vs2022.yaml +- id: Microsoft.VisualCpp.CRT.Headers + payloads: + - fileName: Microsoft.VisualCpp.CRT.Headers.vsix + sha256: a98ec6ee3b3beeb46c6df7dcb65308a8554b84daab6d92ad01a292798abb0fbb + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/a98ec6ee3b3beeb46c6df7dcb65308a8554b84daab6d92ad01a292798abb0fbb/Microsoft.VisualCpp.CRT.Headers.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.Headers.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.Headers.base.vsix + sha256: 6470f78ebeab42ba0dcc258af6381262fd22bcb6c98f7eb475ec4c1abe1def3c + size: 3526094 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/6470f78ebeab42ba0dcc258af6381262fd22bcb6c98f7eb475ec4c1abe1def3c/Microsoft.VC.14.38.17.8.CRT.Headers.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.Servicing.CrtHeaders + payloads: + - fileName: Microsoft.VC.14.38.17.8.Servicing.CrtHeaders.vsix + sha256: 264a78d86d5f6fea76f095642b6c3524299678f8ff0d66c7164b3fc355250b4b + size: 2007 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/264a78d86d5f6fea76f095642b6c3524299678f8ff0d66c7164b3fc355250b4b/Microsoft.VC.14.38.17.8.Servicing.CrtHeaders.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.Servicing + payloads: + - fileName: Microsoft.VC.14.38.17.8.Servicing.vsix + sha256: 1f9050aa0012a3a27432e24cc32d4d8a68be42693ec3809eae385e2d95d2e2ed + size: 2214 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/1f9050aa0012a3a27432e24cc32d4d8a68be42693ec3809eae385e2d95d2e2ed/Microsoft.VC.14.38.17.8.Servicing.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VisualCpp.CRT.Redist.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.ARM64.vsix + sha256: 1b0d024b02ea1b8f3b44235172c66f6b947dfbd401794bc247e31683f3d7a287 + size: 22598676 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/1b0d024b02ea1b8f3b44235172c66f6b947dfbd401794bc247e31683f3d7a287/Microsoft.VisualCpp.CRT.Redist.ARM64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.Redist.ARM64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.Redist.ARM64.base.vsix + sha256: e8b663fa3e2bf8b0e3015a21fc3c18ba8499ebee6d9112581dcf6eebd28a8dbd + size: 5185911 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/e8b663fa3e2bf8b0e3015a21fc3c18ba8499ebee6d9112581dcf6eebd28a8dbd/Microsoft.VC.14.38.17.8.CRT.Redist.ARM64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.Redist.Resources + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.Resources.enu.vsix + sha256: 9213845e19946c9c6f64df0a289601556e4efbba27142aee5d0e2cd368a3f158 + size: 1058 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/9213845e19946c9c6f64df0a289601556e4efbba27142aee5d0e2cd368a3f158/Microsoft.VisualCpp.CRT.Redist.Resources.enu.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.Redist.X64 + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.X64.vsix + sha256: e966520ff9a4b39d93eaf4e2276741815aa4311e2a2a41b8362c54c7332996fe + size: 50365917 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/e966520ff9a4b39d93eaf4e2276741815aa4311e2a2a41b8362c54c7332996fe/Microsoft.VisualCpp.CRT.Redist.X64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.Redist.X64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.Redist.X64.base.vsix + sha256: b898cf07a19e16214e7ec5d28b2699aea8a095456c5de6221d91c95cb2be5740 + size: 3410952 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/b898cf07a19e16214e7ec5d28b2699aea8a095456c5de6221d91c95cb2be5740/Microsoft.VC.14.38.17.8.CRT.Redist.X64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.Redist.X86 + payloads: + - fileName: Microsoft.VisualCpp.CRT.Redist.X86.vsix + sha256: 2dced84dabaef0beb2a3eaa676821714684370e78f0a24b12d1b147ae5a458e2 + size: 27203469 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/2dced84dabaef0beb2a3eaa676821714684370e78f0a24b12d1b147ae5a458e2/Microsoft.VisualCpp.CRT.Redist.X86.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.Redist.X86.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.Redist.X86.base.vsix + sha256: db141c6596ec224a0049592b68f619dd5827b2320ffc501f3079f0a12f861abc + size: 3049295 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/db141c6596ec224a0049592b68f619dd5827b2320ffc501f3079f0a12f861abc/Microsoft.VC.14.38.17.8.CRT.Redist.X86.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.x64.Desktop + payloads: + - fileName: Microsoft.VisualCpp.CRT.x64.Desktop.vsix + sha256: 72a745f7de593a9e1c49b720528f37b8893121569f2f098a84b71044a8f8d776 + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/72a745f7de593a9e1c49b720528f37b8893121569f2f098a84b71044a8f8d776/Microsoft.VisualCpp.CRT.x64.Desktop.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.x64.Desktop.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.x64.Desktop.base.vsix + sha256: aaa82d6cec89e0271a75cf8e07d957ce6fe75a4ac7f58284b8209213ae629cea + size: 47056589 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/aaa82d6cec89e0271a75cf8e07d957ce6fe75a4ac7f58284b8209213ae629cea/Microsoft.VC.14.38.17.8.CRT.x64.Desktop.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.x64.Store + payloads: + - fileName: Microsoft.VisualCpp.CRT.x64.Store.vsix + sha256: 0a84f5744705dbb456131d11e04b3735e1c75dac9160575f96556941b98c420a + size: 1070 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/0a84f5744705dbb456131d11e04b3735e1c75dac9160575f96556941b98c420a/Microsoft.VisualCpp.CRT.x64.Store.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.x64.Store.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.x64.Store.base.vsix + sha256: dcc5afa6389540801e9ccdfdde6982c5173f14802e354f87afc743c54441ee1e + size: 25354259 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/dcc5afa6389540801e9ccdfdde6982c5173f14802e354f87afc743c54441ee1e/Microsoft.VC.14.38.17.8.CRT.x64.Store.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.x86.Desktop + payloads: + - fileName: Microsoft.VisualCpp.CRT.x86.Desktop.vsix + sha256: ec3260046eb52c759ad5319a3e7ff397eebc20728496bd6e94a18790393cc891 + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/ec3260046eb52c759ad5319a3e7ff397eebc20728496bd6e94a18790393cc891/Microsoft.VisualCpp.CRT.x86.Desktop.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.x86.Desktop.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.x86.Desktop.base.vsix + sha256: 98e1bc95ba7956a8ca92eb625b88637651f35bd4fa3d88660ae4b12cd225bf1f + size: 72606892 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/98e1bc95ba7956a8ca92eb625b88637651f35bd4fa3d88660ae4b12cd225bf1f/Microsoft.VC.14.38.17.8.CRT.x86.Desktop.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.CRT.x86.Store + payloads: + - fileName: Microsoft.VisualCpp.CRT.x86.Store.vsix + sha256: 57be84ac82ad5a29b134562057282c8847e61b910a76de50485996fc123d4d53 + size: 1070 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/57be84ac82ad5a29b134562057282c8847e61b910a76de50485996fc123d4d53/Microsoft.VisualCpp.CRT.x86.Store.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.CRT.x86.Store.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.CRT.x86.Store.base.vsix + sha256: 17559c3fc6dd02b4af5c325fa2d009826b687d4186e03c0700eaa75d3d24888c + size: 24946625 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/17559c3fc6dd02b4af5c325fa2d009826b687d4186e03c0700eaa75d3d24888c/Microsoft.VC.14.38.17.8.CRT.x86.Store.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.DIA.SDK + payloads: + - fileName: Microsoft.VisualCpp.DIA.SDK.vsix + sha256: 73e3ddf59bb5ca99da9013aad518a0f96707913de0758421c155b8b2c074d039 + size: 6849524 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/73e3ddf59bb5ca99da9013aad518a0f96707913de0758421c155b8b2c074d039/Microsoft.VisualCpp.DIA.SDK.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VisualCpp.Servicing.DIASDK + payloads: + - fileName: Microsoft.VisualCpp.Servicing.DIASDK.vsix + sha256: 19aa3825fe3afe665596a5a53799cfdb7d3aededeafcdcb61b670c895dc5e978 + size: 2000 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/19aa3825fe3afe665596a5a53799cfdb7d3aededeafcdcb61b670c895dc5e978/Microsoft.VisualCpp.Servicing.DIASDK.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VisualCpp.Tools.HostX64.TargetARM64 + payloads: + - fileName: Microsoft.VisualCpp.Tools.HostX64.TargetARM64.vsix + sha256: 8577d01efebd533062c1761660d6f7a9229deb4c9b69a57a238e156f5e90a753 + size: 2296 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/8577d01efebd533062c1761660d6f7a9229deb4c9b69a57a238e156f5e90a753/Microsoft.VisualCpp.Tools.HostX64.TargetARM64.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetARM64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetARM64.base.vsix + sha256: 1f886d0edaa0036006e21e258466e3eabfaa91d816d33357065323caed2f02ad + size: 19674827 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/1f886d0edaa0036006e21e258466e3eabfaa91d816d33357065323caed2f02ad/Microsoft.VC.14.38.17.8.Tools.HostX64.TargetARM64.base.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetARM64.Res.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetARM64.Res.base.enu.vsix + sha256: b577ea9115bbc0e098f1de3c60046c9175580656c9149d32155315a181f87e86 + size: 219803 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/b577ea9115bbc0e098f1de3c60046c9175580656c9149d32155315a181f87e86/Microsoft.VC.14.38.17.8.Tools.HostX64.TargetARM64.Res.base.enu.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Props.ARM64 + payloads: + - fileName: Microsoft.VC.14.38.17.8.Props.ARM64.vsix + sha256: 4ed2b8968ec3dd0342e037106549128669b7094b5fa4122227c0ab1dace2a3dc + size: 2240 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/4ed2b8968ec3dd0342e037106549128669b7094b5fa4122227c0ab1dace2a3dc/Microsoft.VC.14.38.17.8.Props.ARM64.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Props + payloads: + - fileName: Microsoft.VC.14.38.17.8.Props.vsix + sha256: d246e144631fee8366d3b1dee43da0aeea3981aaeaad65654f77af1035e69c24 + size: 4104 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/d246e144631fee8366d3b1dee43da0aeea3981aaeaad65654f77af1035e69c24/Microsoft.VC.14.38.17.8.Props.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Servicing.Compilers + payloads: + - fileName: Microsoft.VC.14.38.17.8.Servicing.Compilers.vsix + sha256: 9a3673264ceebe311fc9e0785945d4920df311fedca1e718e49a6d6b21420a70 + size: 2001 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/9a3673264ceebe311fc9e0785945d4920df311fedca1e718e49a6d6b21420a70/Microsoft.VC.14.38.17.8.Servicing.Compilers.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VisualCpp.Tools.HostX64.TargetX64 + payloads: + - fileName: Microsoft.VisualCpp.Tools.HostX64.TargetX64.vsix + sha256: 62d763f6e18c0dc4f28c11ca3468ee8b26c5a362a9824566c443c3fa4a1fafab + size: 2245 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/62d763f6e18c0dc4f28c11ca3468ee8b26c5a362a9824566c443c3fa4a1fafab/Microsoft.VisualCpp.Tools.HostX64.TargetX64.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX64.base.vsix + sha256: 43c9b6ad02300e9fed100b187ae129628d1607c3f9f310436c3ab2af91a640ef + size: 20142162 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/43c9b6ad02300e9fed100b187ae129628d1607c3f9f310436c3ab2af91a640ef/Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX64.base.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX64.Res.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX64.Res.base.enu.vsix + sha256: 4545fd9b8558f2f3e471ea7285ccb220bbef84ca271d5094ddc838598195d3cb + size: 219618 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/4545fd9b8558f2f3e471ea7285ccb220bbef84ca271d5094ddc838598195d3cb/Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX64.Res.base.enu.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Props.x64 + payloads: + - fileName: Microsoft.VC.14.38.17.8.Props.x64.vsix + sha256: 4cea241fa03dcfefab34a3c6dd4db4531060160317541f83edd61c532f9999b8 + size: 2227 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/4cea241fa03dcfefab34a3c6dd4db4531060160317541f83edd61c532f9999b8/Microsoft.VC.14.38.17.8.Props.x64.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VisualCpp.Tools.HostX64.TargetX86 + payloads: + - fileName: Microsoft.VisualCpp.Tools.HostX64.TargetX86.vsix + sha256: 69ce817ccf134300c2650b475f22d031dda3ad741c059bebd871afca500c9c22 + size: 2282 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/69ce817ccf134300c2650b475f22d031dda3ad741c059bebd871afca500c9c22/Microsoft.VisualCpp.Tools.HostX64.TargetX86.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX86.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX86.base.vsix + sha256: 51677958cf3dcc11a4b0a470d09eaf4ed1660f19c44896a875d176755a730453 + size: 21297983 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/51677958cf3dcc11a4b0a470d09eaf4ed1660f19c44896a875d176755a730453/Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX86.base.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX86.Res.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX86.Res.base.enu.vsix + sha256: 898f19e75bddfdb9de863f7249fc3c0f333eb9d76fce7f002d23b14da66245ef + size: 219626 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/898f19e75bddfdb9de863f7249fc3c0f333eb9d76fce7f002d23b14da66245ef/Microsoft.VC.14.38.17.8.Tools.HostX64.TargetX86.Res.base.enu.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VC.14.38.17.8.Props.x86 + payloads: + - fileName: Microsoft.VC.14.38.17.8.Props.x86.vsix + sha256: aa0e1636337a40eb9037d409bfb2f7dfc0687f21e638a74f645e088ed162e2a0 + size: 2225 + url: https://download.visualstudio.microsoft.com/download/pr/3d1e46df-bd80-451a-ab69-06c02f9dc3f1/aa0e1636337a40eb9037d409bfb2f7dfc0687f21e638a74f645e088ed162e2a0/Microsoft.VC.14.38.17.8.Props.x86.vsix + type: Vsix + version: 14.38.33133 +- id: Microsoft.VisualCpp.ATL.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.ATL.ARM64.vsix + sha256: d3771e825bf4ba1ce22c41fb35abd01785b5c1623e858e571a946dc0612498d4 + size: 1069 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/d3771e825bf4ba1ce22c41fb35abd01785b5c1623e858e571a946dc0612498d4/Microsoft.VisualCpp.ATL.ARM64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.ATL.ARM64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.ATL.ARM64.base.vsix + sha256: 651cd263b87c6ca25dab72036afd442dffb40ccd58cb0de9eafa4cf2e987e45e + size: 1336359 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/651cd263b87c6ca25dab72036afd442dffb40ccd58cb0de9eafa4cf2e987e45e/Microsoft.VC.14.38.17.8.ATL.ARM64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.Servicing.ATL + payloads: + - fileName: Microsoft.VC.14.38.17.8.Servicing.ATL.vsix + sha256: 8b76cc8c88d8637880316436e27b78caa759c50e9ee02e95d32c5857b642c0b8 + size: 1976 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/8b76cc8c88d8637880316436e27b78caa759c50e9ee02e95d32c5857b642c0b8/Microsoft.VC.14.38.17.8.Servicing.ATL.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.Props.ATLMFC + payloads: + - fileName: Microsoft.VC.14.38.17.8.Props.ATLMFC.vsix + sha256: 0a98ec593216cafa9499fc051c7b209a93d446e57399976c98faf20073c8450c + size: 2179 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/0a98ec593216cafa9499fc051c7b209a93d446e57399976c98faf20073c8450c/Microsoft.VC.14.38.17.8.Props.ATLMFC.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.ATL.Headers + payloads: + - fileName: Microsoft.VisualCpp.ATL.Headers.vsix + sha256: 17322b92686d6e990682cd548efcc21f5e25838d69b3c03c8b8a5595298af1aa + size: 1069 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/17322b92686d6e990682cd548efcc21f5e25838d69b3c03c8b8a5595298af1aa/Microsoft.VisualCpp.ATL.Headers.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.ATL.Headers.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.ATL.Headers.base.vsix + sha256: 097f034e7f300a9d7a52d969af5fa9e0a391ef429cc872d9a4a991cb81caffb1 + size: 576341 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/097f034e7f300a9d7a52d969af5fa9e0a391ef429cc872d9a4a991cb81caffb1/Microsoft.VC.14.38.17.8.ATL.Headers.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.ATL.Source + payloads: + - fileName: Microsoft.VisualCpp.ATL.Source.vsix + sha256: 9df77d201d474b8f83ba2dbea37e42b5f7f65ff6b34565ecc04105fcdfc47fe0 + size: 1069 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/9df77d201d474b8f83ba2dbea37e42b5f7f65ff6b34565ecc04105fcdfc47fe0/Microsoft.VisualCpp.ATL.Source.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.ATL.Source.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.ATL.Source.base.vsix + sha256: 7d8e78794edbcaade94210773c5b44eaa0734f0e7c4032099f72e84553cf7e65 + size: 8618 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/7d8e78794edbcaade94210773c5b44eaa0734f0e7c4032099f72e84553cf7e65/Microsoft.VC.14.38.17.8.ATL.Source.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.ATL.X64 + payloads: + - fileName: Microsoft.VisualCpp.ATL.X64.vsix + sha256: 6d5191ebb525bd90f0b144ac990d7ab90ec015464ab28d2a6f5fbe9682331a23 + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/6d5191ebb525bd90f0b144ac990d7ab90ec015464ab28d2a6f5fbe9682331a23/Microsoft.VisualCpp.ATL.X64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.ATL.X64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.ATL.X64.base.vsix + sha256: f867c77b9897793aee01b7762f4ae2cc18ab84fc0cc8ed4c45f3864ccf7a09e4 + size: 777291 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/f867c77b9897793aee01b7762f4ae2cc18ab84fc0cc8ed4c45f3864ccf7a09e4/Microsoft.VC.14.38.17.8.ATL.X64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.ATL.X86 + payloads: + - fileName: Microsoft.VisualCpp.ATL.X86.vsix + sha256: 1ef6b01a4ce38662e658589b8fd15658dfe94d4bd8d63b9ad5a34596dd0eb553 + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/1ef6b01a4ce38662e658589b8fd15658dfe94d4bd8d63b9ad5a34596dd0eb553/Microsoft.VisualCpp.ATL.X86.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.ATL.X86.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.ATL.X86.base.vsix + sha256: 95aa47038defe7bf6804690637bf06a38afbc45c521ad38cd26ee3fd3f34133b + size: 819855 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/95aa47038defe7bf6804690637bf06a38afbc45c521ad38cd26ee3fd3f34133b/Microsoft.VC.14.38.17.8.ATL.X86.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.Headers + payloads: + - fileName: Microsoft.VisualCpp.MFC.Headers.vsix + sha256: 2b316d901c49e95b8b469cbc0b125c2ece35071e2a48b40eec16c6cf7755b175 + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/2b316d901c49e95b8b469cbc0b125c2ece35071e2a48b40eec16c6cf7755b175/Microsoft.VisualCpp.MFC.Headers.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.Headers.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.Headers.base.vsix + sha256: cfa5e09aab4cd6de86b89ebec78acc965180fcf665652b7678822c198a75dece + size: 2367924 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/cfa5e09aab4cd6de86b89ebec78acc965180fcf665652b7678822c198a75dece/Microsoft.VC.14.38.17.8.MFC.Headers.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.Servicing.MFC + payloads: + - fileName: Microsoft.VC.14.38.17.8.Servicing.MFC.vsix + sha256: 765bbbd571abb629543dfda31012143e40cb864203e08276e2a84ad5823ba8d3 + size: 1976 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/765bbbd571abb629543dfda31012143e40cb864203e08276e2a84ad5823ba8d3/Microsoft.VC.14.38.17.8.Servicing.MFC.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.MBCS + payloads: + - fileName: Microsoft.VisualCpp.MFC.MBCS.vsix + sha256: 6eb192460fdf0c78a06b0bbe8637a2387344a82db3c80a22aaf1f6374e71e2f6 + size: 1067 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/6eb192460fdf0c78a06b0bbe8637a2387344a82db3c80a22aaf1f6374e71e2f6/Microsoft.VisualCpp.MFC.MBCS.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.MBCS.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.MBCS.base.vsix + sha256: 4c5ccce71fb16ab49516231286f3da5be20083d842c69058a8c2800c7c84e341 + size: 27604114 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/4c5ccce71fb16ab49516231286f3da5be20083d842c69058a8c2800c7c84e341/Microsoft.VC.14.38.17.8.MFC.MBCS.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.MBCS.Debug.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.MBCS.Debug.base.vsix + sha256: 47490ac31a103d84a983daf763e40e9b0f51c8833592d2c24a49a7bbe6e4650d + size: 29750834 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/47490ac31a103d84a983daf763e40e9b0f51c8833592d2c24a49a7bbe6e4650d/Microsoft.VC.14.38.17.8.MFC.MBCS.Debug.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.MBCS.X64.Debug.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.MBCS.X64.Debug.base.vsix + sha256: 0ad474786014e89355d10fabfb25129835e9b729093263068c366e431c3269c4 + size: 33464075 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/0ad474786014e89355d10fabfb25129835e9b729093263068c366e431c3269c4/Microsoft.VC.14.38.17.8.MFC.MBCS.X64.Debug.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.MBCS.X64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.MBCS.X64.base.vsix + sha256: c28ffa4773805b27c4ee1fb60698ddf79ac26707c11ca13c98c11a8a5131ac24 + size: 30610725 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/c28ffa4773805b27c4ee1fb60698ddf79ac26707c11ca13c98c11a8a5131ac24/Microsoft.VC.14.38.17.8.MFC.MBCS.X64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.MBCS.X64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.MBCS.X64.vsix + sha256: f0a7144f72a223213924cf8fe1bed14eedc7961413b61f90098efee06919a928 + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/f0a7144f72a223213924cf8fe1bed14eedc7961413b61f90098efee06919a928/Microsoft.VisualCpp.MFC.MBCS.X64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.Redist.X64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.Redist.X64.vsix + sha256: 7b8c780ea74ef0aee4c73739dbff380250c7984852e8ed8cb2c20457d3e406c9 + size: 1073 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/7b8c780ea74ef0aee4c73739dbff380250c7984852e8ed8cb2c20457d3e406c9/Microsoft.VisualCpp.MFC.Redist.X64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.Redist.X64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.Redist.X64.base.vsix + sha256: 73cab73114336524666b538c651b3cf79a4d1da02b77d6bfb2dc184b2d665988 + size: 13809366 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/73cab73114336524666b538c651b3cf79a4d1da02b77d6bfb2dc184b2d665988/Microsoft.VC.14.38.17.8.MFC.Redist.X64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.Redist.X86 + payloads: + - fileName: Microsoft.VisualCpp.MFC.Redist.X86.vsix + sha256: 10df2818a89d121fb921d81834b8764c99a2ca505da78a06ace06c4c413c82e7 + size: 1073 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/10df2818a89d121fb921d81834b8764c99a2ca505da78a06ace06c4c413c82e7/Microsoft.VisualCpp.MFC.Redist.X86.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.Redist.X86.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.Redist.X86.base.vsix + sha256: c7ed3d46fbf65acafa5347edbf0571277395ec6a57c00a2c1182649cf722722c + size: 13290535 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/c7ed3d46fbf65acafa5347edbf0571277395ec6a57c00a2c1182649cf722722c/Microsoft.VC.14.38.17.8.MFC.Redist.X86.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.Source + payloads: + - fileName: Microsoft.VisualCpp.MFC.Source.vsix + sha256: 918eeb015a6f9d0032ba0a723e4e91c0b937f0df779664abcdfc5a85f6707f7a + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/918eeb015a6f9d0032ba0a723e4e91c0b937f0df779664abcdfc5a85f6707f7a/Microsoft.VisualCpp.MFC.Source.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.Source.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.Source.base.vsix + sha256: ae65c9a5c51d28f40acde3f95e566903ebd199e0a60a04a715c1c1620394fc34 + size: 2304582 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/ae65c9a5c51d28f40acde3f95e566903ebd199e0a60a04a715c1c1620394fc34/Microsoft.VC.14.38.17.8.MFC.Source.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.X64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.X64.vsix + sha256: 580e19f8442b3f550f37d6a3ea4355851dbbf034b02c801b1776f32d45b62962 + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/580e19f8442b3f550f37d6a3ea4355851dbbf034b02c801b1776f32d45b62962/Microsoft.VisualCpp.MFC.X64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.X64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.X64.base.vsix + sha256: 40a8f6bcf6146b62b69743ea184c4fa5ad86a4b780b41d8f687d940b47281444 + size: 33147515 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/40a8f6bcf6146b62b69743ea184c4fa5ad86a4b780b41d8f687d940b47281444/Microsoft.VC.14.38.17.8.MFC.X64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.X64.Debug.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.X64.Debug.base.vsix + sha256: 30536ca264dc6836a2911b9aed31b614d0739c98dab97ebb36f70f1cce3b985c + size: 35632802 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/30536ca264dc6836a2911b9aed31b614d0739c98dab97ebb36f70f1cce3b985c/Microsoft.VC.14.38.17.8.MFC.X64.Debug.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.X86 + payloads: + - fileName: Microsoft.VisualCpp.MFC.X86.vsix + sha256: 3f90b7461916e728d2e1b403ac4ca35aa7c96b339b32dbd5d0e34a24a62fa120 + size: 1068 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/3f90b7461916e728d2e1b403ac4ca35aa7c96b339b32dbd5d0e34a24a62fa120/Microsoft.VisualCpp.MFC.X86.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.X86.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.X86.base.vsix + sha256: a05ed24be7c1fd2c359f83cf40e18946e9407778cc413e2808c7ec9f17423c13 + size: 30255389 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/a05ed24be7c1fd2c359f83cf40e18946e9407778cc413e2808c7ec9f17423c13/Microsoft.VC.14.38.17.8.MFC.X86.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.X86.Debug.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.X86.Debug.base.vsix + sha256: 6b5b241f11261763bcbc822b7c5265c65385cbb5d6c88a0eab3f580087101ef6 + size: 32185940 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/6b5b241f11261763bcbc822b7c5265c65385cbb5d6c88a0eab3f580087101ef6/Microsoft.VC.14.38.17.8.MFC.X86.Debug.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.ARM64.vsix + sha256: c2b6f39c78b82a67e64bc1cf5aaad0711d13b1e5a9b96727f2aa42002e40b933 + size: 1069 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/c2b6f39c78b82a67e64bc1cf5aaad0711d13b1e5a9b96727f2aa42002e40b933/Microsoft.VisualCpp.MFC.ARM64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.ARM64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.ARM64.base.vsix + sha256: 03bfd6d226550c9a279f0605347f53db93ae8818e2c646a54d1d88458881644a + size: 72836942 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/03bfd6d226550c9a279f0605347f53db93ae8818e2c646a54d1d88458881644a/Microsoft.VC.14.38.17.8.MFC.ARM64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.ARM64.Debug.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.ARM64.Debug.base.vsix + sha256: 6365314c3b2ea5e291f450c025ff256351754780782586660f1d41520e089017 + size: 77680874 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/6365314c3b2ea5e291f450c025ff256351754780782586660f1d41520e089017/Microsoft.VC.14.38.17.8.MFC.ARM64.Debug.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.MBCS.arm64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.MBCS.arm64.vsix + sha256: a25949d36cbbd7a66966417cd2056c1d4938f1c1744c05f90a6dd7af0e21f490 + size: 1072 + url: https://download.visualstudio.microsoft.com/download/pr/a1a6b2f9-265a-407c-bb15-ddd8d5a802f4/a25949d36cbbd7a66966417cd2056c1d4938f1c1744c05f90a6dd7af0e21f490/Microsoft.VisualCpp.MFC.MBCS.arm64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.MBCS.arm64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.MBCS.arm64.base.vsix + sha256: e281a38207a0b1a9430e8761bebffbd8b99b11518dba3a0cd6bc9357f87d6bf2 + size: 67964584 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/e281a38207a0b1a9430e8761bebffbd8b99b11518dba3a0cd6bc9357f87d6bf2/Microsoft.VC.14.38.17.8.MFC.MBCS.arm64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.MBCS.arm64.Debug.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.MBCS.arm64.Debug.base.vsix + sha256: 65db122886a39e6554cf5372f699cbf41f3f8e9167c942cac7bdda59b3cb1267 + size: 73670936 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/65db122886a39e6554cf5372f699cbf41f3f8e9167c942cac7bdda59b3cb1267/Microsoft.VC.14.38.17.8.MFC.MBCS.arm64.Debug.base.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VisualCpp.MFC.Redist.ARM64 + payloads: + - fileName: Microsoft.VisualCpp.MFC.Redist.ARM64.vsix + sha256: 2c61b6ec42f80ec5dfbc581982de0720b1744362ba3da6d35e958e15ecc896ee + size: 1075 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/2c61b6ec42f80ec5dfbc581982de0720b1744362ba3da6d35e958e15ecc896ee/Microsoft.VisualCpp.MFC.Redist.ARM64.vsix + type: Vsix + version: 14.38.33130 +- id: Microsoft.VC.14.38.17.8.MFC.Redist.ARM64.base + payloads: + - fileName: Microsoft.VC.14.38.17.8.MFC.Redist.ARM64.base.vsix + sha256: d5871d9597312fcd26e539c0cae98094f3d31069bdf3be9cb88ce7b1fc6fa6d3 + size: 22833274 + url: https://download.visualstudio.microsoft.com/download/pr/4276ad73-5c96-443c-be24-4ecb1784abb4/d5871d9597312fcd26e539c0cae98094f3d31069bdf3be9cb88ce7b1fc6fa6d3/Microsoft.VC.14.38.17.8.MFC.Redist.ARM64.base.vsix + type: Vsix + version: 14.38.33130 +- id: Win11SDK_10.0.22621 + payloads: + - fileName: Installers\03fbc2dfe9d3e7bb2389c7ed18c6ad3e.cab + sha256: E80FE2BC3F0195CAB934A5F02817E363BCFD437443FD6BF944CFD1433AA93686 + size: 748915 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/28cb4dc8b92b480a9a37da29897b3ce7/03fbc2dfe9d3e7bb2389c7ed18c6ad3e.cab + - fileName: Installers\05047a45609f311645eebcac2739fc4c.cab + sha256: 3491F8245B508D4687FF9CB045389D5C0EE36A21CCA1403D868A149F504FA226 + size: 249918 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/bd7f4827b5b6f9c3521ed71c64a12e88/05047a45609f311645eebcac2739fc4c.cab + - fileName: Installers\05254f60ea43b4e3959b17cdb03268c0.cab + sha256: BBDAAB9CB80ED70016692A0DF21A4F24BF9FF2BBD051CCC5AAC65F9D3CC0D377 + size: 674457 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b545cc15ac6e56d21510fc01d196c822/05254f60ea43b4e3959b17cdb03268c0.cab + - fileName: Installers\07a57cdb41ba28cced14005f087267be.cab + sha256: 37F93B7000EFB043F5EE0345EBE11B09DCFFC8B8E881FC2605E06D9A45F239DF + size: 101620 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/24e3b52538c0f89961883edce50aaaeb/07a57cdb41ba28cced14005f087267be.cab + - fileName: Installers\08e9468089f54c8455f59fd9bb48fcec.cab + sha256: 27EDE731B714D17C48D792A93A2B2E8006918DBFDBFFE230DE5CF07C531F9E3B + size: 71218 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e25a00d814767a60cd5d5b27584049d9/08e9468089f54c8455f59fd9bb48fcec.cab + - fileName: Installers\0b2a4987421d95d0cb37640889aa9e9b.cab + sha256: 022A1DD7E7870DCA5F0693469B3AAB4C6B1A502D618811E3BEB51028A17D6896 + size: 234756 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c415148487fd8f471a72156cad633f2f/0b2a4987421d95d0cb37640889aa9e9b.cab + - fileName: Installers\12613ba26e037e99a874a64c1084f880.cab + sha256: B6B85261EB8B087C7B88B32A25CBE62CAA29E00406E0B9D0590EE6B67C35366B + size: 572567 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b3194651df3bf081ab18e58f63a0c8fb/12613ba26e037e99a874a64c1084f880.cab + - fileName: Installers\126c039acc6f1c0a9426a128efb713e7.cab + sha256: FEF94D5842E04BB75C843BF065AE182243620D5012A875B32142EAED252FF88D + size: 1560592 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/adc6814856be6b78efdec2a044fab27e/126c039acc6f1c0a9426a128efb713e7.cab + - fileName: Installers\12a529d45b148a2d28290a8a7535b37b.cab + sha256: 9806E59A0EBC3811BD84E9BDBCC511866BCE6F222F9FC09F835C2419DC44AFA2 + size: 1056462 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8b18dfb2c53c9c625cc633cf3442d034/12a529d45b148a2d28290a8a7535b37b.cab + - fileName: Installers\13bf5f9b75a9d1c9f44ba5d34a14227f.cab + sha256: B8DDEFC2DED28EE8EF6862BD74808D144125FE2C26D5186CC3684FBF73C63442 + size: 93302 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b2225488d971d7424bb7d5587c984c12/13bf5f9b75a9d1c9f44ba5d34a14227f.cab + - fileName: Installers\13d68b8a7b6678a368e2d13ff4027521.cab + sha256: E63A66F86A4EF951BAE7A5C3DB7B692BA51708899EB9525E0AB7D219B7EF5BEC + size: 431525 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2246b25d698e1aee2d11edd63d5dd31c/13d68b8a7b6678a368e2d13ff4027521.cab + - fileName: Installers\15bc5316e373960d82abc253bceaa25d.cab + sha256: A9EC7853D9BBB546C46AF522657932FDD71FA56D6877F951003BDB4274A0D2C9 + size: 35528 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/15c7245267c0d3fecde82410543ebb1c/15bc5316e373960d82abc253bceaa25d.cab + - fileName: Installers\1623efce9d1a46396798f44a7bc769e9.cab + sha256: 174EDBBDDFE95A274E6FF77BC4888D99F825E4BDA1E52D8EE81B584297062A3B + size: 447540 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/58992fa1f475e0bdb067db1659f2e1f7/1623efce9d1a46396798f44a7bc769e9.cab + - fileName: Installers\16ab2ea2187acffa6435e334796c8c89.cab + sha256: 5FE487EC589721B43A44672566FC20693611AAEBD33FE08F3BF1E724E48145B0 + size: 674566 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d4ebcf4f2faed895a5e17ff6acf99dd0/16ab2ea2187acffa6435e334796c8c89.cab + - fileName: Installers\19248fabbb2098a7b88c4a2786066bcc.cab + sha256: 59175473F59D05799B60D645F039E16FE10A51909A0CA21E1DDCA18C3A3E134C + size: 783251 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4f0a864616277de959ea3518249bbdb1/19248fabbb2098a7b88c4a2786066bcc.cab + - fileName: Installers\1a296530f0182ff1e94f088c27d05da0.cab + sha256: F063FF4896788A6A1CD5DB66C3A92930F78875F7723147F17244151A036553EC + size: 16592 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6de7a8c632c6cf4f3a1b9386b634772c/1a296530f0182ff1e94f088c27d05da0.cab + - fileName: Installers\1de82860db02f762c5f65a73daa31f3e.cab + sha256: DD6DF8774F5D04F77E2F87A17EAFE20FF8176814AC67D6F276E4EED3BB40A881 + size: 14057309 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f6cab5967d3ccc76c9d8f490e68f1ed8/1de82860db02f762c5f65a73daa31f3e.cab + - fileName: Installers\1f32e9acf0bb1e6a5f485cd8670cd8e1.cab + sha256: 1A279E789D3FD21DDB293E0844C0C0FA2554C2A536E33C7D4BAD437B5DB9D840 + size: 19961 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/517a77e5591e5699fc9ed65b2f8e200e/1f32e9acf0bb1e6a5f485cd8670cd8e1.cab + - fileName: Installers\20e79882c0bf37840a94a4ce06bc571e.cab + sha256: 8F167787DFBB605BC9DEB8D08B7D6F400FC82C812B17E6F0C73006615113B537 + size: 1861857 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9f21998fce220490db5eda3144743a81/20e79882c0bf37840a94a4ce06bc571e.cab + - fileName: Installers\220daf459e79c5d26366654b1b482e87.cab + sha256: 8FF1921F43F1BE6D118114FB22FFCE51A19E13438D14FDF86D5789B4ED5EFF41 + size: 95427 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/07111d0e7c11cd3b050f5634a3be6b51/220daf459e79c5d26366654b1b482e87.cab + - fileName: Installers\262fa3187c00a1f695e0c3eeb7ecf423.cab + sha256: DB4DD0B6B003DC725D1172AFA46DAB2FC54F565F64A5C139ADB2BAEA9EE252DD + size: 1604340 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2b1c1ea142c8ff1b73558ebda4f9c870/262fa3187c00a1f695e0c3eeb7ecf423.cab + - fileName: Installers\2630bae9681db6a9f6722366f47d055c.cab + sha256: 719A35EFC8BEC1BCB44A3C0A146627F2014E9FDAB39DB9CD55E4E2EDE76C5F2E + size: 7652264 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8dc8ec4064668a6e97fdcd1e68f65d05/2630bae9681db6a9f6722366f47d055c.cab + - fileName: Installers\263104e5ce3a72f68151a93d88a3f22f.cab + sha256: 5E41CAF59072398D215897A1DA7D91BA9081649A22A9B27B9C136EC458AA9805 + size: 17150 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/317bba1fb0a160360c287b127bda1803/263104e5ce3a72f68151a93d88a3f22f.cab + - fileName: Installers\26ea25236f12b23db661acf268a70cfa.cab + sha256: D4B88A41529DC2D583D958647E69DC06A20B4C8CA669DCFF07D51103D0799663 + size: 94277 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f2a697ea7efbbc22b4db5fef339ed4fe/26ea25236f12b23db661acf268a70cfa.cab + - fileName: Installers\2868a02217691d527e42fe0520627bfa.cab + sha256: 7A7C757C4456CD40DF0994ABA45EEAA9BF2DE0514C567643C923D903E56826A1 + size: 572524 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5a3ae37ac780649439ccb079e6d4c237/2868a02217691d527e42fe0520627bfa.cab + - fileName: Installers\2a30b5d1115d515c6ddd8cd6b5173835.cab + sha256: ABFC6930CB4B27E3ECB11E23EAEE4EA0EE12C74D5B8F573FA0F996EFC5998295 + size: 94465 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/fe29f52f656b2489715f7d5822737538/2a30b5d1115d515c6ddd8cd6b5173835.cab + - fileName: Installers\2cd67f5657d2cee1a106c4fdab506e58.cab + sha256: F6A424C0AFE38485FEABEAE9A6FBCD4DB6DAA87E8F2807FC5D7B5EF818EEAA9D + size: 241101 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/06965a9fccb17cc1711ac9cc7aea640b/2cd67f5657d2cee1a106c4fdab506e58.cab + - fileName: Installers\2dd914bb5abd9365f932d15eede09c52.cab + sha256: F7E3ADC242FEC800F78BF1D4D546C38C6151284F037C0073B92FAD140E24E5EC + size: 1344576 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5dd8d8e510c7dee7136e04ff703f6b4b/2dd914bb5abd9365f932d15eede09c52.cab + - fileName: Installers\2e876dd22fa5e6785f137e3422dd50ec.cab + sha256: 665E734E8572FEF90FA3552B01BF63472AB9A79522C090BE264F81DA4CBC13BC + size: 9189274 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/a604eacbb200a14f3dc81f6245a58a23/2e876dd22fa5e6785f137e3422dd50ec.cab + - fileName: Installers\306e26e920fd32cb02bf538b4e799a0d.cab + sha256: BC1AF34BD20716A5527E3B4C1F195182A9FF25F0D6D9204EA3504CCBC0947969 + size: 166334 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/065fed871641b1a9821593f6d8bcb852/306e26e920fd32cb02bf538b4e799a0d.cab + - fileName: Installers\31ec2a68a04d58dc4a3d639fddc68493.cab + sha256: 63EB9A31DF4BF703F406630BF54C499CB0354749553BF2E6FF5544A9B87D8A99 + size: 232596 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/772b0e7aa821f22d2c3e1019b212876a/31ec2a68a04d58dc4a3d639fddc68493.cab + - fileName: Installers\353be8f91891a6a5761b9ac157fa2ff1.cab + sha256: 17B13E211442D117A1A0020703710282FD0272B32C096B8302DDCC4828893613 + size: 65912 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c38385a814f8ce1cd5da26fed2b644e6/353be8f91891a6a5761b9ac157fa2ff1.cab + - fileName: Installers\3988e4dfdc3f1d180c47a61a0ca76215.cab + sha256: 517BAD1B53E1815652BF529046C9A60440F04E02437BF0D16F4A9A6B52CFE02D + size: 926997 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/80f0ce8bd39dd50d288a0c78ee644e13/3988e4dfdc3f1d180c47a61a0ca76215.cab + - fileName: Installers\3cf96a08c3b29e9dcf5946d28affb747.cab + sha256: 7134D513B35D3B7E817D888E46908B90DB6EDA8998AC783BDF8AB79EF31C24E4 + size: 106386 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/34ef4d53dcd30003d0c6d2134c4ab30e/3cf96a08c3b29e9dcf5946d28affb747.cab + - fileName: Installers\3e2f7be479e3679d700ce0782e4cc318.cab + sha256: 8C951D2667862F6AB15C245B9F728D02C3F30C5515A4FD296BFC6C0D97D0B629 + size: 33999186 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8f1d8978d12e53f1169dd6e3f6118bfb/3e2f7be479e3679d700ce0782e4cc318.cab + - fileName: Installers\4035a83dc8e73244d15d1196d55059c3.cab + sha256: CC10546ED0250BC4306C1D18B35DFA285EC1BF198BB0AD62756CD5B46CC3F2D2 + size: 17470 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6ec32ff9c15209d614a9d2ad4ddd9281/4035a83dc8e73244d15d1196d55059c3.cab + - fileName: Installers\40d92f424eff54b03db4c51669f9a8d6.cab + sha256: E03EAC70EA166FD5BC12CBA5D6A9E4E32CC5D3C106763735363F1B0C55D6CBD8 + size: 182007 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c4c444ec79cbc1de70a06ca28fe45d70/40d92f424eff54b03db4c51669f9a8d6.cab + - fileName: Installers\43cc1b2daf931a3f0ea4ad696c2327fb.cab + sha256: 17526BC401DCC584E53099734C554A922013CCA9FB8D099C0F6564FA0000F7F0 + size: 20414 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6bea82084aaa507046c4fdd46f475b96/43cc1b2daf931a3f0ea4ad696c2327fb.cab + - fileName: Installers\43d52fdb99b86048e15fbd34f5b99cb5.cab + sha256: BEB7950648E542A684145D4884D66B585DD48B7F25A0BC44CCFF53D061B2FE6F + size: 251080 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/49b00906989129523cde0872cf7aadd4/43d52fdb99b86048e15fbd34f5b99cb5.cab + - fileName: Installers\441901505fcd0b2e997ea7d954f04171.cab + sha256: F83DA1E9FB8A42C5C93814C55F549ABA2AD40C4B3C03649D973990BFC1DEA4B2 + size: 19378 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f55607885fc96ad03b2b9f7ec65ede82/441901505fcd0b2e997ea7d954f04171.cab + - fileName: Installers\44472e2321abba45e828de25827264a3.cab + sha256: B54377FD3FB988250D711A7DC765526A912638187C3DB31ACC09681A39E37EFA + size: 21125 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1049e1d87c9878070f72797205abe406/44472e2321abba45e828de25827264a3.cab + - fileName: Installers\45821d1fcb842bff411f5f2f8c1d4106.cab + sha256: 3087D46DD7A790B3B0BEEF22CB19FCB0812906D975FADFE8157A1717B8B6FC83 + size: 17236 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/00e531dfda28b2dee63d24620adcd3a1/45821d1fcb842bff411f5f2f8c1d4106.cab + - fileName: Installers\463ad1b0783ebda908fd6c16a4abfe93.cab + sha256: 7DD9C80AD7318C411C7B14B3EC5A181B43DBADE66618BB981F41B88C719B951E + size: 235506 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f6c8493226842545d573dfae1e7db50b/463ad1b0783ebda908fd6c16a4abfe93.cab + - fileName: Installers\47133212c2f5ccf49392d7762293a075.cab + sha256: 097B1A18475F575F391F5E7402A8659F1946F9ECD4A84BD2E7CBE15A3EADE795 + size: 1630585 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0a83146315543d7552ee23146a853b62/47133212c2f5ccf49392d7762293a075.cab + - fileName: Installers\4a4c678668584fc994ead5b99ccf7f03.cab + sha256: D540BAF43C53A80249D96DAD3082B3B84ADEFC5CBF04C12BF8FCB7BA2ECB03AF + size: 416624 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/62e8bebc38adf28d4a2c37ebf4f69316/4a4c678668584fc994ead5b99ccf7f03.cab + - fileName: Installers\4ad4df991deb0eaa1f79f896b959d580.cab + sha256: 5C247DEF0AB72C56306279FB810A37078B17F4366CACBB2495BBBBCB3153F97D + size: 1544931 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/09792294d8934a324cc4b4489346889c/4ad4df991deb0eaa1f79f896b959d580.cab + - fileName: Installers\4c3ef4b2b1dc72149f979f4243d2accf.cab + sha256: 431E3702487C422FEAC14B2F13C9738C7E089701DE377B0523793D8B95226B78 + size: 424740 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/dab904b04f91d050917a8d236e83cc4b/4c3ef4b2b1dc72149f979f4243d2accf.cab + - fileName: Installers\4c59234340aaf3a96ec480c1aad8d179.cab + sha256: DE3BC99D7BEC62BA742F41B24EE8120997F2023EB784B2DC14D477704A5EC1C5 + size: 606218 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5a332e9c92a855e2b68e213a6a96e13c/4c59234340aaf3a96ec480c1aad8d179.cab + - fileName: Installers\4dc69cc131b3f4fdde53e76d759509dc.cab + sha256: 552DE8F166727D129D25745484E9C28A0E5B0E0338D837AC65028BE23921DD8A + size: 460099 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/74178eeedfaf5553a93f7c40caf65643/4dc69cc131b3f4fdde53e76d759509dc.cab + - fileName: Installers\4e2dea081242e821596b58b31bc22cca.cab + sha256: 14E485C54FDDD5EB5E264570F87D42FED82BA9D21523E063D963B996772D4FF3 + size: 16706 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5fe1d2d4549ce4dfd9b744a6d2b701c1/4e2dea081242e821596b58b31bc22cca.cab + - fileName: Installers\4ec14c5368b7642563c070cd168960a8.cab + sha256: 256259FAB272E1A9022958781E3C82ECC2F1661EE84B3CFCFE2B00FE014BA25D + size: 1858316 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/103120b734595b48001107183ff13025/4ec14c5368b7642563c070cd168960a8.cab + - fileName: Installers\4fe4c8b88812f5339018c0eef95acdb9.cab + sha256: 1E1DCDB169618EAED620849589F6EA23E0EBC306EA083FCD52F2380CADC6E384 + size: 1183160 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0c5d201dd37d5678198e66d8b1dd7912/4fe4c8b88812f5339018c0eef95acdb9.cab + - fileName: Installers\50ce7925226cb6ab8e0fe9ad9fd58433.cab + sha256: F05FD8AA9AE6D9742855952C7300C92AE9254F44BA31F43F3174B152B2490D80 + size: 7261917 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f063b0320354b984cbe74a46f0d074de/50ce7925226cb6ab8e0fe9ad9fd58433.cab + - fileName: Installers\52a8e5203ade8fe7174c590308f2e44a.cab + sha256: 950F63C89C0788C381555C25E772D680A970A6B44A868EDE2A56F1988C6F3E55 + size: 464540 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b9adab4339ba412043ae0447d4d77caf/52a8e5203ade8fe7174c590308f2e44a.cab + - fileName: Installers\53174a8154da07099db041b9caffeaee.cab + sha256: 9C85E5886113DD7BB6DAA5494EA2C4E94ABBB8AF70D87547AF1BD2CA91026B1A + size: 16316331 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/3dc632edd3cd805bc990f2e0f359b291/53174a8154da07099db041b9caffeaee.cab + - fileName: Installers\5509e4710313421be8d5e7cfbfde4d30.cab + sha256: 164236ABA8EBDB047621F8F9EF51E55343FBCB41FC07F56E0EFE91EDF63CDD38 + size: 1037932 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/7550ccbdc8265e81fdcc3162576cd750/5509e4710313421be8d5e7cfbfde4d30.cab + - fileName: Installers\559dbc3a49a69c6adf60b1c87b4df71b.cab + sha256: 0A3A31648A5850AA2A93FDE742AA3E21970430EFD0470C331C7794C5563C34BE + size: 16567 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5fda28d1f53bdeced0c405b5f82ed5a5/559dbc3a49a69c6adf60b1c87b4df71b.cab + - fileName: Installers\563138901adf40a699df4654138ac397.cab + sha256: 5036CCE4BC5B3F8C8250C66EC9E952156C00FC0E7A9307A0AEAD76F00525F6F8 + size: 1432328 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/13b8150ffbe8df66f2e997bc2585d766/563138901adf40a699df4654138ac397.cab + - fileName: Installers\56a114848fda9a7e47bad4b3fc4be9a6.cab + sha256: 28FD98D60E74A7E628E303112E56B83D432BD744775BAC0044E4C8E6F4EC283C + size: 7953654 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1dc711e686fae088f6e3b94d1cf54074/56a114848fda9a7e47bad4b3fc4be9a6.cab + - fileName: Installers\576cff9c50e8085ab8d9c28ee12bac3e.cab + sha256: 86E71592F874AC0CC3374273B2717821D25345AC9A5BE18718D9C424320BFD69 + size: 674368 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/14ee753146e892862fc3dbc4509e7e48/576cff9c50e8085ab8d9c28ee12bac3e.cab + - fileName: Installers\58314d0646d7e1a25e97c902166c3155.cab + sha256: 155428ADF19FA1AE3E78A02ABF5AD28B84DCFE464E84890CB38EE969F6155BA3 + size: 18247681 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2d351174dd939fc81fc3f111924031d0/58314d0646d7e1a25e97c902166c3155.cab + - fileName: Installers\590d28783ff280b8b0016c3492433241.cab + sha256: 6F5952FB4ECB211CDC71F7B455E5A5FE5DE05BAA43AA17206F785C3AAB17B31F + size: 8855682 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d0475d22968de0f5bb39b964de85df8e/590d28783ff280b8b0016c3492433241.cab + - fileName: Installers\598442d9f84639d200d4f3af477da95c.cab + sha256: 25CCFC0EDC6C1B6CE7FCA0ACC4478FA1BCDB38521413ED87517E691F5B275E7A + size: 57100 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c2b862bab1e7d7d8068a1810c1049fc2/598442d9f84639d200d4f3af477da95c.cab + - fileName: Installers\5a22e5cde814b041749fb271547f4dd5.cab + sha256: 94EA13E1DC6745F585EDAB60525EC1D5540EBEA59BEC9988FAA35EFAC4F11417 + size: 14883042 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/3f184c7a6671f63b69884b5267bffd32/5a22e5cde814b041749fb271547f4dd5.cab + - fileName: Installers\5c2fcb46e03eada0ed0cad44a3f5c71f.cab + sha256: A13A1DFD92FEACDB417DD39AEC50690C1477251AF028DB06DDAAE504096D9EA2 + size: 16493 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/90ec500a61eed11cd08212972839d8da/5c2fcb46e03eada0ed0cad44a3f5c71f.cab + - fileName: Installers\5c9ecffb06ed5f4fe5fb7db86bf7328b.cab + sha256: C307A1F904EEF779CDE2283E63A1136111F6A25163DDD9A59098C628E05BFD4B + size: 365226 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/69db42ab442c4ea1f447a6a477395a32/5c9ecffb06ed5f4fe5fb7db86bf7328b.cab + - fileName: Installers\5cf1d61a223a02ff2f52fe05f058d52e.cab + sha256: FD18447890393A2A8ECF815212816A289A052BE71E2F48A10FBE50AB6D339363 + size: 1245019 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/30adc501871e25d527cc3ae69abb2a97/5cf1d61a223a02ff2f52fe05f058d52e.cab + - fileName: Installers\5f6cfec263cd265cf3b0d97fd78ddf05.cab + sha256: A6A4BEAA2825B9B51041B922E6143D649EBA492A3143281094609B5BCF53BDA0 + size: 3098064 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/48521844a29173d49899051e13e03c5a/5f6cfec263cd265cf3b0d97fd78ddf05.cab + - fileName: Installers\61d57a7a82309cd161a854a6f4619e52.cab + sha256: B974E0C9CD037E2722B12E970B68D76E3D1F9D90DBB8E81903666B66CEFC40F0 + size: 9682522 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/41b99f83468e63e55082431776320a6a/61d57a7a82309cd161a854a6f4619e52.cab + - fileName: Installers\66c7c64126fbf84f47ccec556d149b12.cab + sha256: BF66AA7A3483E14D60E7CC5AA4980090D1D70103364D3F1DB61A719B199E0C4A + size: 16924 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d895d31b6ac030ed00959feda7c19456/66c7c64126fbf84f47ccec556d149b12.cab + - fileName: Installers\67c9fd1fab36154e6e7e429610cd67c8.cab + sha256: 15D3E48A58F7481A91331DBA9E642F0D46A4DBF445E3F5390BCC302A6198AEC1 + size: 766910 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c274d5d104845cddbabe35ee2fc60f32/67c9fd1fab36154e6e7e429610cd67c8.cab + - fileName: Installers\67fb2af3d2219b403e419535a547c019.cab + sha256: 8E11FAB52630EAF26E04E0FD330914ACFDAB875C8CD7E8D4A2176BA170F4D676 + size: 97375 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/56276abb011fb7f9ad26761b78e6d246/67fb2af3d2219b403e419535a547c019.cab + - fileName: Installers\685f3d4691f444bc382762d603a99afc.cab + sha256: D730FD3A0986F2A5E737622429E4E2FE4EC5AB68B3CA04FF5DA251CD0E05B58C + size: 1055229 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c911ed0c9541f65557474303c0cd8cfc/685f3d4691f444bc382762d603a99afc.cab + - fileName: Installers\68a5a2b14625f935761325cddfadca11.cab + sha256: 6B67CBF2E9FBC20B44C670626BFE243E2220BA42314A1B2B016E531A02894E33 + size: 2286402 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4bf72d5f2e84895c5ee6d7380147c2e3/68a5a2b14625f935761325cddfadca11.cab + - fileName: Installers\68de71e3e2fb9941ee5b7c77500c0508.cab + sha256: A3011763D1538707AC22EC7D0EABAA691F5029547114882A627C30C7CDB1A340 + size: 17354985 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ca4d24255305019005fad727a6334086/68de71e3e2fb9941ee5b7c77500c0508.cab + - fileName: Installers\69661e20556b3ca9456b946c2c881ddd.cab + sha256: EE19778F3B0D943D1D18A33D03EC26F2EFE0D4E3BB5CE91C2D10E810F4392F80 + size: 21082620 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/36b6c5488d0c568b743ac806fd533be4/69661e20556b3ca9456b946c2c881ddd.cab + - fileName: Installers\6b12414fdb1b4978419abcd383206c09.cab + sha256: DEE92DADF56264E511AE99E4B73C113D1B4525F8EC8094B843436657E4A9808B + size: 16483 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2d6afb072112953f40a15aa502ff77ef/6b12414fdb1b4978419abcd383206c09.cab + - fileName: Installers\6b5a91701fdb98ac8bc4af6e238e0390.cab + sha256: 27C13153DAD440E66E2DC4721E746F00294047962031EF37A999D3D44AF65026 + size: 1970595 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/487344da38bdaeec1c1476d294c013b4/6b5a91701fdb98ac8bc4af6e238e0390.cab + - fileName: Installers\6e86d5003787b5a44d77f0142b20f2ff.cab + sha256: 695AAA1B4CFF419292B2090711A35C2E55171A94E8918BD5BBAB8A80C8D6563B + size: 102293 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/eaac0661e4d03c2b8dbeb40641bf1224/6e86d5003787b5a44d77f0142b20f2ff.cab + - fileName: Installers\6ee7bbee8435130a869cf971694fd9e2.cab + sha256: 0B119281363BF4018E71D81B7D71202AE20D183FF11AADDD274ED0E9E84F55BA + size: 24939245 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d3878db54d50cf0965f32ec5e20cbeac/6ee7bbee8435130a869cf971694fd9e2.cab + - fileName: Installers\703316c9de0a32acf316d03b1cffc559.cab + sha256: B90F62A031D9CE6ADB002F57236EBB505953455A3167715A4B0875BDF91E1BB2 + size: 16181033 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b9b6f1318c2db5d4e9e7b839294cf850/703316c9de0a32acf316d03b1cffc559.cab + - fileName: Installers\73b80f421d7f3df5a71bd772f56bf3ae.cab + sha256: 495871A0BF0E9434C8BF38E46622340DC67A3DE030460434C2601CA872C2E657 + size: 96177 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/873851306e48431f00f187237b909e18/73b80f421d7f3df5a71bd772f56bf3ae.cab + - fileName: Installers\75122a9de1700f465c29b6cc76fa6372.cab + sha256: 43A90263B666CFA788468607D20AE386C340CA70A77876250866D3BC09986DCD + size: 16627 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b8593824468c1ba0fe74e60ac857253f/75122a9de1700f465c29b6cc76fa6372.cab + - fileName: Installers\766c0ffd568bbb31bf7fb6793383e24a.cab + sha256: AB6FAE79D3749E8013E18F5BBF220B0661EA779419FFA20A56872A4FE82636CD + size: 7912974 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9dc20255a416316887dd957088e04818/766c0ffd568bbb31bf7fb6793383e24a.cab + - fileName: Installers\77db8ab55a0b236db83c55ced6e8a9a3.cab + sha256: EBA14925A45FB04FFC23D3F44392E11979DB813D10DBB7BFFFF9CAE36C80EA13 + size: 16620717 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/95924bfb62775c64a0221e3ebaeb5c8a/77db8ab55a0b236db83c55ced6e8a9a3.cab + - fileName: Installers\78fa3c824c2c48bd4a49ab5969adaaf7.cab + sha256: 0ABC373CE1E43747A259522AD2963E8E5383216D5B98F9FEEDDA3B720D8EF0D8 + size: 52185986 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/28898ada97043a50d887aa0f92641db1/78fa3c824c2c48bd4a49ab5969adaaf7.cab + - fileName: Installers\7afc7b670accd8e3cc94cfffd516f5cb.cab + sha256: 0E9BDEBF58C5514CE97CB1C8B7593D8BAB19B11A1DA6BF62A21CC746CC64B7D4 + size: 1056323 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b8d078b63f9bcb79b39d77ff60122bd6/7afc7b670accd8e3cc94cfffd516f5cb.cab + - fileName: Installers\7b7c7382fe1ea268787e911da88eb37e.cab + sha256: 0BC0AF0EE7A93DF1DBF6E266EEF432D833F7AB0D7179B9FE68613835C3E14468 + size: 151127 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/80a6d726369162379c134d3170bb74d8/7b7c7382fe1ea268787e911da88eb37e.cab + - fileName: Installers\7c3667a45d36470bf3cb648878a6ac2e.cab + sha256: 1A27BCE8FE7ABB778D090516392D338C1BA93A06DBC768E2C4271D0A568B1DFC + size: 774389 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/3c4f73355554f0c18bdfe25cdefaa4ed/7c3667a45d36470bf3cb648878a6ac2e.cab + - fileName: Installers\8016f7584c8fbeff0b032c65f4173e78.cab + sha256: A0DC88523C82BD240F2CDE6ED1085514B3C1F9976503902BAA7BF83BBC3E1D5B + size: 39055 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/248c1e7a894288ed016a52d47e4d98e5/8016f7584c8fbeff0b032c65f4173e78.cab + - fileName: Installers\8038f3cc95dc4b7d0346cb2ab7e044ff.cab + sha256: 001F52848F273D65F0D5AD7E776A85F71BE44749DFCC9E99104A55670F38A038 + size: 1056329 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2a6f6fca08298a0897da1363f1138651/8038f3cc95dc4b7d0346cb2ab7e044ff.cab + - fileName: Installers\80dcdb79b8a5960a384abe5a217a7e3a.cab + sha256: 3EB08A2A381446D9F8AD0B68D473ED1CD3D13CFEEE7519987786717EB80AB29B + size: 25576652 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f00d572625a7dfce893e079463406677/80dcdb79b8a5960a384abe5a217a7e3a.cab + - fileName: Installers\8125ee239710f33ea485965f76fae646.cab + sha256: DBA6E86F53BF6427B79A836A41632E430649DF7FABC3AD70140A2FEC382615AF + size: 5705341 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1ab6034ea3c50dff97c46fb76058e695/8125ee239710f33ea485965f76fae646.cab + - fileName: Installers\818d2d3634f0efb6e64d7e7c8ca5f98b.cab + sha256: DC576E491CE149C81810AABAA9272F4E811EF4A5E6665AE7166058E823FBCA07 + size: 111679 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/cb14b2c6af40a0d2c9f5ae073daac06f/818d2d3634f0efb6e64d7e7c8ca5f98b.cab + - fileName: Installers\838060235bcd28bf40ef7532c50ee032.cab + sha256: 67823CB153BB75122A366FA3A1C8020A66BFDB2F1B30723172EE6D0E756C98FE + size: 17131 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e9b55caf9bf3facda5011d2b193d1952/838060235bcd28bf40ef7532c50ee032.cab + - fileName: Installers\89d9bbd87f7a5560bafa520a4ebfdf17.cab + sha256: 161C10EA0CACF07642820D92C582AD05E1D5F89147A57D6720FA3E241D96C51F + size: 89461 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e99df4a453862f14a61a2dcc23264e69/89d9bbd87f7a5560bafa520a4ebfdf17.cab + - fileName: Installers\8c44e508e7582f9362c66a2e47a19b5e.cab + sha256: D170800B288370D980388A305E980A6123AAD22DD878D1CACEDADB030D4CC871 + size: 41190 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/48d936010291c8131a6017ccf71de547/8c44e508e7582f9362c66a2e47a19b5e.cab + - fileName: Installers\8ce0662e0e014576121e526f53d8f6b5.cab + sha256: 03B4472A25AB874EF61AD41DA63510A437A370D210E84AF50D09FE1047A2548D + size: 409599 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/3b48f35dac0477822a5d5aefb6eecdbe/8ce0662e0e014576121e526f53d8f6b5.cab + - fileName: Installers\8da73ae89e24f0b5cdf1787799c2a65f.cab + sha256: CBC19B7786F87E22C8BF8B93770D8876BD36634DDB420177EC3CA71F9BE63C14 + size: 1501954 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/eff3447076aa18e5c04a79f04fb5784b/8da73ae89e24f0b5cdf1787799c2a65f.cab + - fileName: Installers\8daf1f236e631041cdaa802ddb9ccc3d.cab + sha256: D9554D0B075A405920969FFC18576AFF820C7BF95A203DEC59685252048B203E + size: 107411 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/dc3fbdd73c1dcba72d18d9f9195bc9c1/8daf1f236e631041cdaa802ddb9ccc3d.cab + - fileName: Installers\8e4755178e6b5bcba8d3538c3630b7a5.cab + sha256: EFC5E8AD7EB0638CE00C534D4B4AEF35445DAB4D31A9B549087C5764DB864D57 + size: 1121051 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b1763bac80ab258481e9298ec75507b2/8e4755178e6b5bcba8d3538c3630b7a5.cab + - fileName: Installers\8eec88833ea319aaa1061d6528c77b93.cab + sha256: E34A5C37DA16021083644EEA90679271F93311DE8807337878C1200047046610 + size: 180202 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1cfca8a04a06ee19429dfd3205b08fd0/8eec88833ea319aaa1061d6528c77b93.cab + - fileName: Installers\8fe3c1ca244ece932599eb0b61855d8f.cab + sha256: 7024DB8FBEA0A3EAA9CA0B4655DCE50B759BFFB2ED6152F7A3513FC222F9A219 + size: 93214 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/cb1a3801b4827e59ad90821ab1e1bf77/8fe3c1ca244ece932599eb0b61855d8f.cab + - fileName: Installers\90e1202895672ce81992e71be30528cc.cab + sha256: E7D46C8DFC8DB985915274BEEC3E12947E983519BB3A8FD2E8BC3C1F262D293D + size: 348257 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6cbdf6058688c1bb975efde175b6fc33/90e1202895672ce81992e71be30528cc.cab + - fileName: Installers\9126f6ff98d955951fe9323f4444c119.cab + sha256: B83345501710DFC04EA545E6C5B7B053E965ECC0F5B60D4B4FA1B7416B2D8803 + size: 568666 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b5d4fccd1bc71de7561a1646c2549111/9126f6ff98d955951fe9323f4444c119.cab + - fileName: Installers\921968b1c32e680f338247ac68950f5a.cab + sha256: D0953698E8627CD75228CFDF5CE77212DB945A195072133A1B7B1182B5A80211 + size: 38616 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e9e8c91f7bdd599566a2800cf0a12005/921968b1c32e680f338247ac68950f5a.cab + - fileName: Installers\931721e121ef91707ddcb6cac354d95c.cab + sha256: 135140D68DD681ADD8D4C9D127569DC9984A935F713CDF28ECCD1ABC0C6B80AC + size: 16726 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/a4a3129b07826c5ed9172aa72ba5ca50/931721e121ef91707ddcb6cac354d95c.cab + - fileName: Installers\93a74a1d34a22ae9d2e1ccc5208ad21a.cab + sha256: 6DDE5EC0358C22BA1D84E8D6C5ACE904D8D1F06A68A12DAB30AD4F7F8B8ADE95 + size: 473639 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ee73b66173514017e6c7b1662b9c71a2/93a74a1d34a22ae9d2e1ccc5208ad21a.cab + - fileName: Installers\94521fd1a9c57258998d60ce60dc43c3.cab + sha256: B66A66B82D5F981D8C5724A775B3FBC3B8D47D1C8A1BD3E57BCF90668CBF91F3 + size: 1903877 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/69d8f8d4079a5bdce633d09c54040611/94521fd1a9c57258998d60ce60dc43c3.cab + - fileName: Installers\948a611cd2aca64b1e5113ffb7b95d5f.cab + sha256: E17804825BDC529D3B4E2946C2EBB132F1E0B61550362CF49219D625B54F386A + size: 695219 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1621a0068d5853b5e72621dfa68fef46/948a611cd2aca64b1e5113ffb7b95d5f.cab + - fileName: Installers\9494c0c1f781298600a3c07e837acd0f.cab + sha256: D773FFECA132154B5810387788BA98307EE161F605DE4527EF35CD38DA4DA9F9 + size: 28880 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9631b442ccba5fe3af6defa5b0e8f26a/9494c0c1f781298600a3c07e837acd0f.cab + - fileName: Installers\96076045170fe5db6d5dcf14b6f6688e.cab + sha256: 317C77A4679C61307BAA31714DB52EFBA0BDB70E35565075DA8CA5826BB4ED05 + size: 659042 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1e6254eeee4a8338635e48bb40040643/96076045170fe5db6d5dcf14b6f6688e.cab + - fileName: Installers\9a7145bc3b132e5da6d44c0ab4a1af70.cab + sha256: 4320C2EFDDCB2C4B230A7FAA2E6332E1478885292DD55C2338658202DB796B9F + size: 7800046 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f7ab723beb199bdedc9b616cff9a33c7/9a7145bc3b132e5da6d44c0ab4a1af70.cab + - fileName: Installers\9ba47e440ec2fbe9a3d32a53bf0f68dc.cab + sha256: 2140B50F87B0B81B9FDAAB8DFACFFD3B18C551B00F0ED5E6E67E09EDF4CFA8CE + size: 451144 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b085e40212ae510de5aaaffa87f53c71/9ba47e440ec2fbe9a3d32a53bf0f68dc.cab + - fileName: Installers\9bcb3fab78e80d68be28892ea7ad46c3.cab + sha256: BB15C8F1BDD2B9ED249DD3D1AD7E5DB3A625D2740E08A5316FD417205091920A + size: 161580 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8c7512f7e2054d7693fccdd39be8f6d2/9bcb3fab78e80d68be28892ea7ad46c3.cab + - fileName: Installers\9bfca1e044c38e04afe2363d3db899c8.cab + sha256: FDCE7BFE7D4F2A5591CF2208C1FDD1D2198CEB273FE06EB2CD0D748B53230858 + size: 1198582 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/34be7155a0a1432fde543c43200c0278/9bfca1e044c38e04afe2363d3db899c8.cab + - fileName: Installers\a17683486ace64c3f9a1cacb81ee0260.cab + sha256: D9A2834A823A55E6CE5B1B93C6924229C1BDB4CBDE33431A731FC429E4BCCB7A + size: 99597 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/727f13db580db40001711f700ce5fec9/a17683486ace64c3f9a1cacb81ee0260.cab + - fileName: Installers\a1e2a83aa8a71c48c742eeaff6e71928.cab + sha256: 2C3E53A2BF91ADDBDE5B343DD53A2934F930CF53AEBDD04F5EE2B3D432659B20 + size: 26951085 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/7534f2776572ad7fa700d4b58f1340cf/a1e2a83aa8a71c48c742eeaff6e71928.cab + - fileName: Installers\a330840cf08ad4d210703c9acd1bf2b8.cab + sha256: 575B3E447D95E79335F719A85CCAAFA55814F64674F688CC1C410704A3E53248 + size: 1053895 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f96dde1bd8e949bc8aac7e46e2d400e9/a330840cf08ad4d210703c9acd1bf2b8.cab + - fileName: Installers\a35cd6c9233b6ba3da66eecaa9190436.cab + sha256: C0FBC22847676D6484FBD613D218E12CCE33A65859B46ACB95F1CA37F18E96AD + size: 1895042 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c6c89e4765e754c531b9556c53b0e789/a35cd6c9233b6ba3da66eecaa9190436.cab + - fileName: Installers\a68c0988d16ee124783efd98074dcbf9.cab + sha256: 9311E08042DCFC8B547A2734EEC0BA07763ED15D897934DEE9F15BF4FFCB0EDD + size: 17272 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f7e08b51a3d04dc18a368cd530d708b4/a68c0988d16ee124783efd98074dcbf9.cab + - fileName: Installers\a76e4219ecb0f1c0006a6fe080c54ad9.cab + sha256: BECA3D84DBD434B25196BB5CF9848C742F922D24661E8C90BD3DD10A2D83451A + size: 8359834 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/673b7603fc81db148b63fb27146c5c7b/a76e4219ecb0f1c0006a6fe080c54ad9.cab + - fileName: Installers\aa9c58552bdb82dae4ed48ece081cfe3.cab + sha256: C71095C8833CF72EFF3D2B26E0539C2A5277BF9CAC537E50F0997194769FCE49 + size: 1573491 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6630eacc6f2e13e4c55e99a01617edd7/aa9c58552bdb82dae4ed48ece081cfe3.cab + - fileName: Installers\ac4ddfcf1101c483559a5f6e36f1ef2d.cab + sha256: D71E1EFED1958251717E028893EDD4557723C4DD4A5671589C64A412DBB74C65 + size: 18882 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/97764aa5438b7350975da3b56050a7af/ac4ddfcf1101c483559a5f6e36f1ef2d.cab + - fileName: Installers\Application Verifier arm External Package (DesktopEditions)-arm_en-us.msi + sha256: 41168E5F693F80E34B49569F41F00153DA8DBC018D2B5139B3ECD2D5F5771FD3 + size: 487424 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/155db2ec1a52a6658cbf48b3055ac663/application%20verifier%20arm%20external%20package%20%28desktopeditions%29-arm_en-us.msi + - fileName: Installers\Application Verifier arm External Package (OnecoreUAP)-arm_en-us.msi + sha256: EFE6F39D330145DB4FF9B15C72998DB0F672AF9172C082C6DAB6BDD977EDE742 + size: 2154496 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/53e8cf76b654e5562d5cbebb0da9b6b6/application%20verifier%20arm%20external%20package%20%28onecoreuap%29-arm_en-us.msi + - fileName: Installers\Application Verifier arm64 External Package (DesktopEditions)-arm64_en-us.msi + sha256: 58C0CA29183D737F47BFD5BD4CE02D60C97E79A98EC7329585B82758ACD1D9C1 + size: 532480 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/fe33bb3d04c5e33bc61e38b4cf7d4ad3/application%20verifier%20arm64%20external%20package%20%28desktopeditions%29-arm64_en-us.msi + - fileName: Installers\Application Verifier arm64 External Package (OnecoreUAP)-arm64_en-us.msi + sha256: 861771E8BB496D73934CB5548919B2B08EC1964C4B443D5DCACFC84EBE8ACC76 + size: 2187264 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b62e5b855763a111183ce85a347cda53/application%20verifier%20arm64%20external%20package%20%28onecoreuap%29-arm64_en-us.msi + - fileName: Installers\Application Verifier x64 External Package (DesktopEditions)-x64_en-us.msi + sha256: CCEFB3B4900B026EA754CA788BF222F7DAF6500B5455366ECFB642D24131E129 + size: 638976 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/862df79e07542f1497cf46c3e06a0905/application%20verifier%20x64%20external%20package%20%28desktopeditions%29-x64_en-us.msi + - fileName: Installers\Application Verifier x64 External Package (OnecoreUAP)-x64_en-us.msi + sha256: C02624888FA480D2A580291542382613D29188FD2F9A4C0F8BC408E5DF4713B6 + size: 3661824 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1882ed0d71d155c8b3c07dc40b93917d/application%20verifier%20x64%20external%20package%20%28onecoreuap%29-x64_en-us.msi + - fileName: Installers\Application Verifier x86 External Package (DesktopEditions)-x86_en-us.msi + sha256: 77D1A5CC5CEF47D6BDF1EC2F56E93F36FADBF72F7CEC8169CA8AEB427B25A47D + size: 516096 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/456a036ee700d4e4b458a14b7cbadf6d/application%20verifier%20x86%20external%20package%20%28desktopeditions%29-x86_en-us.msi + - fileName: Installers\Application Verifier x86 External Package (OnecoreUAP)-x86_en-us.msi + sha256: 93788240FCE750B2B9BCDBC1253D72BEAF4C2DBAF27AAD3775FBC71FFD0AFC06 + size: 1957888 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/61f0a0a93ec7ef6364d97d3e19769bc0/application%20verifier%20x86%20external%20package%20%28onecoreuap%29-x86_en-us.msi + - fileName: Installers\b1a824e2952532fe8fd0145f5d148d25.cab + sha256: A7EF4E6B205D084CD7E4F32557939433971BCC8E3DE4DFE0ABE8D32185121CF6 + size: 397749 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8eeb8b77504499d2f9ca6dad19d3cfe9/b1a824e2952532fe8fd0145f5d148d25.cab + - fileName: Installers\b1a8ecf890b4ffddd05e8c9422f55db7.cab + sha256: A59EC1F96B7753FEACDD129D2C07B3CE67E45B240E25621B93B98449F01FFAD5 + size: 155362 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/779fbf11a1838e8a7e24fbdce0e4497d/b1a8ecf890b4ffddd05e8c9422f55db7.cab + - fileName: Installers\b2f03f34ff83ec013b9e45c7cd8e8a73.cab + sha256: 22A3C02529087CFC196094FC096300226B2A24652FCCC5196D17B4A21A4967C1 + size: 152967 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/a58da29b0f41b7e6a784fe7e6aedb7dc/b2f03f34ff83ec013b9e45c7cd8e8a73.cab + - fileName: Installers\b4eea6c909a31ab051e6f9b6218beec8.cab + sha256: 4931222F231D3708A7785A8342E138F446EB91BA165C23CF082DFF715CC5F1DF + size: 369727 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0e1d647044d7e91b5f3927f22e18ccfc/b4eea6c909a31ab051e6f9b6218beec8.cab + - fileName: Installers\b5f177b84c0ec473cbd69557634b27cd.cab + sha256: B7791C2AAF572A5A4F918C5A50B7A66A3433BD98021AB24368A89922A6A1D2B2 + size: 16622 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/7480aefa2245f0c952801fc8a0c732d7/b5f177b84c0ec473cbd69557634b27cd.cab + - fileName: Installers\b80b7321357f7c9f281536f9440dfe68.cab + sha256: 739FA2EE8F3480C55FD6F2788E9920AD1EDF63874E757EDC83763A8C7071F631 + size: 16967 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1b951e68af666c9682e7c0160d7f968e/b80b7321357f7c9f281536f9440dfe68.cab + - fileName: Installers\b82881a61b7477bd4eb5de2cd5037fe2.cab + sha256: 95F7CD718AB48BB202B85C0F689898E4952083AFE6E8711B973B3FD574E951DE + size: 28343810 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/01d7b6e164636363e051306e4f62271b/b82881a61b7477bd4eb5de2cd5037fe2.cab + - fileName: Installers\b913ca15956d14df2d4b1f11ae07885b.cab + sha256: 8B75913981DC41925E3A268A24EEBDDC8101D7FB024BD31CCC5F452F952B6F9B + size: 224529 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/3dc095afadbfb693a30468427c642312/b913ca15956d14df2d4b1f11ae07885b.cab + - fileName: Installers\ba60f891debd633ae9c26e1372703e3c.cab + sha256: 65CC46EFC7844E446D55993DF0E9CB04E9FA93FE5C35555D84ED68DBCC70200C + size: 7118189 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4bc100e641205a80ef37eabd6abce4a0/ba60f891debd633ae9c26e1372703e3c.cab + - fileName: Installers\be06eca425b0c3c2f4de61cbfe9bc7a7.cab + sha256: D5FB2445367756682C7A3BAABE5DFA2D061CCBEC5CC937FEE3A2ECA85AE09789 + size: 224529 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ff560de86e57d88963c115325c8fff35/be06eca425b0c3c2f4de61cbfe9bc7a7.cab + - fileName: Installers\beb5360d2daaa3167dea7ad16c28f996.cab + sha256: DCFE1CBD4B30E35613E79553C278A921FF704F93706B4BF9E5EE3C2C3AAC2913 + size: 605683 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4c53c52961d31f4828cc886ff21fef0f/beb5360d2daaa3167dea7ad16c28f996.cab + - fileName: Installers\c0aa6d435b0851bf34365aadabd0c20f.cab + sha256: E3A1792D74EAE5EBDC0EBD6EDD5A9B56848AAD93D14B35242BD72306B6FC66FC + size: 4391445 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e32bb7061badba06efc99f3414b78919/c0aa6d435b0851bf34365aadabd0c20f.cab + - fileName: Installers\c1be9e93e88be3f6207f5cc074775d81.cab + sha256: 7395DF2EBE4CF3927FA92CF91FE9E9B5BC81A314DF6AE2A6B61821883923B12F + size: 95715 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c8206bcdebb8cc7ca1208c6e3f06dc39/c1be9e93e88be3f6207f5cc074775d81.cab + - fileName: Installers\c1c7e442409c0adbf81ae43aa0e4351f.cab + sha256: F9F616DBF010282DD3B80DE870B15C7C9A2B6429D8EB2B26F470B12A76DB60E2 + size: 892709 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/7bdc8c19f2cb12327900a814cf0d459e/c1c7e442409c0adbf81ae43aa0e4351f.cab + - fileName: Installers\c2aabf6ea5c1d348ec22f3aeb92f8656.cab + sha256: DABE14AF79B16D9289C67D401E6C9C5D1AA5BC42FFF014B7F82FC262D0DB14B3 + size: 16823 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/a0716beef98be3ea6a7bec179bb627fe/c2aabf6ea5c1d348ec22f3aeb92f8656.cab + - fileName: Installers\c4d38a2c963178a1a3469ca3d913768e.cab + sha256: 470BC8D1CDDF49119BDC41092BD772C6CCAB36B53146C0C6A973198B124E6342 + size: 19234 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8168c0082d517e0e5cca16bf006761a5/c4d38a2c963178a1a3469ca3d913768e.cab + - fileName: Installers\cd9128b760c06a010e1621af6528432e.cab + sha256: BAF4AE7256C1F645B56DBA6267EDB9A5E54E563A8B1E14C72F961A2EEFC2E7C9 + size: 62228 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6883b98c2e4990ab259d96b25707cc70/cd9128b760c06a010e1621af6528432e.cab + - fileName: Installers\cdea5502a35d09ddfbcda12e3a391dc0.cab + sha256: F22532984D3017A87289BE81A1038BE3D7F867A323D6C957BD9BB27A85DAC2E9 + size: 7547607 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/07d96feb23009b21a51795d0e6e5334c/cdea5502a35d09ddfbcda12e3a391dc0.cab + - fileName: Installers\d117bb4bc77abadc7c603552e122e513.cab + sha256: E3B7D17C0D8E84B9DEA85EC29ED48FBBE71A127BD74AA315E2BE1BE3B53DF461 + size: 580970 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/355b8ffaa6fd3cf711bc98a5bf7639a4/d117bb4bc77abadc7c603552e122e513.cab + - fileName: Installers\d3e405ab232f8aca8c5b6a48a913d6b0.cab + sha256: 173B3D274C5F1839589BDB3857188ABB5DC9248671F08230E339B81B511D9B0D + size: 195178 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5316d64d74a83b149e0700b07e5cd8cf/d3e405ab232f8aca8c5b6a48a913d6b0.cab + - fileName: Installers\d67259e233ce975d91c3b02d483becad.cab + sha256: 17DC66199B6AF74D4804C6C3CEC4D6072ABD087AB6A7990BAA8E8B51DDCA664B + size: 13648050 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/1962a888db88e2ed62dfc51cd05f4c1c/d67259e233ce975d91c3b02d483becad.cab + - fileName: Installers\dcfb1aa345e349091a44e86ce1766566.cab + sha256: 12E58290F3FDFDF211D79E193C9C7789FFC0D315961111F80FA0C5D1FFE34A31 + size: 94284 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/73e2b8a2df5f15ce5fef29055ebc83bf/dcfb1aa345e349091a44e86ce1766566.cab + - fileName: Installers\de111c3d435b0785b31b28c386ee691f.cab + sha256: 4C4004FE9B5CC083A1DFE8247FEAFD16EA430904A1B5007CCD6767B7C2928E3C + size: 16926 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4bc151861eedbe55b676d188b339dbb8/de111c3d435b0785b31b28c386ee691f.cab + - fileName: Installers\e072b3b3d3164e26b63338dce51862a7.cab + sha256: 727E8744F3D67E595369BCD0A25ED0F07ECC5ABB376B83C81754ED37BB52A6BD + size: 2683675 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f0b3ff77c02d21650c2fe6a20a5eb689/e072b3b3d3164e26b63338dce51862a7.cab + - fileName: Installers\e10768bb6e9d0ea730280336b697da66.cab + sha256: 74814C75DF70E7FDBA9CC7E6CA5905E1376296CB73DCD96EC537D6F26265A00B + size: 7239460 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b86a54b7e67a79b3922f3e9b5fdc21dc/e10768bb6e9d0ea730280336b697da66.cab + - fileName: Installers\e10f8811d44b50885777f56f8272f66b.cab + sha256: 7203D336A0B384FA99FA2BC292C64B0751AD7E4A27A7616F04FE78608A5ACBA5 + size: 605912 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4ef4171b13d5037f0aca5304630d639e/e10f8811d44b50885777f56f8272f66b.cab + - fileName: Installers\e24dd258b3bbfa69c0842948fe0dd670.cab + sha256: F11588503265748F18923D113A2EB558C07CAF51D142E03E3966BC3E3FD2DA88 + size: 894053 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/537667b80d9f654ba8f309c5cb8db5e9/e24dd258b3bbfa69c0842948fe0dd670.cab + - fileName: Installers\e3bfdbe21d5f48f62e6347294e6e8492.cab + sha256: 86573647E649CDE3DE4F089BFAD58F545CF38F1DFD156CA49A737C5A114A1AD5 + size: 106412 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9d2035341d102130b1075975b38894d9/e3bfdbe21d5f48f62e6347294e6e8492.cab + - fileName: Installers\e3d1b35aecfccda1b4af6fe5988ac4be.cab + sha256: 4CE5C24438A5BA7C56F5E5F14643BDAB9A1C677E50B1AC7EC9C70378F8804255 + size: 17665841 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9f350cbd05ec08f5a5d56a036d3df8e6/e3d1b35aecfccda1b4af6fe5988ac4be.cab + - fileName: Installers\e5950ce9ba509b3370ebf328742a5f45.cab + sha256: 5024FEBBBE2547E1117D1FBA2676953465BC3184D558269AC4BAEA875BEE4D88 + size: 30634 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6b9fa798d5289ea4efabadd69555c5c7/e5950ce9ba509b3370ebf328742a5f45.cab + - fileName: Installers\e59830bab4961666e8d8c2af1e5fa771.cab + sha256: E5D86C07420E50E9C5431737F1B1BE7C773E1C63AF9BFF30AF99BB295B5CB945 + size: 162537 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5d605b3d6307cb99c2425365602505b8/e59830bab4961666e8d8c2af1e5fa771.cab + - fileName: Installers\e5c4b31ff9997ac5603f4f28cd7df602.cab + sha256: FC6CF473F946DF7004F5EB28D209D032D885971E80ECC6109E18CA8527CBFF02 + size: 1799288 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c996b07d2b21bf27afe93fec193688a3/e5c4b31ff9997ac5603f4f28cd7df602.cab + - fileName: Installers\e87de81a902e0c8cde9e1355c3ff5f3f.cab + sha256: E9074B8CFE79DB05C75365B7FC4D93C99A8D419224F77D248980719BDA6FCD7A + size: 1706665 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/21b0503b230486b959f0c09da2734fc7/e87de81a902e0c8cde9e1355c3ff5f3f.cab + - fileName: Installers\e98fa5eb5fee6ce17a7a69d585870b7c.cab + sha256: 1806798E75F3FD586F0A813F70D379A40399CD82082CCAAF15FA334EA4C2D347 + size: 1365781 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f95e154d921d7d70267c0cae82f1906a/e98fa5eb5fee6ce17a7a69d585870b7c.cab + - fileName: Installers\ec0637c03f99046936d32d51e13a392a.cab + sha256: 8AD7C813A6C12A7405E6839F66BD42EB007CA6DBB3A16EBE6454ABD6F07A366E + size: 16591 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/65ded11a997db13bbf5a432b0c9a6c87/ec0637c03f99046936d32d51e13a392a.cab + - fileName: Installers\ec9ab4bbb809719605d27da343b909e8.cab + sha256: C61D28D571ED411D27212CA4A4C2B507DD0BC522299D600597F46543B0C8E16D + size: 106335 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/25dff9cce8ac78e2f95bf9f323cd2cb0/ec9ab4bbb809719605d27da343b909e8.cab + - fileName: Installers\ec9d39539c27e8cf5ad39bffce00c34e.cab + sha256: 798D4484F1D42C7FD79341EFED95E05FDA83EF7D81ED107F3583F27A2CAAE783 + size: 224016 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5022e184ba48b7bd08b8ef555276f37d/ec9d39539c27e8cf5ad39bffce00c34e.cab + - fileName: Installers\eca0aa33de85194cd50ed6e0aae0156f.cab + sha256: 7FF11889C56E071D9836818EF72650A6D0EBA2985CB22D6435E85F74D16BCEC9 + size: 40310 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f39b836410530eda94d26988c784dc25/eca0aa33de85194cd50ed6e0aae0156f.cab + - fileName: Installers\ed4d1c6b9811d81e3cebc553ae604f0d.cab + sha256: 0D0FACB3245962C3E7DCC698D76D885F6A33871C1F69112A4DA0F2803294E342 + size: 16750 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/48581202f366b8054058283c8f56d7fd/ed4d1c6b9811d81e3cebc553ae604f0d.cab + - fileName: Installers\ed5aa2f399092df3084cce671f072cac.cab + sha256: 9078AB6FB4558FE48F7B1E5FE9AEE0FC32C831683487F5D033ABE85E29400BF6 + size: 1516219 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ddfabc1e5ba0535b77b0de3395a9a5d4/ed5aa2f399092df3084cce671f072cac.cab + - fileName: Installers\ef4472fd7552490fd759075186ed2ec8.cab + sha256: FE88967023C94514F16DDDCFA90DB1B6CBB19860D3989E0D85FBA0D227871F0F + size: 264238 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e252550488867e75162e8ae7d061bf8d/ef4472fd7552490fd759075186ed2ec8.cab + - fileName: Installers\f105a73f98cfc88c7b64d8f7b39a474c.cab + sha256: 3316EB87528B4AF1FDA51109BC2A18FF418B0ED057F36170FA74362D4403AE18 + size: 57209 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d9f57707154c265b7476e7cf274bb7af/f105a73f98cfc88c7b64d8f7b39a474c.cab + - fileName: Installers\f4661eda3692e166927c14c96164150a.cab + sha256: A44B8C0E8E7DFDD0F79118335A6C5AA37BF90F595C2B25D35D34F03887158D43 + size: 969649 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d056e6c386a656dd230fe7a0a259b793/f4661eda3692e166927c14c96164150a.cab + - fileName: Installers\f7b25543b47329ef932ad391c72c4ab7.cab + sha256: EC037AD3F95106AE4E91AE35A8E7BADD71BDA93F8AA7AFCB63A72BB5F4879F9D + size: 85822 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/49c863c2a1e1c09ee59ff004d343d5f2/f7b25543b47329ef932ad391c72c4ab7.cab + - fileName: Installers\f87007e985bc5453a0f01ed1a5510abe.cab + sha256: DC4709A3A038DB29EFCBD7D583751E880C82CEA479872AF00EA3A32AC28BD71E + size: 19246 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/16b9cd32e21edf17a6f5e52f3d8ec9de/f87007e985bc5453a0f01ed1a5510abe.cab + - fileName: Installers\f9b24c8280986c0683fbceca5326d806.cab + sha256: DBA4620C107B17F5A9F7FAE54A55CA9FE5C5A150D76761350539DF60CC1275A3 + size: 7255774 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/00db6467b6f88a77a01711125506b828/f9b24c8280986c0683fbceca5326d806.cab + - fileName: Installers\f9ff50431335056fb4fbac05b8268204.cab + sha256: B747D3105549B6E137A3B3D4F74027C3B6AA9EA170E4282CA85EA152A9FB8580 + size: 17199 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d9e03d7f3f5aa9fa5770817212ddf98d/f9ff50431335056fb4fbac05b8268204.cab + - fileName: Installers\fe38b2fd0d440e3c6740b626f51a22fc.cab + sha256: 592287AE17544DA8D1BF113BE2AA9E790FAE5F4B68500AA13EBB870A6051E527 + size: 17234 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9d481276ab7017f28144d11043e9fa5d/fe38b2fd0d440e3c6740b626f51a22fc.cab + - fileName: Installers\fef2cfedd6135e0ed85290b83f3682c3.cab + sha256: 4852F7FE11BCBDFFCB86CD1D7DA99B9A3DB52B5F15CA41CEAEB7DDDE445DBDDB + size: 687200 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/27a8ce8e83bc61457b237ae6b407075f/fef2cfedd6135e0ed85290b83f3682c3.cab + - fileName: Installers\ff8dd5a961e46b5d05906ac4b7a5ba37.cab + sha256: A33AE53525DC24408F1A0E9D8EE1E962E2D4A8CE55BA1625AB89AD81223208BB + size: 16475 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/153cd306f5545d33c713ffbd3fce8ed2/ff8dd5a961e46b5d05906ac4b7a5ba37.cab + - fileName: Installers\Kits Configuration Installer-x86_en-us.msi + sha256: ADD211DE904A8ECD0A8C8E1C8E6155A63C0012770F627D39A84ABB424033FCC1 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0378854d39800489df0a8001d2a4ebe7/kits%20configuration%20installer-x86_en-us.msi + - fileName: Installers\MSI Development Tools-x86_en-us.msi + sha256: B37745C92FD7C956EF3FEF907673208033BA20DDA406CAFEE30807C3C1AFB9E8 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/75329ae2a3f353d3f6faedd3599d05cf/msi%20development%20tools-x86_en-us.msi + - fileName: Installers\MsiVal2-x86_en-us.msi + sha256: 18F9C5E056EAF83A4080BCFA7126E67FF6D42C3725B18D310467429FCC8FFFD9 + size: 610304 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/20e2ce082de53867943c8a6797381af9/msival2-x86_en-us.msi + - fileName: Installers\Orca-x86_en-us.msi + sha256: 255EEBC2366EA0159CCD328736D4A4C7E2317EBB6600DAE6C6865E4C757BD5ED + size: 610304 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f4945b9de276338c2f2b05a300cdf1a8/orca-x86_en-us.msi + - fileName: Installers\SDK ARM Additions-x86_en-us.msi + sha256: 59593CFF18597C459AD1631F0686C42380A1C02A451C6DE7678AB93EC08F4EE6 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/33068e1a7c5574c0eaa11c9ea931bf96/sdk%20arm%20additions-x86_en-us.msi + - fileName: Installers\SDK ARM Redistributables-x86_en-us.msi + sha256: D89B91A5CBA7B0199EFC7F937920192D2BDBC976DDB6C09383783E751B0B188E + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b1bbca0cbd2d30f5be90739c6e28dcce/sdk%20arm%20redistributables-x86_en-us.msi + - fileName: Installers\Universal CRT Extension SDK-x86_en-us.msi + sha256: 1EE395EB80E2C6F2C40EFC31D3F05EC7F768A03A085055540FC3A194CEB85880 + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/62b406001fa755f6b39630410205228e/universal%20crt%20extension%20sdk-x86_en-us.msi + - fileName: Installers\Universal CRT Headers Libraries and Sources-x86_en-us.msi + sha256: EA49E8F8F960C8739CB50E3936377B30C4D17AD72A5E0CD19F0EB6D2FC829D0D + size: 536576 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/3bf8dfb5b837de6e21219296e7abe7b5/universal%20crt%20headers%20libraries%20and%20sources-x86_en-us.msi + - fileName: Installers\Universal CRT Redistributable-x86_en-us.msi + sha256: 31BDFCF999B379DEB45938E158217B9BCE9D3A1B4180E8650DDFEC7BEFC8DD37 + size: 434176 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/30b97df54595a827fe113583d45f279c/universal%20crt%20redistributable-x86_en-us.msi + - fileName: Installers\Universal CRT Tools arm64-arm64_en-us.msi + sha256: A82579927C11A9E0CEE02E421553D20B86ABB91A50DEA6E997FBA11BEBABCD3F + size: 421888 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0efcf00ca51cd253d9d16de1a0cc775a/universal%20crt%20tools%20arm64-arm64_en-us.msi + - fileName: Installers\Universal CRT Tools x64-x64_en-us.msi + sha256: 2CF3CA5E0C3A5C2D22041EF9B5682C6CB3766428095989EB08A40E2CC9715289 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5939d0ebb8b4ee6d449134614b6933a8/universal%20crt%20tools%20x64-x64_en-us.msi + - fileName: Installers\Universal CRT Tools x86-x86_en-us.msi + sha256: B930B2E42ED2B07BE657596171142EFFDCF3606565D890ADCC59B8A55D402CF0 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/72730c8a78ddceb845cdd6716ed38d50/universal%20crt%20tools%20x86-x86_en-us.msi + - fileName: Installers\Universal General MIDI DLS Extension SDK-x86_en-us.msi + sha256: 3BF97CFA9F3E74A99FC22283B776131A89E7D902F67EF947D2523ABC78392460 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9edcd670a26f87594566fdc5b42502f3/universal%20general%20midi%20dls%20extension%20sdk-x86_en-us.msi + - fileName: Installers\WinAppDeploy-x86_en-us.msi + sha256: 8A47D1E5AF254767767FBAD4A0D8BD61D89693FAE9C31081EDDADA615AF82173 + size: 1925120 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c15b190bd50f25ddc676dca0515251bc/winappdeploy-x86_en-us.msi + - fileName: Installers\Windows App Certification Kit Native Components-x64_en-us.msi + sha256: CB416B9ECF1BA695A1D6E4184D9599E27D015682760049211069D473D4AD10B2 + size: 466944 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f772939181c88349573dc967b1548a63/windows%20app%20certification%20kit%20native%20components-x64_en-us.msi + - fileName: Installers\Windows App Certification Kit Native Components-x86_en-us.msi + sha256: 0911A2A8ED3370258AE66DED7C8FAC49F0003DEBB858A530331052377D82F4C6 + size: 466944 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/221c659559ab977717779453b2cd995e/windows%20app%20certification%20kit%20native%20components-x86_en-us.msi + - fileName: Installers\Windows App Certification Kit SupportedApiList ARM-arm_en-us.msi + sha256: 961515D62214C5F1B4F5FE01A3C3541FEE4E73736896BD2A822667F00FFC7207 + size: 376832 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2d383889379e33ef3bdfbd3569c6167e/windows%20app%20certification%20kit%20supportedapilist%20arm-arm_en-us.msi + - fileName: Installers\Windows App Certification Kit SupportedApiList x86-x86_en-us.msi + sha256: A51C561A293D4DC8F3F10FA3B2ADDA503EDEC9110815AE2B2C24424D1939D6FC + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b9b84deab09eb27ba4f19c600ea35429/windows%20app%20certification%20kit%20supportedapilist%20x86-x86_en-us.msi + - fileName: Installers\Windows App Certification Kit x64 (OnecoreUAP)-x86_en-us.msi + sha256: 5F271ADCB727848C29B7500069CB8C36C9CE72B193003DE884C536FCAE85DCB1 + size: 417792 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0bf036a96679b67f65fee5dbe20b813d/windows%20app%20certification%20kit%20x64%20%28onecoreuap%29-x86_en-us.msi + - fileName: Installers\Windows App Certification Kit x64-x86_en-us.msi + sha256: F98DEC0E4AEF0150C279064B63D800BC04F50D015A417EE765979D6CF7C0FBE8 + size: 544768 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4b6202630bc8004e4d570acd4a76bb28/windows%20app%20certification%20kit%20x64-x86_en-us.msi + - fileName: Installers\Windows App Certification Kit x86 (OnecoreUAP)-x86_en-us.msi + sha256: 01AC9127C657135375A5A3AD269782F144D8CAD4050EAFD95A81D69A16F21372 + size: 417792 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b31921a2999a3a036c07aa6ed5b68114/windows%20app%20certification%20kit%20x86%20%28onecoreuap%29-x86_en-us.msi + - fileName: Installers\Windows App Certification Kit x86-x86_en-us.msi + sha256: 92545986067D8A1B4593A69408EED919124D31B01550F5052FD214B2CF29346A + size: 544768 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9d9484d638e38b09e931eddc3e5d7a80/windows%20app%20certification%20kit%20x86-x86_en-us.msi + - fileName: Installers\Windows Desktop Extension SDK Contracts-x86_en-us.msi + sha256: 87B6761B3FC975DF750724B5753383D40012959628CB04E55478C5C6C42B63C3 + size: 425984 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/0685c71486a422fe099a322e6d3f8db7/windows%20desktop%20extension%20sdk%20contracts-x86_en-us.msi + - fileName: Installers\Windows Desktop Extension SDK-x86_en-us.msi + sha256: 006B5F3BEAAB0770B58AE8689C35D03ED026A2848964CF762F6D3544C279300C + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6d2fd0939b09281121bf802f87efadfc/windows%20desktop%20extension%20sdk-x86_en-us.msi + - fileName: Installers\Windows IoT Extension SDK Contracts-x86_en-us.msi + sha256: 9EE722A1DECA663B8DC2A35BB90B328D15C9589C80826DFEBF9F4A1279E32401 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/11edd6bb213f2351e7667c5561c8f55e/windows%20iot%20extension%20sdk%20contracts-x86_en-us.msi + - fileName: Installers\Windows IoT Extension SDK-x86_en-us.msi + sha256: 372BA9F8FF8E94D3931D657856549A1D6286732F10AA66CEED7C15F38C0C2178 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/affc08dcd23449dd6dc1364e824068d3/windows%20iot%20extension%20sdk-x86_en-us.msi + - fileName: Installers\Windows Mobile Extension SDK Contracts-x86_en-us.msi + sha256: 3439D3F4A5B012D67A5421A0495444B927DA714001B23502CE591226E8A81DEE + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/82b1fd61f04afca31e1f14cdf2730888/windows%20mobile%20extension%20sdk%20contracts-x86_en-us.msi + - fileName: Installers\Windows Mobile Extension SDK-x86_en-us.msi + sha256: 42742D42EDCE01827717FC5C6C4B29B1BD2398A1AF4CE575BE330C8F9B58AABD + size: 417792 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/17a6535d5da510d6c087c412bd052f64/windows%20mobile%20extension%20sdk-x86_en-us.msi + - fileName: Installers\Windows SDK ARM Desktop Tools-x86_en-us.msi + sha256: A20D29E360890964D2F35DE2F6C6E2F40B148337AA8500B3C644BEB1663ABB06 + size: 413696 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b55195586073353151a3f2934e97fc45/windows%20sdk%20arm%20desktop%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Headers arm-x86_en-us.msi + sha256: 8802A2F0AD07FCAA84DD432CB1012A91618B8B32091231FA880FB29A5FD613CE + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/075e1937a67c3cee8e819049a02edab7/windows%20sdk%20desktop%20headers%20arm-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Headers arm64-x86_en-us.msi + sha256: DAFD300488E13A4F8D35AAA5849A4C0CC31B8D9917B957E1CFC05AA328A37D6A + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/62913a2f6ef47b251585cea3487ab215/windows%20sdk%20desktop%20headers%20arm64-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Headers x64-x86_en-us.msi + sha256: FDA41F280EB7A83CEABF1D66D56B1BD1A021B39962C0F60D9BB86C204416B9F5 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/873ec90c32180e6d972d50e4fed88cf5/windows%20sdk%20desktop%20headers%20x64-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Headers x86-x86_en-us.msi + sha256: 5EB06273907A460D730D58E3A5CA03BAD5C9CFE6F7049FEC54F1A22DE4F31112 + size: 786432 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/455212c466a6b48073c8dbabc663fa17/windows%20sdk%20desktop%20headers%20x86-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Libs arm-x86_en-us.msi + sha256: F7737555FBB1F7512A7F050DAD963F131EB3AA532677478DFD8EF30513BEA2B9 + size: 479232 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9b125eec1b6f0008e3071e718c445f2e/windows%20sdk%20desktop%20libs%20arm-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Libs arm64-x86_en-us.msi + sha256: F148514540313651627DF88767A1AE19BEF4A0AE051D432CBF8D481EA5C4DBC9 + size: 483328 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ef4f1b979af68727b88a08c62bb1a6ef/windows%20sdk%20desktop%20libs%20arm64-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Libs x64-x86_en-us.msi + sha256: FF94540BE079FDF4C54112F614A25EE4F25B820B68FA3FB84DD8879CEF490D89 + size: 483328 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/09056983818d043fcb50f968269d73f7/windows%20sdk%20desktop%20libs%20x64-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Libs x86-x86_en-us.msi + sha256: C7227CBD4696A809DD39AA55881E5BA43FF906E08825FDFF314E2DD3D26F0CA9 + size: 483328 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b0693a574d339f29c92366b8a89c8393/windows%20sdk%20desktop%20libs%20x86-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Tools arm64-x86_en-us.msi + sha256: 2933F7F65B5472C286D7D6FB591A29608217F0CC0D5E4B3FAEDAAD706A6A781F + size: 425984 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/e1db924b1dd5729dc29e49d462759c7e/windows%20sdk%20desktop%20tools%20arm64-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Tools x64-x86_en-us.msi + sha256: AF87B9B7F7A2B2DEEBE883B69337DD87D73C1AE735A36D848B9270BC0CFE86D0 + size: 425984 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/4e017e35b0ab95b2daeaa90c234c61e0/windows%20sdk%20desktop%20tools%20x64-x86_en-us.msi + - fileName: Installers\Windows SDK Desktop Tools x86-x86_en-us.msi + sha256: AAC8B4B24FF765EB1BDCAFF6714C6E490876A91130CB7A9394CB4CD7A30F40C4 + size: 430080 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/8356eecbbd2e373be1f491cb01122914/windows%20sdk%20desktop%20tools%20x86-x86_en-us.msi + - fileName: Installers\Windows SDK DirectX ARM Remote-arm_en-us.msi + sha256: DE2DC127B607111DD5AA74E2CF7146095AA52DAD52058AE1984BDB00702B34B3 + size: 376832 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f6190aaf3a0c1e8af1ad547caed57e90/windows%20sdk%20directx%20arm%20remote-arm_en-us.msi + - fileName: Installers\Windows SDK DirectX x64 Remote-x64_en-us.msi + sha256: 9FE85349B3D73B5F5D2883E13B974FDAAC542535F3AA1A16D8C6A2F450188615 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d3ef9c6ba809d67ae857d5e70a53031f/windows%20sdk%20directx%20x64%20remote-x64_en-us.msi + - fileName: Installers\Windows SDK DirectX x86 Remote-x86_en-us.msi + sha256: F6FB41714FBD6165845AF62EAB613D923A787CFE5B51C2CDE8343D363FD40D51 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/65ef2e4de7435051c98ba0f3c371df03/windows%20sdk%20directx%20x86%20remote-x86_en-us.msi + - fileName: Installers\Windows SDK EULA-x86_en-us.msi + sha256: 7A3E1A5DCD3346FD186DA5F4BD221AECA1080C8D45BCBB305D4465F82B371979 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ad05426408e125a76a6d3d70ccc2d805/windows%20sdk%20eula-x86_en-us.msi + - fileName: Installers\Windows SDK Facade Windows WinMD Versioned-x86_en-us.msi + sha256: 5F6EFB27B94F882D9623DB66F642AB4A998E76BAC3885D5528A2B67A244918A0 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/67bec769969331d59a01da014e02e9a2/windows%20sdk%20facade%20windows%20winmd%20versioned-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Contracts-x86_en-us.msi + sha256: 71BB4876B2AF91230221F0871D73DCB280760DF2882D35759D0F6C7C265704DD + size: 421888 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6c12a2145bf6f488cd07a852b200d6a2/windows%20sdk%20for%20windows%20store%20apps%20contracts-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps DirectX ARM Remote-arm_en-us.msi + sha256: 8E8D8CECC48365E363A71A8E2F2A080E70FAC2B5CAF6E3AFEFADA9A2DE63CFEC + size: 380928 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/2071b3d2e5126303ee951f4bcd799038/windows%20sdk%20for%20windows%20store%20apps%20directx%20arm%20remote-arm_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps DirectX x64 Remote-x64_en-us.msi + sha256: BC8B73CED44BDFD239D0B4B3847D981C82BD7BE91C97E0382A6431A8DEDE7FD2 + size: 413696 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c407ef359442a9025fdc2fbf846ee733/windows%20sdk%20for%20windows%20store%20apps%20directx%20x64%20remote-x64_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps DirectX x86 Remote-x86_en-us.msi + sha256: 50ED1B0725E07AA3B0AE7D616B0D26A5C7020CFEB549487AB62F4BE7BB2F64AE + size: 413696 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/7f52dc9dbdbc74a0a9fbef98c5e51a0b/windows%20sdk%20for%20windows%20store%20apps%20directx%20x86%20remote-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Headers-x86_en-us.msi + sha256: FD4A8A18E65B1E634C5547668EEDE556EF32250B0CE1F04E8025E5F0762F3C96 + size: 1024000 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/c69bf436474fad49f43b0ee9a161f106/windows%20sdk%20for%20windows%20store%20apps%20headers-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Legacy Tools-x86_en-us.msi + sha256: A79BF46129B680F0ABADFBB527DEF9F4E18CBE0E88BC6DC60A45F7AE30EF98A6 + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/9c7c7451db9a4a5cefbf49da14349b2f/windows%20sdk%20for%20windows%20store%20apps%20legacy%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Libs-x86_en-us.msi + sha256: 27164B5274365EB8027E634131FFF36B08617F7E8E7D1D7103FD274901C647A8 + size: 503808 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/887c76e122fa8cd86a2e64a32297826a/windows%20sdk%20for%20windows%20store%20apps%20libs-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Metadata-x86_en-us.msi + sha256: 3881D762BA86FBD21B9F9C243233B4AB53535231DAD0EA24128C6C7C749986D9 + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/5e112cb2167d372a8e187a3fcb83f1cf/windows%20sdk%20for%20windows%20store%20apps%20metadata-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps Tools-x86_en-us.msi + sha256: DE7E95CAEA5FE136415D7B47A7E814AADA829763F2F1CAFC6012AFCB41F98EB8 + size: 491520 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ab273e055f3beffec7fb6d9d9e1b8afc/windows%20sdk%20for%20windows%20store%20apps%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Apps-x86_en-us.msi + sha256: EF4E0D2BF8BEFC26F24CDFF291FE2DAEC62232D5AFAC053BBCA3528D51699F14 + size: 417792 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d55da022ec6094ba1a84eecb4e01a8c9/windows%20sdk%20for%20windows%20store%20apps-x86_en-us.msi + - fileName: Installers\Windows SDK for Windows Store Managed Apps Libs-x86_en-us.msi + sha256: 9E6DECE2FD9A857C97B879D245D968802458F9419A34B4F4EB3590F7D1EFC023 + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/7d7984f4610dd1c68e8be21ba5801ead/windows%20sdk%20for%20windows%20store%20managed%20apps%20libs-x86_en-us.msi + - fileName: Installers\Windows SDK Modern Non-Versioned Developer Tools-x86_en-us.msi + sha256: 85B1CFE25AC30B76C9C33CA5D671F2CDE6BCA6551009DCB46F6B5F05B4315D19 + size: 413696 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/38ace30be384796e4ac448bd28ae9808/windows%20sdk%20modern%20non-versioned%20developer%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK Modern Versioned Developer Tools-x86_en-us.msi + sha256: DFDD77D21D17F61124F069294129222FAFFE676DAD5C601B439AB0A2818F6D1D + size: 417792 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/430172372ceec9aef4e61d507e72dd59/windows%20sdk%20modern%20versioned%20developer%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK Redistributables-x86_en-us.msi + sha256: 6F392D60FC8DE23E6DE9DD2C35C2C1C9D0DC82AD725894CA08FF8066DB8393DB + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/18f1678522c2799c97163f31aa74f686/windows%20sdk%20redistributables-x86_en-us.msi + - fileName: Installers\Windows SDK Signing Tools-x86_en-us.msi + sha256: F0E2467A79447897C402F5E369D9CC823128989397A2DEB81010D6B40BD646E7 + size: 421888 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/a3561ef72e7195e9c71a4e9d313ab3da/windows%20sdk%20signing%20tools-x86_en-us.msi + - fileName: Installers\Windows SDK-x86_en-us.msi + sha256: 79412A73A3A388B35EF76668EDBB54677095EC8797B658801E0FF8D6C703FE5D + size: 417792 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/f9922b347fd4053bd51f06d59d57f712/windows%20sdk-x86_en-us.msi + - fileName: Installers\Windows Team Extension SDK Contracts-x86_en-us.msi + sha256: BE759923517C20756E2C02A1CA4D7DA9A2D54D0BA4B556B09B6EE6472768FAE7 + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ff323953923d74e1a4e968e91f1b1301/windows%20team%20extension%20sdk%20contracts-x86_en-us.msi + - fileName: Installers\Windows Team Extension SDK-x86_en-us.msi + sha256: 5F2E1611458F9C3285C5BEA0E1899B404D1EE216956D364B7F490F3C8A0F06CD + size: 405504 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/a3db1a29c805894b4f739fb5143db381/windows%20team%20extension%20sdk-x86_en-us.msi + - fileName: Installers\WinRT Intellisense Desktop - en-us-x86_en-us.msi + sha256: 9D2E6E7FA33C132361AE0F696F6A293BFE0427CCA4F78F992E6F706F290285E0 + size: 450560 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6e51bed2dd7f2ffc2f5ee6084fa22d26/winrt%20intellisense%20desktop%20-%20en-us-x86_en-us.msi + - fileName: Installers\WinRT Intellisense Desktop - Other Languages-x86_en-us.msi + sha256: AD5323B30A722DA01E299EC63D56B351B3D18518E3A18559E21ECA693A84F66D + size: 557056 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/6eb95317172afed4d8a51bbce42dfc70/winrt%20intellisense%20desktop%20-%20other%20languages-x86_en-us.msi + - fileName: Installers\WinRT Intellisense IoT - en-us-x86_en-us.msi + sha256: 74E8E28FD4D326667CECBCA44FB3733AECB5F6D127987AE8DBC857D9A8465975 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/b00b793779f61414bbb00b9509979bf5/winrt%20intellisense%20iot%20-%20en-us-x86_en-us.msi + - fileName: Installers\WinRT Intellisense IoT - Other Languages-x86_en-us.msi + sha256: 3FD42B8E9BDD0E101BC2291E6FD033440B86F4D470D0781CDDC43EBCACF06EB9 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/14a25708590bcaee79dafdc2d1b52618/winrt%20intellisense%20iot%20-%20other%20languages-x86_en-us.msi + - fileName: Installers\WinRT Intellisense Mobile - en-us-x86_en-us.msi + sha256: B0B37C34FABDF661FBA17EF7C55F44CD511F7A0F9840EC5F5C7503A79FA7C533 + size: 409600 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/676362b4bd152ca87942011a5c9c79d3/winrt%20intellisense%20mobile%20-%20en-us-x86_en-us.msi + - fileName: Installers\WinRT Intellisense PPI - en-us-x86_en-us.msi + sha256: D34C7CE6008EAB5C443A4743E2AA3EA9DAC8B61A00FC1407818F87E5FE91B788 + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/06d7c0876e4ff340b25338069f0a1c5e/winrt%20intellisense%20ppi%20-%20en-us-x86_en-us.msi + - fileName: Installers\WinRT Intellisense PPI - Other Languages-x86_en-us.msi + sha256: 3DA078CBCF1BAF2DE94B944EEEA98FE2495EB084C2AD025C715FDB252041E44C + size: 401408 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/086cf8a07fabe78870d222815f9e86f5/winrt%20intellisense%20ppi%20-%20other%20languages-x86_en-us.msi + - fileName: Installers\WinRT Intellisense UAP - en-us-x86_en-us.msi + sha256: 8C1E8BB7395969449CB11ABD12DCC65107569F71B48D75DBA40E12837BA3483E + size: 438272 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/d5cd1f69d20002b3d97e9e94b5a4ffca/winrt%20intellisense%20uap%20-%20en-us-x86_en-us.msi + - fileName: Installers\WinRT Intellisense UAP - Other Languages-x86_en-us.msi + sha256: DD26A598E6C4279214CAF0791B4B1CABED91135C44520B0EFB372A0DD378A32B + size: 507904 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/ae2f6b381f4690f936a2b45a2ded569d/winrt%20intellisense%20uap%20-%20other%20languages-x86_en-us.msi + - fileName: Redistributable\10.1.0.0\UAPSDKAddOn-x86.msi + sha256: C7E425D05559A1BE94A1CE794A8D33ECF1CD2B05BF8D51E998C4EE098349E853 + size: 221184 + url: https://download.visualstudio.microsoft.com/download/pr/c001d4bb-6b32-4ca0-896e-7e0e82df71eb/45514db3ac1acd367ac9f365bd338940/uapsdkaddon-x86.msi + type: Exe + version: 10.0.22621.5 + diff --git a/build/win32/__init__.py b/build/win32/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/build/win32/__init__.py diff --git a/build/win32/autowinchecksec.py b/build/win32/autowinchecksec.py new file mode 100644 index 0000000000..1803d407e8 --- /dev/null +++ b/build/win32/autowinchecksec.py @@ -0,0 +1,85 @@ +#!/usr/bin/env 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/. + +# run the Winchecksec tool (https://github.com/trailofbits/winchecksec) +# against a given Windows binary. + +import json +import subprocess +import sys + +import buildconfig + +# usage +if len(sys.argv) != 2: + print("""usage : autowinchecksec.by path_to_binary""") + sys.exit(0) + +binary_path = sys.argv[1] + +# execute winchecksec against the binary, using the WINCHECKSEC environment +# variable as the path to winchecksec.exe +try: + winchecksec_path = buildconfig.substs["WINCHECKSEC"] +except KeyError: + print( + "TEST-UNEXPECTED-FAIL | autowinchecksec.py | WINCHECKSEC environment variable is " + "not set, can't check DEP/ASLR etc. status." + ) + sys.exit(1) + +wine = buildconfig.substs.get("WINE") +if wine and winchecksec_path.lower().endswith(".exe"): + cmd = [wine, winchecksec_path] +else: + cmd = [winchecksec_path] + +try: + result = subprocess.check_output(cmd + ["-j", binary_path], universal_newlines=True) + +except subprocess.CalledProcessError as e: + print( + "TEST-UNEXPECTED-FAIL | autowinchecksec.py | Winchecksec returned error code %d:\n%s" + % (e.returncode, e.output) + ) + sys.exit(1) + + +result = json.loads(result) + +checks = [ + "aslr", + "cfg", + "dynamicBase", + "gs", + "isolation", + "nx", + "seh", +] + +if buildconfig.substs["TARGET_CPU"] == "x86": + checks += [ + "safeSEH", + ] +else: + checks += [ + "highEntropyVA", + ] + +failed = [c for c in checks if result.get(c) is False] + +if failed: + print( + "TEST-UNEXPECTED-FAIL | autowinchecksec.py | Winchecksec reported %d error(s) for %s" + % (len(failed), binary_path) + ) + print( + "TEST-UNEXPECTED-FAIL | autowinchecksec.py | The following check(s) failed: %s" + % (", ".join(failed)) + ) + sys.exit(1) +else: + print("TEST-PASS | autowinchecksec.py | %s succeeded" % binary_path) diff --git a/build/win32/crashinject.cpp b/build/win32/crashinject.cpp new file mode 100644 index 0000000000..076e5a12a2 --- /dev/null +++ b/build/win32/crashinject.cpp @@ -0,0 +1,94 @@ +/* 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 PID, this program attempts to inject a DLL into the process + * with that PID. The DLL it attempts to inject, "crashinjectdll.dll", + * must exist alongside this exe. The DLL will then crash the process. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <windows.h> + +int main(int argc, char** argv) { + if (argc != 2) { + fprintf(stderr, "Usage: crashinject <PID>\n"); + return 1; + } + + int pid = atoi(argv[1]); + if (pid <= 0) { + fprintf(stderr, "Usage: crashinject <PID>\n"); + return 1; + } + + // find our DLL to inject + wchar_t filename[_MAX_PATH]; + if (GetModuleFileNameW(nullptr, filename, + sizeof(filename) / sizeof(wchar_t)) == 0) + return 1; + + wchar_t* slash = wcsrchr(filename, L'\\'); + if (slash == nullptr) return 1; + + slash++; + wcscpy(slash, L"crashinjectdll.dll"); + + // now find our target process + HANDLE targetProc = + OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | + PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION, + FALSE, pid); + if (targetProc == nullptr) { + fprintf(stderr, "Error %lu opening target process\n", GetLastError()); + return 1; + } + + /* + * This is sort of insane, but we're implementing a technique described here: + * http://www.codeproject.com/KB/threads/winspy.aspx#section_2 + * + * The gist is to use CreateRemoteThread to create a thread in the other + * process, but cheat and make the thread function kernel32!LoadLibrary, + * so that the only remote data we have to pass to the other process + * is the path to the library we want to load. The library we're loading + * will then do its dirty work inside the other process. + */ + HMODULE hKernel32 = GetModuleHandleW(L"Kernel32"); + // allocate some memory to hold the path in the remote process + void* pLibRemote = VirtualAllocEx(targetProc, nullptr, sizeof(filename), + MEM_COMMIT, PAGE_READWRITE); + if (pLibRemote == nullptr) { + fprintf(stderr, "Error %lu in VirtualAllocEx\n", GetLastError()); + CloseHandle(targetProc); + return 1; + } + + if (!WriteProcessMemory(targetProc, pLibRemote, (void*)filename, + sizeof(filename), nullptr)) { + fprintf(stderr, "Error %lu in WriteProcessMemory\n", GetLastError()); + VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE); + CloseHandle(targetProc); + return 1; + } + // Now create a thread in the target process that will load our DLL + HANDLE hThread = CreateRemoteThread( + targetProc, nullptr, 0, + (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW"), + pLibRemote, 0, nullptr); + if (hThread == nullptr) { + fprintf(stderr, "Error %lu in CreateRemoteThread\n", GetLastError()); + VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE); + CloseHandle(targetProc); + return 1; + } + WaitForSingleObject(hThread, INFINITE); + // Cleanup, not that it's going to matter at this point + CloseHandle(hThread); + VirtualFreeEx(targetProc, pLibRemote, sizeof(filename), MEM_RELEASE); + CloseHandle(targetProc); + + return 0; +} diff --git a/build/win32/crashinjectdll/crashinjectdll.cpp b/build/win32/crashinjectdll/crashinjectdll.cpp new file mode 100644 index 0000000000..7ee7e6812d --- /dev/null +++ b/build/win32/crashinjectdll/crashinjectdll.cpp @@ -0,0 +1,29 @@ +/* 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 <stdio.h> +#include <windows.h> + +// make sure we only ever spawn one thread +DWORD tid = -1; + +DWORD WINAPI CrashingThread(LPVOID lpParameter) { + // not a very friendly DLL + volatile int* x = (int*)0x0; + *x = 1; + return 0; +} + +BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved) { + if (tid == (DWORD)-1) + // we have to crash on another thread because LoadLibrary() will + // catch memory access errors and return failure to the calling process + CreateThread(nullptr, // default security attributes + 0, // use default stack size + CrashingThread, // thread function name + nullptr, // argument to thread function + 0, // use default creation flags + &tid); // returns the thread identifier + return TRUE; +} diff --git a/build/win32/crashinjectdll/crashinjectdll.def b/build/win32/crashinjectdll/crashinjectdll.def new file mode 100644 index 0000000000..d1ea5602da --- /dev/null +++ b/build/win32/crashinjectdll/crashinjectdll.def @@ -0,0 +1,7 @@ +;+# 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/. + +LIBRARY crashinjectdll +EXPORTS + DllMain diff --git a/build/win32/crashinjectdll/moz.build b/build/win32/crashinjectdll/moz.build new file mode 100644 index 0000000000..ff113f61e6 --- /dev/null +++ b/build/win32/crashinjectdll/moz.build @@ -0,0 +1,16 @@ +# -*- 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/. + +SOURCES += [ + "crashinjectdll.cpp", +] + +SharedLibrary("crashinjectdll") + +DEFFILE = "crashinjectdll.def" + +USE_STATIC_LIBS = True +NO_PGO = True diff --git a/build/win32/dummy_libs.py b/build/win32/dummy_libs.py new file mode 100644 index 0000000000..16947c6c84 --- /dev/null +++ b/build/win32/dummy_libs.py @@ -0,0 +1,24 @@ +# 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/. + +import os +import subprocess + +from buildconfig import substs + + +def main(output, *other_libs): + output.close() + # ar doesn't like it when the file exists beforehand. + os.unlink(output.name) + libs = [output.name] + parent = os.path.dirname(output.name) + libs.extend(os.path.join(parent, l) for l in other_libs) + for lib in libs: + result = subprocess.run( + [substs["AR"]] + [f.replace("$@", lib) for f in substs["AR_FLAGS"]] + ) + if result.returncode != 0: + return result.returncode + return 0 diff --git a/build/win32/moz.build b/build/win32/moz.build new file mode 100644 index 0000000000..d8d61a22db --- /dev/null +++ b/build/win32/moz.build @@ -0,0 +1,32 @@ +# -*- 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/. + +TEST_DIRS += ["crashinjectdll"] + +if CONFIG["ENABLE_TESTS"]: + Program("crashinject") + SOURCES += [ + "crashinject.cpp", + ] + USE_STATIC_LIBS = True + +NO_PGO = True + +# See comment about *-windows-gnu targets in config/makefiles/rust.mk +if CONFIG["CC_TYPE"] == "clang": + GeneratedFile( + "libgcc.a", + "libgcc_eh.a", + "libpthread.a", + script="dummy_libs.py", + flags=["libgcc_eh.a", "libpthread.a"], + ) + + +if CONFIG["WIN32_REDIST_DIR"] and CONFIG["COMPILE_ENVIRONMENT"]: + for f in ["MSVC_C_RUNTIME_DLL", "MSVC_C_RUNTIME_1_DLL", "MSVC_CXX_RUNTIME_DLL"]: + if CONFIG[f]: + FINAL_TARGET_FILES += ["%%%s/%s" % (CONFIG["WIN32_REDIST_DIR"], CONFIG[f])] diff --git a/build/win32/mozconfig.vs-latest b/build/win32/mozconfig.vs-latest new file mode 100644 index 0000000000..1d5b73148d --- /dev/null +++ b/build/win32/mozconfig.vs-latest @@ -0,0 +1,3 @@ +. $topsrcdir/build/win32/mozconfig.vs2019 +. "$topsrcdir/build/mozconfig.clang-cl" +. "$topsrcdir/build/mozconfig.lld-link" diff --git a/build/win32/mozconfig.vs2019 b/build/win32/mozconfig.vs2019 new file mode 100644 index 0000000000..5dc7574744 --- /dev/null +++ b/build/win32/mozconfig.vs2019 @@ -0,0 +1,10 @@ +if [ -z "${VSPATH}" ]; then + VSPATH="$(cd ${MOZ_FETCHES_DIR} && pwd)/vs" +fi + +if [ -d "${VSPATH}" ]; then + export WIN32_REDIST_DIR="${VSPATH}/VC/Redist/MSVC/14.29.30133/x86/Microsoft.VC142.CRT" + export WINSYSROOT="${VSPATH}" +fi + +ac_add_options --target=i686-pc-windows-msvc diff --git a/build/win32/nsis-no-insert-timestamp.patch b/build/win32/nsis-no-insert-timestamp.patch new file mode 100644 index 0000000000..8053b820c6 --- /dev/null +++ b/build/win32/nsis-no-insert-timestamp.patch @@ -0,0 +1,27 @@ +diff -ur nsis-3.03-src/SCons/Config/gnu nsis-3.03-src.n/SCons/Config/gnu +--- nsis-3.03-src/SCons/Config/gnu 2017-10-06 15:30:20.000000000 -0400 ++++ nsis-3.03-src.n/SCons/Config/gnu 2018-06-17 13:26:05.945495151 -0400 +@@ -102,6 +102,7 @@ + stub_env.Append(LINKFLAGS = ['$NODEFLIBS_FLAG']) # no standard libraries + stub_env.Append(LINKFLAGS = ['$ALIGN_FLAG']) # 512 bytes align + stub_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file ++stub_env.Append(LINKFLAGS = ['-Wl,--no-insert-timestamp']) # remove timestamps for reproducible builds + + stub_uenv = stub_env.Clone() + stub_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE']) +@@ -142,6 +143,7 @@ + plugin_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file + plugin_env.Append(LINKFLAGS = ['-static-libgcc']) # remove libgcc*.dll dependency + plugin_env.Append(LINKFLAGS = ['-static-libstdc++']) # remove libstdc++*.dll dependency ++plugin_env.Append(LINKFLAGS = ['-Wl,--no-insert-timestamp']) # remove timestamps for reproducible builds + + plugin_uenv = plugin_env.Clone() + plugin_uenv.Append(CPPDEFINES = ['_UNICODE', 'UNICODE']) +@@ -181,6 +183,7 @@ + + util_env.Append(LINKFLAGS = ['-mwindows']) # build windows executables + util_env.Append(LINKFLAGS = ['$ALIGN_FLAG']) # 512 bytes align ++util_env.Append(LINKFLAGS = ['-Wl,--no-insert-timestamp']) # remove timestamps for reproducible builds + + + conf = FlagsConfigure(util_env) diff --git a/build/win32/nsis-no-underscore.patch b/build/win32/nsis-no-underscore.patch new file mode 100644 index 0000000000..79cff1d4b3 --- /dev/null +++ b/build/win32/nsis-no-underscore.patch @@ -0,0 +1,34 @@ +The `_` environment variable is a variable that is set by bash and some other +shells to point to the executable they use when executing a command. That is, +when executing `foo` from the command line, the shell sets `_` to +`/usr/bin/foo` (assuming that's where foo is). + +However, nothing else does the same, so when e.g. a python program uses +`subprocess.Popen` to run another program, it doesn't set `_`. Worse, if that +python program itself was invoked from a shell, `_` would be set to e.g. +`/usr/bin/python3`. + +So when nsis is invoked from a program that is not a shell, but the process +ancestry has a process that was a shell, `_` may be set to the first +intermediary program rather than nsis, which defeats nsis's assumption that `_` +would contain the nsis path. Ironically, nsis also has more reliable fallbacks +(using e.g. /proc/self/exe), but somehow prefers `_`. + +We remove the reliance of `_` entirely, for simplicity's sake. + + +diff -ruN nsis-3.07-src.orig/Source/util.cpp nsis-3.07-src/Source/util.cpp +--- nsis-3.07-src.orig/Source/util.cpp 2021-09-02 09:25:48.489016918 +0900 ++++ nsis-3.07-src/Source/util.cpp 2021-09-02 09:26:21.158814484 +0900 +@@ -810,10 +810,7 @@ + assert(rc == 0); + return tstring(CtoTString(temp_buf)); + #else /* Linux/BSD/POSIX/etc */ +- const TCHAR *envpath = _tgetenv(_T("_")); +- if (envpath) +- return get_full_path(envpath); +- else { ++ { + char *path = NULL, *pathtmp; + size_t len = 100; + int nchars; diff --git a/build/win32/nsis-scons.patch b/build/win32/nsis-scons.patch new file mode 100644 index 0000000000..d372ea99ea --- /dev/null +++ b/build/win32/nsis-scons.patch @@ -0,0 +1,23 @@ +Patch from https://sourceforge.net/p/nsis/code/7291/ + +diff -ruN nsis-3.07-src/Contrib/ExDLL/SConscript nsis-3.08-src/Contrib/ExDLL/SConscript +--- nsis-3.07-src/Contrib/ExDLL/SConscript 2015-06-22 01:13:45.000000000 +0900 ++++ nsis-3.08-src/Contrib/ExDLL/SConscript 2021-08-05 05:15:13.000000000 +0900 +@@ -47,7 +47,7 @@ + env.DistributeExamples(api_files, path='Plugin/nsis') + env.DistributeExamples(example, path='Plugin') + if env['PLATFORM'] != 'win32': +- if env.has_key('PREFIX_PLUGINAPI_INC'): ++ if 'PREFIX_PLUGINAPI_INC' in env: + env.Distribute(api_files, None, 'pluginapi_inc', '', 'nsis', 'pluginapi', 'pluginapi') + + +@@ -56,7 +56,7 @@ + else: + example += lib_files + +- if env.has_key('PREFIX_PLUGINAPI_LIB'): ++ if 'PREFIX_PLUGINAPI_LIB' in env: + env.Distribute(lib, None, 'pluginapi_lib', '', 'nsis', 'pluginapi', 'pluginapi') + + diff --git a/build/win64-aarch64/mozconfig.vs-latest b/build/win64-aarch64/mozconfig.vs-latest new file mode 100644 index 0000000000..2d7e28ae08 --- /dev/null +++ b/build/win64-aarch64/mozconfig.vs-latest @@ -0,0 +1,3 @@ +. $topsrcdir/build/win64-aarch64/mozconfig.vs2019 +. "$topsrcdir/build/mozconfig.clang-cl" +. "$topsrcdir/build/mozconfig.lld-link" diff --git a/build/win64-aarch64/mozconfig.vs2019 b/build/win64-aarch64/mozconfig.vs2019 new file mode 100644 index 0000000000..ac2e7eefe3 --- /dev/null +++ b/build/win64-aarch64/mozconfig.vs2019 @@ -0,0 +1,8 @@ +if [ -z "${VSPATH}" ]; then + VSPATH="$(cd ${MOZ_FETCHES_DIR} && pwd)/vs" +fi + +if [ -d "${VSPATH}" ]; then + export WIN32_REDIST_DIR="${VSPATH}/VC/Redist/MSVC/14.29.30133/arm64/Microsoft.VC142.CRT" + export WINSYSROOT="${VSPATH}" +fi diff --git a/build/win64/mozconfig.asan b/build/win64/mozconfig.asan new file mode 100644 index 0000000000..8aa1810b78 --- /dev/null +++ b/build/win64/mozconfig.asan @@ -0,0 +1,23 @@ +. "$topsrcdir/browser/config/mozconfigs/win64/common-win64" + +if [ -d "$MOZ_FETCHES_DIR/clang" ]; then + CLANG_LIB_DIR="$(cd $MOZ_FETCHES_DIR/clang/lib/clang/* && cd lib/windows && pwd)" + + export LDFLAGS="clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib" + + export MOZ_COPY_PDBS=1 + export LLVM_SYMBOLIZER="$MOZ_FETCHES_DIR/llvm-symbolizer/bin/llvm-symbolizer.exe" + export MOZ_CLANG_RT_ASAN_LIB_PATH="${CLANG_LIB_DIR}/clang_rt.asan_dynamic-x86_64.dll" +fi + +# Enable ASan specific code and build workarounds +ac_add_options --enable-address-sanitizer + +# Mandatory options required for ASan builds +ac_add_options --enable-debug-symbols +ac_add_options --disable-jemalloc +ac_add_options --disable-crashreporter +ac_add_options --disable-profiling + +. "$topsrcdir/build/mozconfig.clang-cl" +. "$topsrcdir/build/mozconfig.lld-link" diff --git a/build/win64/mozconfig.vs-latest b/build/win64/mozconfig.vs-latest new file mode 100644 index 0000000000..4caed70ae7 --- /dev/null +++ b/build/win64/mozconfig.vs-latest @@ -0,0 +1,3 @@ +. $topsrcdir/build/win64/mozconfig.vs2019 +. "$topsrcdir/build/mozconfig.clang-cl" +. "$topsrcdir/build/mozconfig.lld-link" diff --git a/build/win64/mozconfig.vs2019 b/build/win64/mozconfig.vs2019 new file mode 100644 index 0000000000..e0d5da8203 --- /dev/null +++ b/build/win64/mozconfig.vs2019 @@ -0,0 +1,8 @@ +if [ -z "${VSPATH}" ]; then + VSPATH="$(cd ${MOZ_FETCHES_DIR} && pwd)/vs" +fi + +if [ -d "${VSPATH}" ]; then + export WIN32_REDIST_DIR=${VSPATH}/VC/Redist/MSVC/14.29.30133/x64/Microsoft.VC142.CRT + export WINSYSROOT="${VSPATH}" +fi diff --git a/build/workspace-hack/Cargo.toml b/build/workspace-hack/Cargo.toml new file mode 100644 index 0000000000..6e3243d211 --- /dev/null +++ b/build/workspace-hack/Cargo.toml @@ -0,0 +1,192 @@ +[package] +name = "mozilla-central-workspace-hack" +version = "0.1.0" +license = "MPL-2.0" +description = "Workspace hack for mozilla-central" + +# This is a hack to help rust code in the tree that are built by different +# invocations of cargo share dependencies rather than rebuilding them. This is +# based on the "rustc-workspace-hack" used by the rustc build system to achieve +# the same. From the description of the issue given there: +# +# "Each time Cargo runs a build it will re-resolve the dependency graph, " +# "notably selecting different features sometimes for each build." +# +# We work around this by specifying the union of the set of features selected +# by dependencies in each cargo invocation for each instance they would differ. + +[dependencies] +arrayvec = { version = "0.7", features = ["serde"], optional = true } +bitflags = { version = "2", features = ["serde", "std"], optional = true } +bytes = { version = "1", optional = true } +chrono = { version = "0.4", features = ["serde"], optional = true } +env_logger = { version = "0.10", default-features = false, features = ["color"], optional = true } +flate2 = { version = "1", optional = true } +futures-channel = { version = "0.3", features = ["sink"], optional = true } +futures-sink = { version = "0.3", optional = true } +futures-core = { version = "0.3", optional = true } +futures-util = { version = "0.3", features = ["channel", "io", "sink"], optional = true } +getrandom = { version = "0.2", default-features = false, features = ["std"], optional = true } +hashbrown = { version = "0.12", optional = true } +hyper = { version = "0.14", features = ["full"], optional = true } +indexmap = { version = "1", default-features = false, features = ["serde-1", "std"], optional = true } +libc = { version = "0.2", features = ["extra_traits"] } +log = { version = "0.4", features = ["release_max_level_info"], optional = true } +mio = { version = "0.8", features = ["log"], optional = true } +num-integer = { version = "0.1", optional = true } +num-traits = { version = "0.2", features = ["i128", "libm"], optional = true } +once_cell = { version = "1", optional = true } +regex = { version = "1", optional = true } +semver = { version = "1", features = ["serde"], optional = true } +serde = { version = "1", features = ["derive", "rc"] } +serde_json = { version = "1", features = ["preserve_order", "unbounded_depth"], optional = true } +smallvec = { version = "1", features = ["const_new", "serde", "union"], optional = true } +time = { version = "0.3", features = ["macros", "parsing"], optional = true } +tokio = { version = "1", features = ["fs", "num_cpus", "rt-multi-thread"], optional = true } +tokio-util = { version = "0.7", features = ["io"], optional = true } +tracing = { version = "0.1", features = ["log"], optional = true } +url = { version = "2", features = ["serde"], optional = true } +uuid = { version = "1", features = ["serde", "v4"], optional = true } + +[target."cfg(windows)".dependencies] +scopeguard = { version = "1", optional = true } + +[build-dependencies] +bindgen = { version = "0.69", default-features = false, features = ["runtime"], optional = true } +cc = { version = "1.0", features = ["parallel"], optional = true } +libc = "0.2" +memchr = { version = "2", optional = true } +nom = { version = "7", optional = true } +proc-macro2 = "1" +quote = "1" +regex = { version = "1", default-features = false, features = ["perf"], optional = true } +semver = { version = "1", features = ["serde"], optional = true } +serde = { version = "1", features = ["derive"] } +syn = { version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } + +[target."cfg(windows)".dependencies.winapi] +version = "0.3.6" +features = [ + "avrt", + "basetsd", + "bits", + "bits2_5", + "bitsmsg", + "cfg", + "combaseapi", + "consoleapi", + "d3d11", + "d3d11_1", + "d3d11_2", + "d3d11sdklayers", + "d3d12", + "d3d12sdklayers", + "d3d12shader", + "d3dcommon", + "d3dcompiler", + "dcomp", + "dwrite", + "dwrite_1", + "dwrite_3", + "dxgi1_2", + "dxgi1_3", + "dxgi1_4", + "dxgi1_5", + "dxgi1_6", + "dxgidebug", + "dxgiformat", + "errhandlingapi", + "evntrace", + "fileapi", + "guiddef", + "handleapi", + "hidclass", + "hidpi", + "hidusage", + "impl-debug", + "impl-default", + "in6addr", + "inaddr", + "ioapiset", + "knownfolders", + "libloaderapi", + "memoryapi", + "minwinbase", + "minwindef", + "mmeapi", + "mmsystem", + "mswsock", + "namedpipeapi", + "ntdef", + "ntsecapi", + "ntstatus", + "oaidl", + "objbase", + "oleauto", + "processenv", + "processthreadsapi", + "profileapi", + "psapi", + "rpcndr", + "setupapi", + "shlobj", + "std", + "synchapi", + "sysinfoapi", + "taskschd", + "timeapi", + "timezoneapi", + "unknwnbase", + "winbase", + "wincon", + "wincrypt", + "windef", + "winerror", + "wininet", + "winioctl", + "winnls", + "winnt", + "winreg", + "winsock2", + "winuser", + "ws2def", + "ws2ipdef", + "ws2tcpip", + "wtypes", + "wtypesbase", +] + +[target."cfg(windows)".dependencies.windows-sys] +version = "0.52" +optional = true +features = [ + "Wdk_System_Threading", + "Win32_Foundation", + "Win32_Security", + "Win32_Storage_FileSystem", + "Win32_System_Com", + "Win32_System_Diagnostics_Debug", + "Win32_System_ErrorReporting", + "Win32_System_Kernel", + "Win32_System_LibraryLoader", + "Win32_System_Memory", + "Win32_System_Pipes", + "Win32_System_ProcessStatus", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", +] + + +[features] +builtins-static = ["dep:bindgen", "dep:bitflags", "dep:memchr", "dep:nom", "dep:regex", "dep:smallvec"] +geckodriver = ["dep:bitflags", "dep:bytes", "dep:cc", "dep:chrono", "dep:flate2", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hyper", "dep:indexmap", "dep:log", "dep:memchr", "dep:mio", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:semver", "dep:serde_json", "dep:smallvec", "dep:time", "dep:tokio", "dep:tokio-util", "dep:tracing", "dep:url", "dep:uuid", "dep:windows-sys"] +gkrust = ["dep:arrayvec", "dep:bindgen", "dep:bitflags", "dep:bytes", "dep:cc", "dep:chrono", "dep:env_logger", "dep:flate2", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:memchr", "dep:nom", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:scopeguard", "dep:semver", "dep:serde_json", "dep:smallvec", "dep:time", "dep:url", "dep:uuid", "dep:windows-sys"] +gkrust-gtest = ["gkrust"] +http3server = ["dep:arrayvec", "dep:bindgen", "dep:bitflags", "dep:bytes", "dep:chrono", "dep:env_logger", "dep:futures-channel", "dep:futures-core", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hyper", "dep:indexmap", "dep:log", "dep:memchr", "dep:mio", "dep:nom", "dep:num-integer", "dep:num-traits", "dep:once_cell", "dep:regex", "dep:serde_json", "dep:smallvec", "dep:time", "dep:tokio", "dep:tokio-util", "dep:tracing", "dep:url", "dep:windows-sys"] +ipcclientcerts-static = ["dep:bindgen", "dep:bitflags", "dep:memchr", "dep:nom", "dep:regex"] +jsrust = ["dep:arrayvec", "dep:cc", "dep:env_logger", "dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:memchr", "dep:num-traits", "dep:once_cell", "dep:semver", "dep:smallvec", "dep:url"] +mozwer_s = ["dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:once_cell", "dep:serde_json", "dep:uuid", "dep:windows-sys"] +osclientcerts-static = ["dep:bindgen", "dep:bitflags", "dep:env_logger", "dep:log", "dep:memchr", "dep:nom", "dep:regex"] diff --git a/build/workspace-hack/src/lib.rs b/build/workspace-hack/src/lib.rs new file mode 100644 index 0000000000..b15e83eb00 --- /dev/null +++ b/build/workspace-hack/src/lib.rs @@ -0,0 +1,11 @@ +/* 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/. */ + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/build/zstandard_requirements.in b/build/zstandard_requirements.in new file mode 100644 index 0000000000..168042c4bc --- /dev/null +++ b/build/zstandard_requirements.in @@ -0,0 +1,2 @@ +zstandard==0.22.0 + diff --git a/build/zstandard_requirements.txt b/build/zstandard_requirements.txt new file mode 100644 index 0000000000..7553ded463 --- /dev/null +++ b/build/zstandard_requirements.txt @@ -0,0 +1,54 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --generate-hashes --output-file=build/zstandard_requirements.txt build/zstandard_requirements.in +# +zstandard==0.22.0 \ + --hash=sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd \ + --hash=sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2 \ + --hash=sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356 \ + --hash=sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf \ + --hash=sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004 \ + --hash=sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69 \ + --hash=sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019 \ + --hash=sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a \ + --hash=sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440 \ + --hash=sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b \ + --hash=sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775 \ + --hash=sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e \ + --hash=sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc \ + --hash=sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d \ + --hash=sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09 \ + --hash=sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c \ + --hash=sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe \ + --hash=sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88 \ + --hash=sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94 \ + --hash=sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08 \ + --hash=sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0 \ + --hash=sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a \ + --hash=sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292 \ + --hash=sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93 \ + --hash=sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70 \ + --hash=sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8 \ + --hash=sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2 \ + --hash=sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45 \ + --hash=sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202 \ + --hash=sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3 \ + --hash=sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb \ + --hash=sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4 \ + --hash=sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d \ + --hash=sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c \ + --hash=sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f \ + --hash=sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26 \ + --hash=sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303 \ + --hash=sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df \ + --hash=sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e \ + --hash=sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73 \ + --hash=sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c \ + --hash=sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2 \ + --hash=sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0 \ + --hash=sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375 \ + --hash=sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912 \ + --hash=sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e + # via -r build/zstandard_requirements.in |