diff --git a/.github/agents/agentic-workflows.agent.md b/.github/agents/agentic-workflows.agent.md new file mode 100644 index 000000000000..b6e648cbda58 --- /dev/null +++ b/.github/agents/agentic-workflows.agent.md @@ -0,0 +1,196 @@ +--- +description: GitHub Agentic Workflows (gh-aw) - Create, debug, and upgrade AI-powered workflows with intelligent prompt routing +disable-model-invocation: true +--- + +# GitHub Agentic Workflows Agent + +This agent helps you work with **GitHub Agentic Workflows (gh-aw)**, a CLI extension for creating AI-powered workflows in natural language using markdown files. + +## What This Agent Does + +This is a **dispatcher agent** that routes your request to the appropriate specialized prompt based on your task: + +- **Creating new workflows**: Routes to `create` prompt +- **Updating existing workflows**: Routes to `update` prompt +- **Debugging workflows**: Routes to `debug` prompt +- **Upgrading workflows**: Routes to `upgrade-agentic-workflows` prompt +- **Creating report-generating workflows**: Routes to `report` prompt — consult this whenever the workflow posts status updates, audits, analyses, or any structured output as issues, discussions, or comments +- **Creating shared components**: Routes to `create-shared-agentic-workflow` prompt +- **Fixing Dependabot PRs**: Routes to `dependabot` prompt — use this when Dependabot opens PRs that modify generated manifest files (`.github/workflows/package.json`, `.github/workflows/requirements.txt`, `.github/workflows/go.mod`). Never merge those PRs directly; instead update the source `.md` files and rerun `gh aw compile --dependabot` to bundle all fixes +- **Analyzing test coverage**: Routes to `test-coverage` prompt — consult this whenever the workflow reads, analyzes, or reports on test coverage data from PRs or CI runs +- **CLI commands and triggering workflows**: Routes to `cli-commands` guide — consult this whenever the user asks how to run, compile, debug, or manage workflows from the command line, or when they need the MCP tool equivalent of a `gh aw` command + +Workflows may optionally include: + +- **Project tracking / monitoring** (GitHub Projects updates, status reporting) +- **Orchestration / coordination** (one workflow assigning agents or dispatching and coordinating other workflows) + +## Files This Applies To + +- Workflow files: `.github/workflows/*.md` and `.github/workflows/**/*.md` +- Workflow lock files: `.github/workflows/*.lock.yml` +- Shared components: `.github/workflows/shared/*.md` +- Configuration: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/github-agentic-workflows.md + +## Problems This Solves + +- **Workflow Creation**: Design secure, validated agentic workflows with proper triggers, tools, and permissions +- **Workflow Debugging**: Analyze logs, identify missing tools, investigate failures, and fix configuration issues +- **Version Upgrades**: Migrate workflows to new gh-aw versions, apply codemods, fix breaking changes +- **Component Design**: Create reusable shared workflow components that wrap MCP servers + +## How to Use + +When you interact with this agent, it will: + +1. **Understand your intent** - Determine what kind of task you're trying to accomplish +2. **Route to the right prompt** - Load the specialized prompt file for your task +3. **Execute the task** - Follow the detailed instructions in the loaded prompt + +## Available Prompts + +### Create New Workflow +**Load when**: User wants to create a new workflow from scratch, add automation, or design a workflow that doesn't exist yet + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/create-agentic-workflow.md + +**Use cases**: +- "Create a workflow that triages issues" +- "I need a workflow to label pull requests" +- "Design a weekly research automation" + +### Update Existing Workflow +**Load when**: User wants to modify, improve, or refactor an existing workflow + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/update-agentic-workflow.md + +**Use cases**: +- "Add web-fetch tool to the issue-classifier workflow" +- "Update the PR reviewer to use discussions instead of issues" +- "Improve the prompt for the weekly-research workflow" + +### Debug Workflow +**Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/debug-agentic-workflow.md + +**Use cases**: +- "Why is this workflow failing?" +- "Analyze the logs for workflow X" +- "Investigate missing tool calls in run #12345" + +### Upgrade Agentic Workflows +**Load when**: User wants to upgrade workflows to a new gh-aw version or fix deprecations + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/upgrade-agentic-workflows.md + +**Use cases**: +- "Upgrade all workflows to the latest version" +- "Fix deprecated fields in workflows" +- "Apply breaking changes from the new release" + +### Create a Report-Generating Workflow +**Load when**: The workflow being created or updated produces reports — recurring status updates, audit summaries, analyses, or any structured output posted as a GitHub issue, discussion, or comment + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/report.md + +**Use cases**: +- "Create a weekly CI health report" +- "Post a daily security audit to Discussions" +- "Add a status update comment to open PRs" + +### Create Shared Agentic Workflow +**Load when**: User wants to create a reusable workflow component or wrap an MCP server + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/create-shared-agentic-workflow.md + +**Use cases**: +- "Create a shared component for Notion integration" +- "Wrap the Slack MCP server as a reusable component" +- "Design a shared workflow for database queries" + +### Fix Dependabot PRs +**Load when**: User needs to close or fix open Dependabot PRs that update dependencies in generated manifest files (`.github/workflows/package.json`, `.github/workflows/requirements.txt`, `.github/workflows/go.mod`) + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/dependabot.md + +**Use cases**: +- "Fix the open Dependabot PRs for npm dependencies" +- "Bundle and close the Dependabot PRs for workflow dependencies" +- "Update @playwright/test to fix the Dependabot PR" + +### Analyze Test Coverage +**Load when**: The workflow reads, analyzes, or reports test coverage — whether triggered by a PR, a schedule, or a slash command. Always consult this prompt before designing the coverage data strategy. + +**Prompt file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/test-coverage.md + +**Use cases**: +- "Create a workflow that comments coverage on PRs" +- "Analyze coverage trends over time" +- "Add a coverage gate that blocks PRs below a threshold" + +### CLI Commands Reference +**Load when**: The user asks how to run, compile, debug, or manage workflows from the command line; needs the MCP tool equivalent of a `gh aw` command; or is in a restricted environment (e.g., Copilot Cloud) without direct CLI access. + +**Reference file**: https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/cli-commands.md + +**Use cases**: +- "How do I trigger workflow X on the main branch?" +- "What's the MCP equivalent of `gh aw logs`?" +- "I'm in Copilot Cloud — how do I compile a workflow?" +- "Show me all available gh aw commands" + +## Instructions + +When a user interacts with you: + +1. **Identify the task type** from the user's request +2. **Load the appropriate prompt** from the GitHub repository URLs listed above +3. **Follow the loaded prompt's instructions** exactly +4. **If uncertain**, ask clarifying questions to determine the right prompt + +## Quick Reference + +```bash +# Initialize repository for agentic workflows +gh aw init + +# Generate the lock file for a workflow +gh aw compile [workflow-name] + +# Trigger a workflow on demand (preferred over gh workflow run) +gh aw run # interactive input collection +gh aw run --ref main # run on a specific branch + +# Debug workflow runs +gh aw logs [workflow-name] +gh aw audit + +# Upgrade workflows +gh aw fix --write +gh aw compile --validate +``` + +## Key Features of gh-aw + +- **Natural Language Workflows**: Write workflows in markdown with YAML frontmatter +- **AI Engine Support**: Copilot, Claude, Codex, or custom engines +- **MCP Server Integration**: Connect to Model Context Protocol servers for tools +- **Safe Outputs**: Structured communication between AI and GitHub API +- **Strict Mode**: Security-first validation and sandboxing +- **Shared Components**: Reusable workflow building blocks +- **Repo Memory**: Persistent git-backed storage for agents +- **Sandboxed Execution**: All workflows run in the Agent Workflow Firewall (AWF) sandbox, enabling full `bash` and `edit` tools by default + +## Important Notes + +- Always reference the instructions file at https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/github-agentic-workflows.md for complete documentation +- Use the MCP tool `agentic-workflows` when running in GitHub Copilot Cloud +- Workflows must be compiled to `.lock.yml` files before running in GitHub Actions +- **Bash tools are enabled by default** - Don't restrict bash commands unnecessarily since workflows are sandboxed by the AWF +- Follow security best practices: minimal permissions, explicit network access, no template injection +- **Network configuration**: Use ecosystem identifiers (`node`, `python`, `go`, etc.) or explicit FQDNs in `network.allowed`. Bare shorthands like `npm` or `pypi` are **not** valid. See https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/network.md for the full list of valid ecosystem identifiers and domain patterns. +- **Single-file output**: When creating a workflow, produce exactly **one** workflow `.md` file. Do not create separate documentation files (architecture docs, runbooks, usage guides, etc.). If documentation is needed, add a brief `## Usage` section inside the workflow file itself. +- **Triggering runs**: Always use `gh aw run ` to trigger a workflow on demand — not `gh workflow run .lock.yml`. `gh aw run` handles workflow resolution by short name, input parsing and validation, and correct run-tracking for agentic workflows. Use `--ref ` to run on a specific branch. +- **CLI commands reference**: For a complete guide on all `gh aw` commands and their MCP tool equivalents (for restricted environments), see https://github.com/github/gh-aw/blob/v0.71.5/.github/aw/cli-commands.md diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index e44fd6da3ec8..79c34c44d3d7 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -5,10 +5,10 @@ "version": "v9.0.0", "sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3" }, - "github/gh-aw-actions/setup@v0.71.1": { + "github/gh-aw-actions/setup@v0.71.5": { "repo": "github/gh-aw-actions/setup", - "version": "v0.71.1", - "sha": "239aec45b78c8799417efdd5bc6d8cc036629ec1" + "version": "v0.71.5", + "sha": "b8068426813005612b960b5ab0b8bd2c27142323" } }, "containers": { diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 570b20cbd2ba..4cb9965eaa88 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -156,6 +156,7 @@ Common project structure for Apple platform apps: 2. Run `make` to rebuild affected components 3. Test changes using appropriate test suite 4. Verify on both simulator and device when possible +5. Check if the documentation in the `docs/` directory needs to be updated to reflect the changes (e.g. new MSBuild properties should be documented in `docs/building-apps/build-properties.md`) ### Code Style diff --git a/.github/skills/macios-reviewer/SKILL.md b/.github/skills/macios-reviewer/SKILL.md index 4e58caf65a61..196852d33fcd 100644 --- a/.github/skills/macios-reviewer/SKILL.md +++ b/.github/skills/macios-reviewer/SKILL.md @@ -97,6 +97,13 @@ Post your findings directly: If no issues found **and CI is green**, submit with at most one or two 💡 suggestions and a positive summary. Truly trivial PRs (dependency bumps, 1-line typo fixes) may have no inline comments. +**Review event to submit:** +- If there are ❌ **error** issues → submit as `REQUEST_CHANGES`. +- If there are no ❌ **error** issues (only warnings/suggestions or clean) → submit as `COMMENT`. +- **Never submit `APPROVE`.** + +This is especially important on re-reviews: if a previous review requested changes and those changes have been addressed, submitting a `COMMENT` review replaces the previous `REQUEST_CHANGES` state, clearing the "changes requested" flag on the PR. + **Copilot-authored PRs:** If the PR author is `Copilot` (the GitHub Copilot coding agent) and the verdict is ⚠️ Needs Changes or ❌ Reject, prefix the review summary with `@copilot ` so the comment automatically triggers Copilot to address the feedback. Do NOT add the prefix for ✅ LGTM verdicts. ## Comment format diff --git a/.github/workflows/code-radiator.lock.yml b/.github/workflows/code-radiator.lock.yml new file mode 100644 index 000000000000..7c9e915f63c0 --- /dev/null +++ b/.github/workflows/code-radiator.lock.yml @@ -0,0 +1,1491 @@ +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"76af0f752f9c80c182f233d9269f96cb4486de4da16d47dd58abdbd52c4ef543","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot","agent_model":"claude-sonnet-4.5"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.71.5). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - COPILOT_GITHUB_TOKEN +# - GH_AW_CI_TRIGGER_TOKEN +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# +# Custom actions used: +# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 +# +# Container images used: +# - ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 +# - ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c +# - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 +# - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + +name: "Code Radiator" +"on": + # roles: # Roles processed as role check in pre-activation job + # - admin # Roles processed as role check in pre-activation job + # - maintainer # Roles processed as role check in pre-activation job + # - write # Roles processed as role check in pre-activation job + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + inputs: + aw_context: + default: "" + description: Agent caller context (used internally by Agentic Workflows). + required: false + type: string + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}" + +run-name: "Code Radiator" + +jobs: + activation: + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + outputs: + comment_id: "" + comment_repo: "" + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Code Radiator" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/code-radiator.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" + - name: Generate agentic run info + id: generate_aw_info + env: + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: "claude-sonnet-4.5" + GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_AGENT_VERSION: "1.0.40" + GH_AW_INFO_CLI_VERSION: "v0.71.5" + GH_AW_INFO_WORKFLOW_NAME: "Code Radiator" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.25.40" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + .claude + .codex + .crush + .gemini + .opencode + .pi + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_FILE: "code-radiator.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_COMPILED_VERSION: "v0.71.5" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_f18a65bced008989_EOF' + + GH_AW_PROMPT_f18a65bced008989_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_f18a65bced008989_EOF' + + Tools: add_comment(max:10), create_pull_request(max:10), update_pull_request(max:10), add_labels(max:10), push_to_pull_request_branch(max:10), missing_tool, missing_data, noop + GH_AW_PROMPT_f18a65bced008989_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" + cat << 'GH_AW_PROMPT_f18a65bced008989_EOF' + + GH_AW_PROMPT_f18a65bced008989_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_f18a65bced008989_EOF' + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_f18a65bced008989_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_f18a65bced008989_EOF' + + {{#runtime-import .github/workflows/code-radiator.md}} + GH_AW_PROMPT_f18a65bced008989_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + include-hidden-files: true + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: coderadiator + outputs: + agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + model_not_supported_error: ${{ steps.detect-copilot-errors.outputs.model_not_supported_error || 'false' }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Code Radiator" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/code-radiator.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" + - name: Set runtime paths + id: set-runtime-paths + run: | + { + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" + } >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" + - name: Configure gh CLI for GitHub Enterprise + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" + env: + GH_TOKEN: ${{ github.token }} + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.40 + - name: Parse integrity filter lists + id: parse-guard-vars + env: + GH_AW_BLOCKED_USERS_VAR: ${{ vars.GH_AW_GITHUB_BLOCKED_USERS || '' }} + GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} + GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + - name: Generate Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_67dd340333ff2a92_EOF' + {"add_comment":{"max":10},"add_labels":{"max":10},"create_pull_request":{"max":10,"max_patch_files":100,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"]},"create_report_incomplete_issue":{},"merge_pull_request":{"max":10},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_to_pull_request_branch":{"if_no_changes":"warn","max":10,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"]},"report_incomplete":{},"update_pull_request":{"allow_body":true,"allow_title":true,"max":10,"update_branch":false}} + GH_AW_SAFE_OUTPUTS_CONFIG_67dd340333ff2a92_EOF + - name: Generate Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 10 comment(s) can be added. Supports reply_to_id for discussion threading.", + "add_labels": " CONSTRAINTS: Maximum 10 label(s) can be added.", + "create_pull_request": " CONSTRAINTS: Maximum 10 pull request(s) can be created.", + "push_to_pull_request_branch": " CONSTRAINTS: Maximum 10 push(es) can be made.", + "update_pull_request": " CONSTRAINTS: Maximum 10 pull request(s) can be updated." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "add_labels": { + "defaultMax": 5, + "fields": { + "item_number": { + "issueNumberOrTemporaryId": true + }, + "labels": { + "required": true, + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "create_pull_request": { + "defaultMax": 1, + "fields": { + "base": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "merge_pull_request": { + "defaultMax": 1, + "fields": { + "commit_message": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "commit_title": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "merge_method": { + "type": "string", + "enum": [ + "merge", + "squash", + "rebase" + ] + }, + "pull_request_number": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "push_to_pull_request_branch": { + "defaultMax": 1, + "fields": { + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "pull_request_number": { + "issueOrPRNumber": true + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + }, + "update_pull_request": { + "defaultMax": 1, + "fields": { + "body": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "draft": { + "type": "boolean" + }, + "operation": { + "type": "string", + "enum": [ + "replace", + "append", + "prepend" + ] + }, + "pull_request_number": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "update_branch": { + "type": "boolean" + } + }, + "customValidation": "requiresOneOf:title,body,update_branch" + } + } + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6' + + mkdir -p /home/runner/.copilot + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_1fe8f1e7abc04440_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v1.0.3", + "env": { + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "pull_requests,repos" + }, + "guard-policies": { + "allow-only": { + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "min-integrity": "none", + "repos": "all", + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_1fe8f1e7abc04440_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","docs.github.com","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","google/deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.40,squid=sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51,agent=sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504,api-proxy=sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280,cli-proxy=sha256:3e7152911d4b4b7b97beef9d3d7d924ff7902227e86001ef3838fb728d5d514c"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + # shellcheck disable=SC1003 + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_API_KEY: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: claude-sonnet-4.5 + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_VERSION: v0.71.5 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + XDG_CONFIG_HOME: /home/runner + - name: Detect Copilot errors + id: detect-copilot-errors + if: always() + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_copilot_errors.cjs" + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + await main(); + - name: Print AWF reflect summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + await main(); + - name: Write agent output placeholder if missing + if: always() + run: | + if [ ! -f /tmp/gh-aw/agent_output.json ]; then + echo '{"items":[]}' > /tmp/gh-aw/agent_output.json + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/aw-*.patch + /tmp/gh-aw/aw-*.bundle + /tmp/gh-aw/awf-config.json + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/sandbox/firewall/audit/ + /tmp/gh-aw/sandbox/firewall/awf-reflect.json + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-code-radiator" + cancel-in-progress: false + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Code Radiator" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/code-radiator.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Process no-op messages + id: noop + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Code Radiator" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Log detection run + id: detection_runs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Radiator" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Code Radiator" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Code Radiator" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Radiator" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "code-radiator" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" + GH_AW_ENGINE_ID: "copilot" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} + GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} + GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }} + GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }} + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + detection: + needs: + - activation + - agent + if: > + always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_reason: ${{ steps.detection_conclusion.outputs.reason }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Code Radiator" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/code-radiator.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Checkout repository for patch context + if: needs.agent.outputs.has_patch == 'true' + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + # --- Threat Detection --- + - name: Clean stale firewall files from agent artifact + run: | + rm -rf /tmp/gh-aw/sandbox/firewall/logs + rm -rf /tmp/gh-aw/sandbox/firewall/audit + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP Config for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" + rm -f /home/runner/.copilot/mcp-config.json + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + for f in /tmp/gh-aw/aw-*.bundle; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + WORKFLOW_NAME: "Code Radiator" + WORKFLOW_DESCRIPTION: "No description provided" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.40 + - name: Execute GitHub Copilot CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true + id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) + export GH_AW_NODE_BIN + (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.40,squid=sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51,agent=sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504,api-proxy=sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280,cli-proxy=sha256:3e7152911d4b4b7b97beef9d3d7d924ff7902227e86001ef3838fb728d5d514c"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json + # shellcheck disable=SC1003 + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_API_KEY: dummy-byok-key-for-offline-mode + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: claude-sonnet-4.5 + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_VERSION: v0.71.5 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + XDG_CONFIG_HOME: /home/runner + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: detection + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Parse and conclude threat detection + id: detection_conclusion + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + with: + script: | + try { + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + } catch (loadErr) { + const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; + const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); + core.error(msg); + core.setOutput('reason', 'parse_error'); + if (continueOnError) { + core.warning('\u26A0\uFE0F ' + msg); + core.setOutput('conclusion', 'warning'); + core.setOutput('success', 'false'); + } else { + core.setOutput('conclusion', 'failure'); + core.setOutput('success', 'false'); + core.setFailed(msg); + } + } + + safe_outputs: + needs: + - activation + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/code-radiator" + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "claude-sonnet-4.5" + GH_AW_ENGINE_VERSION: "1.0.40" + GH_AW_WORKFLOW_ID: "code-radiator" + GH_AW_WORKFLOW_NAME: "Code Radiator" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }} + created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + push_commit_sha: ${{ steps.process_safe_outputs.outputs.push_commit_sha }} + push_commit_url: ${{ steps.process_safe_outputs.outputs.push_commit_url }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Code Radiator" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/code-radiator.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Checkout repository + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') || (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') || (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,docs.github.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":10},\"add_labels\":{\"max\":10},\"create_pull_request\":{\"max\":10,\"max_patch_files\":100,\"max_patch_size\":1024,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"]},\"create_report_incomplete_issue\":{},\"merge_pull_request\":{\"max\":10},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"push_to_pull_request_branch\":{\"if_no_changes\":\"warn\",\"max\":10,\"max_patch_size\":1024,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"]},\"report_incomplete\":{},\"update_pull_request\":{\"allow_body\":true,\"allow_title\":true,\"max\":10,\"update_branch\":false}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/code-radiator.md b/.github/workflows/code-radiator.md new file mode 100644 index 000000000000..88ef05a185d5 --- /dev/null +++ b/.github/workflows/code-radiator.md @@ -0,0 +1,170 @@ +--- +on: + schedule: "0 0 * * *" + workflow_dispatch: + roles: [admin, maintainer, write] +permissions: + contents: read + pull-requests: read +engine: + id: copilot + model: claude-sonnet-4.5 +network: + allowed: + - defaults + - github +tools: + github: + toolsets: [pull_requests, repos] + min-integrity: none + bash: true +safe-outputs: + create-pull-request: + max: 10 + add-comment: + max: 10 + add-labels: + max: 10 + merge-pull-request: + max: 10 + push-to-pull-request-branch: + max: 10 + update-pull-request: + max: 10 +--- + +# Code Radiator + +Merge code from `main` into active target branches, creating pull requests for each. + +## Target Branch Patterns + +Only consider remote branches matching these patterns: +- `net[0-9]*.0` (e.g., `net11.0`, `net10.0`) +- `xcode[0-9]*` (e.g., `xcode26`) +- `xcode[0-9]*.[0-9]*` (e.g., `xcode26.4`) + +Only process branches that have had commits in the last 30 days. + +## Workflow + +### 1. Identify Target Branches + +```bash +# List remote branches matching target patterns with recent activity +git fetch origin +git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:iso8601)' refs/remotes/origin/ +``` + +Filter to branches matching the patterns above AND having a commit within the last month. + +### 2. For Each Target Branch + +#### a. Determine the local branch name + +The local branch name is: `merge/main-to--` (e.g., `merge/main-to-net11.0-20260506`). + +#### b. Check for existing pull requests + +Search for an open PR with: +- Base: the target branch +- Title matching: `🤖 Merge 'main' => ''` + +If a matching PR exists: +- If it is a **draft**: add a comment saying "⏭️ Skipping merge update: this PR is a draft. Convert to ready when you want automated updates to resume." and **skip** this target. +- If it is **not a draft**: use its head branch name as the local branch name (to update the existing PR). + +#### c. Update from target branch + +If updating an existing PR, first merge the target branch into the PR branch to incorporate any new commits from the target: + +```bash +git checkout -B "" "origin/" +git merge "origin/" --no-edit -m "Merge branch '' into ''" +``` + +If creating a new branch, start from the target: + +```bash +git checkout -B "" "origin/" +``` + +#### d. Merge main + +```bash +git merge origin/main --no-edit -m "Merge branch 'main' into ''" +``` + +#### e. Resolve merge conflicts + +If there are merge conflicts: + +**For files under `tests/dotnet/UnitTests/expected/`:** +- Do not include these files in the merge commit at all. Remove them from the index: + ```bash + git rm --cached + ``` + +**For `eng/Version.Details.props` or `eng/Version.Details.xml`:** +- Parse both the `origin/main` and `origin/` versions of the file as XML. +- For each `` element present in both files, keep the one with the **higher** `` value. +- Use semantic version comparison (split on `.`, `-`, `+` and compare numerically). +- Write the merged result and `git add` the file. + +**For `NuGet.config`:** +- Include all package source feeds from both the source (main) and target branches. +- If a feed exists in both with the same key but different URL, keep both (rename the key from main to avoid collision). +- Write the merged result and `git add` the file. + +**For any other conflicting files:** +- Do your best to resolve them using context and judgment. +- If you resolved any "other" conflicts (not covered by the rules above), mark the PR for human review: + - Do **not** enable automerge (and disable it if already enabled). + - Add the `do-not-merge` label. + - Add a comment requesting human review of the conflict resolution, listing which files were manually resolved. + +#### e. Push and create/update the PR + +```bash +git push origin "" +``` + +- If updating an existing PR: the push is sufficient (the PR updates automatically). +- If creating a new PR: + - Title: `🤖 Merge 'main' => ''` + - Body: `Automated merge of \`main\` into \`\`.\n\nCreated by the code-radiator workflow.` + - Base: the target branch + - Head: the local branch + - Enable automerge (merge strategy) on the new PR. + +### 3. Summary + +After processing all branches, report: +- Which PRs were created (with links) +- Which PRs were updated +- Which branches were skipped (draft PRs, no conflicts resolution possible) +- Which branches had no diff (main already merged) + +## Conflict Resolution Details + +### Version file merge algorithm + +For `eng/Version.Details.props` and `eng/Version.Details.xml`: + +1. Parse both XML files. +2. Build a map of `Dependency[@Name]` → `Version` text from each file. +3. For each dependency present in either file, select the higher version. +4. Use the target branch's file as the base structure, updating versions where main has higher values. +5. Dependencies that exist only in main should be added to the result. + +### Version comparison + +Split version strings on `.`, `-`, and `+`. Compare each segment numerically. Example: +- `9.0.0-preview.1.24080.9` vs `9.0.0-preview.2.24101.3` → second is higher. + +## Important Notes + +- Never force push. Always use regular `git push`. +- The workflow operates on the current repository checkout. +- Run `git fetch origin` before starting to ensure up-to-date remote refs. +- Use `gh` CLI for PR operations (create, comment, list, merge --auto). diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000000..f5f09b80ef69 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,26 @@ +name: "Copilot Setup Steps" + +# This workflow configures the environment for GitHub Copilot Agent with gh-aw MCP server +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + # The job MUST be called 'copilot-setup-steps' to be recognized by GitHub Copilot Agent + copilot-setup-steps: + runs-on: ubuntu-latest + + # Set minimal permissions for setup steps + # Copilot Agent receives its own token with appropriate permissions + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: Install gh-aw extension + uses: github/gh-aw-actions/setup-cli@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 + with: + version: v0.71.5 diff --git a/.github/workflows/inter-branch-merge-flow.yml b/.github/workflows/inter-branch-merge-flow.yml index 35a5b4584b4f..b6b979ddad46 100644 --- a/.github/workflows/inter-branch-merge-flow.yml +++ b/.github/workflows/inter-branch-merge-flow.yml @@ -16,13 +16,13 @@ name: Inter-branch merge workflow on: - push: - branches: - - main + # allow triggering this action manually + workflow_dispatch: - # Run every day at 3:00 AM UTC - schedule: - - cron: '0 3 * * *' +# Disable for now, trying out an agentic workflow +# # Run every day at 3:00 AM UTC +# schedule: +# - cron: '0 3 * * *' permissions: contents: write diff --git a/.github/workflows/macios-reviewer.lock.yml b/.github/workflows/macios-reviewer.lock.yml index 96544eebf0de..9f23069944af 100644 --- a/.github/workflows/macios-reviewer.lock.yml +++ b/.github/workflows/macios-reviewer.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a4ffe1d52364aca7fafba9ba975ec40a3f4fc4908801119268fc1812f9b09cbe","compiler_version":"v0.71.1","strict":true,"agent_id":"copilot","agent_model":"claude-sonnet-4.5"} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"239aec45b78c8799417efdd5bc6d8cc036629ec1","version":"v0.71.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28","digest":"sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28","digest":"sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28","digest":"sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.0","digest":"sha256:9c2228324fb1f26f39dc9471612e530ae3efc3156dac05efb2e8d212878d454d","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.0@sha256:9c2228324fb1f26f39dc9471612e530ae3efc3156dac05efb2e8d212878d454d"},{"image":"ghcr.io/github/github-mcp-server:v1.0.2","digest":"sha256:26db03408086a99cf1916348dcc4f9614206658f9082a8060dc7c81ad787f4ba","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.2@sha256:26db03408086a99cf1916348dcc4f9614206658f9082a8060dc7c81ad787f4ba"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a4ffe1d52364aca7fafba9ba975ec40a3f4fc4908801119268fc1812f9b09cbe","compiler_version":"v0.71.5","strict":true,"agent_id":"copilot","agent_model":"claude-sonnet-4.5"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40","digest":"sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40","digest":"sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40","digest":"sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.6","digest":"sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c"},{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.71.1). DO NOT EDIT. +# This file was automatically generated by gh-aw (v0.71.5). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -32,17 +32,17 @@ # Custom actions used: # - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 -# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 +# - github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb -# - ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474 -# - ghcr.io/github/gh-aw-mcpg:v0.3.0@sha256:9c2228324fb1f26f39dc9471612e530ae3efc3156dac05efb2e8d212878d454d -# - ghcr.io/github/github-mcp-server:v1.0.2@sha256:26db03408086a99cf1916348dcc4f9614206658f9082a8060dc7c81ad787f4ba +# - ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 +# - ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c +# - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 # - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f name: ".NET for Apple Platforms PR Reviewer" @@ -72,6 +72,7 @@ jobs: actions: read contents: read issues: write + pull-requests: write outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: ${{ steps.add-comment.outputs.comment-id }} @@ -89,31 +90,35 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/macios-reviewer.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Generate agentic run info id: generate_aw_info env: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" GH_AW_INFO_MODEL: "claude-sonnet-4.5" - GH_AW_INFO_VERSION: "1.0.35" - GH_AW_INFO_AGENT_VERSION: "1.0.35" - GH_AW_INFO_CLI_VERSION: "v0.71.1" + GH_AW_INFO_VERSION: "1.0.40" + GH_AW_INFO_AGENT_VERSION: "1.0.40" + GH_AW_INFO_CLI_VERSION: "v0.71.5" GH_AW_INFO_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","dotnet","github","aka.ms","dev.azure.com","microsoft.com","vsassets.io"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.25.28" + GH_AW_INFO_AWF_VERSION: "v0.25.40" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_COMPILED_STRICT: "true" - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -122,8 +127,8 @@ jobs: await main(core, context); - name: Add eyes reaction for immediate feedback id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id || github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.id == github.repository_id + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REACTION: "eyes" with: @@ -150,17 +155,18 @@ jobs: .crush .gemini .opencode + .pi sparse-checkout-cone-mode: true fetch-depth: 1 - name: Save agent config folders for base branch restoration env: - GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode" - GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md opencode.jsonc" + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" # poutine:ignore untrusted_checkout_exec run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" - name: Check workflow lock file id: check-lock-file - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_FILE: "macios-reviewer.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" @@ -171,9 +177,9 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - name: Check compile-agentic version - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.71.1" + GH_AW_COMPILED_VERSION: "v0.71.5" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -182,7 +188,7 @@ jobs: await main(); - name: Compute current body text id: sanitized - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,aka.ms,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,dev.azure.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,microsoft.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vsassets.io,www.googleapis.com,www.microsoft.com" with: @@ -193,8 +199,8 @@ jobs: await main(); - name: Add comment with workflow run link id: add-comment - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || github.event_name == 'pull_request' && github.event.pull_request.head.repo.id == github.repository_id || github.event_name == 'pull_request_review' && github.event.pull_request.head.repo.id == github.repository_id + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" with: @@ -231,6 +237,9 @@ jobs: Tools: create_pull_request_review_comment(max:50), submit_pull_request_review, missing_tool, missing_data, noop + GH_AW_PROMPT_31522cd090dd3137_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_31522cd090dd3137_EOF' The following GitHub context information is available for this workflow: {{#if __GH_AW_GITHUB_ACTOR__ }} @@ -270,9 +279,10 @@ jobs: GH_AW_PROMPT_31522cd090dd3137_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -280,7 +290,7 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); await main(); - name: Substitute placeholders - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -292,6 +302,7 @@ jobs: GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_IS_PR_COMMENT: ${{ github.event.issue.pull_request && 'true' || '' }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: ${{ needs.pre_activation.outputs.matched_command }} with: @@ -314,6 +325,7 @@ jobs: GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, GH_AW_IS_PR_COMMENT: process.env.GH_AW_IS_PR_COMMENT, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST, GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED, GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND } @@ -333,6 +345,7 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: activation + include-hidden-files: true path: | /tmp/gh-aw/aw_info.json /tmp/gh-aw/aw-prompts/prompt.txt @@ -369,11 +382,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/macios-reviewer.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Set runtime paths id: set-runtime-paths run: | @@ -409,7 +426,7 @@ jobs: id: checkout-pr if: | github.event.pull_request || github.event.issue.pull_request - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} with: @@ -420,11 +437,11 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); await main(); - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.35 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.28 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.40 - name: Parse integrity filter lists id: parse-guard-vars env: @@ -440,12 +457,12 @@ jobs: - name: Restore agent config folders from base branch if: steps.checkout-pr.outcome == 'success' env: - GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode" - GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md opencode.jsonc" + GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474 ghcr.io/github/gh-aw-mcpg:v0.3.0@sha256:9c2228324fb1f26f39dc9471612e530ae3efc3156dac05efb2e8d212878d454d ghcr.io/github/github-mcp-server:v1.0.2@sha256:26db03408086a99cf1916348dcc4f9614206658f9082a8060dc7c81ad787f4ba node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f - - name: Write Safe Outputs Config + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 ghcr.io/github/gh-aw-mcpg:v0.3.6@sha256:2bb8eef86006a4c5963c55616a9c51c32f27bfdecb023b8aa6f91f6718d9171c ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f + - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs @@ -453,7 +470,7 @@ jobs: cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_89a2d4b9522a1c3e_EOF' {"create_pull_request_review_comment":{"max":50,"side":"RIGHT"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"submit_pull_request_review":{"allowed_events":["COMMENT","REQUEST_CHANGES"],"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_89a2d4b9522a1c3e_EOF - - name: Write Safe Outputs Tools + - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | { @@ -595,7 +612,7 @@ jobs: } } } - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -656,6 +673,7 @@ jobs: # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="8080" export MCP_GATEWAY_DOMAIN="host.docker.internal" + export MCP_GATEWAY_HOST_DOMAIN="localhost" MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') echo "::add-mask::${MCP_GATEWAY_API_KEY}" export MCP_GATEWAY_API_KEY @@ -668,7 +686,7 @@ jobs: MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0') - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.0' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6' mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) @@ -677,7 +695,7 @@ jobs: "mcpServers": { "github": { "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v1.0.2", + "container": "ghcr.io/github/github-mcp-server:v1.0.3", "env": { "GITHUB_HOST": "\${GITHUB_SERVER_URL}", "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", @@ -717,9 +735,27 @@ jobs: } } GH_AW_MCP_CONFIG_8d4f4bdb31699167_EOF - - name: Clean git credentials + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): @@ -730,9 +766,10 @@ jobs: GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.vsblob.vsassets.io","aka.ms","api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","api.nuget.org","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","azuresearch-usnc.nuget.org","azuresearch-ussc.nuget.org","builds.dotnet.microsoft.com","ci.dot.net","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","dc.services.visualstudio.com","dev.azure.com","dist.nuget.org","docs.github.com","dot.net","dotnet.microsoft.com","dotnetcli.blob.core.windows.net","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","microsoft.com","nuget.org","nuget.pkg.github.com","nugetregistryv2prod.blob.core.windows.net","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","oneocsp.microsoft.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","pkgs.dev.azure.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","telemetry.enterprise.githubcopilot.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","vsassets.io","www.googleapis.com","www.microsoft.com"]},"apiProxy":{"enabled":true,"models":{"auto":["large"],"deep-research":["copilot/deep-research*","google/deep-research*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash"],"opus":["copilot/*opus*","anthropic/*opus*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"]}},"container":{"imageTag":"0.25.40,squid=sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51,agent=sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504,api-proxy=sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280,cli-proxy=sha256:3e7152911d4b4b7b97beef9d3d7d924ff7902227e86001ef3838fb728d5d514c"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --allow-domains '*.githubusercontent.com,*.vsblob.vsassets.io,aka.ms,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,dev.azure.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,microsoft.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vsassets.io,www.googleapis.com,www.microsoft.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --image-tag 0.25.28,squid=sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474,agent=sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a,api-proxy=sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb,cli-proxy=sha256:fdf310e4678ce58d248c466b89399e9680a3003038fd19322c388559016aaac7 --skip-pull --enable-api-proxy \ - -- /bin/bash -c 'GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_API_KEY: dummy-byok-key-for-offline-mode @@ -742,7 +779,7 @@ jobs: GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_VERSION: v0.71.1 + GH_AW_VERSION: v0.71.5 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -790,7 +827,7 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" - name: Redact secrets in logs if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -816,7 +853,7 @@ jobs: - name: Ingest agent output id: collect_output if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,aka.ms,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,dev.azure.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,microsoft.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vsassets.io,www.googleapis.com,www.microsoft.com" @@ -831,7 +868,7 @@ jobs: await main(); - name: Parse agent logs for step summary if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ with: @@ -843,7 +880,7 @@ jobs: - name: Parse MCP Gateway logs for step summary if: always() id: parse-mcp-gateway - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -868,13 +905,23 @@ jobs: - name: Parse token usage for step summary if: always() continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); await main(); + - name: Print AWF reflect summary + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs'); + await main(); - name: Write agent output placeholder if missing if: always() run: | @@ -896,14 +943,17 @@ jobs: !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/agent/ /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_output.json /tmp/gh-aw/aw-*.patch /tmp/gh-aw/aw-*.bundle + /tmp/gh-aw/awf-config.json /tmp/gh-aw/sandbox/firewall/logs/ /tmp/gh-aw/sandbox/firewall/audit/ + /tmp/gh-aw/sandbox/firewall/awf-reflect.json if-no-files-found: ignore conclusion: @@ -930,11 +980,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/macios-reviewer.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -951,7 +1005,7 @@ jobs: echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" - name: Process no-op messages id: noop - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" @@ -968,7 +1022,7 @@ jobs: await main(); - name: Log detection run id: detection_runs - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" @@ -984,7 +1038,7 @@ jobs: await main(); - name: Record missing tool id: missing_tool - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" @@ -998,7 +1052,7 @@ jobs: await main(); - name: Record incomplete id: report_incomplete - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" @@ -1013,7 +1067,7 @@ jobs: - name: Handle agent failure id: handle_agent_failure if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" @@ -1028,10 +1082,13 @@ jobs: GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_GROUP_REPORTS: "false" GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" GH_AW_TIMEOUT_MINUTES: "20" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1042,7 +1099,7 @@ jobs: await main(); - name: Update reaction comment with completion status id: conclusion - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} @@ -1076,11 +1133,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/macios-reviewer.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1106,7 +1167,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.28@sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a ghcr.io/github/gh-aw-firewall/api-proxy:0.25.28@sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb ghcr.io/github/gh-aw-firewall/squid:0.25.28@sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.40@sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.40@sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280 ghcr.io/github/gh-aw-firewall/squid:0.25.40@sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51 - name: Check if detection needed id: detection_guard if: always() @@ -1121,7 +1182,7 @@ jobs: echo "run_detection=false" >> "$GITHUB_OUTPUT" echo "Detection skipped: no agent outputs or patches to analyze" fi - - name: Clear MCP configuration for detection + - name: Clear MCP Config for detection if: always() && steps.detection_guard.outputs.run_detection == 'true' run: | rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" @@ -1143,7 +1204,7 @@ jobs: ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true - name: Setup threat detection if: always() && steps.detection_guard.outputs.run_detection == 'true' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" WORKFLOW_DESCRIPTION: "No description provided" @@ -1165,13 +1226,14 @@ jobs: node-version: '24' package-manager-cache: false - name: Install GitHub Copilot CLI - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.35 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40 env: GH_HOST: github.com - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.28 + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.40 - name: Execute GitHub Copilot CLI if: always() && steps.detection_guard.outputs.run_detection == 'true' + continue-on-error: true id: detection_agentic_execution # Copilot CLI tool arguments (sorted): timeout-minutes: 20 @@ -1181,9 +1243,10 @@ jobs: GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json","network":{"allowDomains":["api.business.githubcopilot.com","api.enterprise.githubcopilot.com","api.github.com","api.githubcopilot.com","api.individual.githubcopilot.com","github.com","host.docker.internal","telemetry.enterprise.githubcopilot.com"]},"apiProxy":{"enabled":true},"container":{"imageTag":"0.25.40,squid=sha256:b084f4a2c771f584ee68084ced52fa6b3245197a1889645d817462d307d3ac51,agent=sha256:14ff567e8d9d4c2fbc5e55c973488381c71d7e0fdbe72d30ee7b8a738fd86504,api-proxy=sha256:2883ca3e5ae9f330cafdd9345bfd4ae17fc8da36c96d4c9a1f76e922b4c45280,cli-proxy=sha256:3e7152911d4b4b7b97beef9d3d7d924ff7902227e86001ef3838fb728d5d514c"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json # shellcheck disable=SC1003 - sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,telemetry.enterprise.githubcopilot.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --image-tag 0.25.28,squid=sha256:844c18280f82cd1b06345eb2f4e91966b34185bfc51c9f237c3e022e848fb474,agent=sha256:a8834e285807654bf680154faa710d43fe4365a0868142f5c20e48c85e137a7a,api-proxy=sha256:93290f2393752252911bd7c39a047f776c0b53063575e7bde4e304962a9a61cb,cli-proxy=sha256:fdf310e4678ce58d248c466b89399e9680a3003038fd19322c388559016aaac7 --skip-pull --enable-api-proxy \ - -- /bin/bash -c 'GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_API_KEY: dummy-byok-key-for-offline-mode @@ -1191,7 +1254,7 @@ jobs: COPILOT_MODEL: claude-sonnet-4.5 GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.71.1 + GH_AW_VERSION: v0.71.5 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1215,19 +1278,36 @@ jobs: - name: Parse and conclude threat detection id: detection_conclusion if: always() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" with: script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); - await main(); + try { + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + } catch (loadErr) { + const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false'; + const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr)); + core.error(msg); + core.setOutput('reason', 'parse_error'); + if (continueOnError) { + core.warning('\u26A0\uFE0F ' + msg); + core.setOutput('conclusion', 'warning'); + core.setOutput('success', 'false'); + } else { + core.setOutput('conclusion', 'failure'); + core.setOutput('success', 'false'); + core.setFailed(msg); + } + } pre_activation: - if: "github.event_name == 'issue_comment' && (startsWith(github.event.comment.body, '/review ') || startsWith(github.event.comment.body, '/review\n') || github.event.comment.body == '/review') && github.event.issue.pull_request != null || !(github.event_name == 'issue_comment')" + if: "(github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment' || contains(fromJSON('[\"OWNER\",\"MEMBER\",\"COLLABORATOR\"]'), github.event.comment.author_association)) && (github.event_name == 'issue_comment' && (startsWith(github.event.comment.body, '/review ') || startsWith(github.event.comment.body, '/review\n') || github.event.comment.body == '/review') && github.event.issue.pull_request != null || !(github.event_name == 'issue_comment'))" runs-on: ubuntu-slim outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' && steps.check_command_position.outputs.command_position_ok == 'true' }} @@ -1236,13 +1316,17 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/macios-reviewer.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Check team membership for command workflow id: check_membership - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_REQUIRED_ROLES: "admin,maintainer,write" with: @@ -1254,7 +1338,7 @@ jobs: await main(); - name: Check command position id: check_command_position - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_COMMANDS: "[\"review\"]" with: @@ -1282,7 +1366,7 @@ jobs: GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: "claude-sonnet-4.5" - GH_AW_ENGINE_VERSION: "1.0.35" + GH_AW_ENGINE_VERSION: "1.0.40" GH_AW_WORKFLOW_ID: "macios-reviewer" GH_AW_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" outputs: @@ -1295,11 +1379,15 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@239aec45b78c8799417efdd5bc6d8cc036629ec1 # v0.71.1 + uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} trace-id: ${{ needs.activation.outputs.setup-trace-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET for Apple Platforms PR Reviewer" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/macios-reviewer.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.40" - name: Download agent output artifact id: download-agent-output continue-on-error: true @@ -1325,7 +1413,7 @@ jobs: echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" - name: Process Safe Outputs id: process_safe_outputs - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,aka.ms,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,dev.azure.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,microsoft.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vsassets.io,www.googleapis.com,www.microsoft.com" diff --git a/.github/workflows/macios-reviewer.md b/.github/workflows/macios-reviewer.md index 72da3cc06bd9..10fe33bae503 100644 --- a/.github/workflows/macios-reviewer.md +++ b/.github/workflows/macios-reviewer.md @@ -56,6 +56,6 @@ A maintainer commented `/review` on this pull request. Perform a thorough code r - Don't flag what CI catches (compiler errors, linter issues). - Don't review C# code formatting — it is handled automatically. - Avoid false positives — verify concerns given the full file context. -- **Never submit an APPROVE event.** Use COMMENT for clean PRs and REQUEST_CHANGES when issues are found. +- **Never submit an APPROVE event.** Use COMMENT for clean PRs (or re-reviews where previous issues are fixed) and REQUEST_CHANGES only when ❌ error-level issues are found. Submitting COMMENT on a re-review clears any previous REQUEST_CHANGES state. - Prioritize: bugs > breaking changes > binding correctness > safety > performance > missing tests > duplication > consistency > documentation. - Ignore comments from the user 'vs-mobiletools-engineering-service2'. diff --git a/Make.config b/Make.config index 68960a6b82dc..9c23ce0b7871 100644 --- a/Make.config +++ b/Make.config @@ -50,10 +50,10 @@ include $(TOP)/Make.versions # The value is taken from the name + version of the Ref pack. # Example: given the Ref pack "Microsoft.iOS.Ref.net8.0_17.5" with the version "17.5.8030", the value # to write here would be the part after "Microsoft.iOS.Ref." + "/" + version: "net8.0_17.5/17.5.8030" -STABLE_NUGET_VERSION_iOS=net10.0_26.2/26.2.10233 -STABLE_NUGET_VERSION_tvOS=net10.0_26.2/26.2.10233 -STABLE_NUGET_VERSION_MacCatalyst=net10.0_26.2/26.2.10233 -STABLE_NUGET_VERSION_macOS=net10.0_26.2/26.2.10233 +STABLE_NUGET_VERSION_iOS=net10.0_26.4/26.4.10259 +STABLE_NUGET_VERSION_tvOS=net10.0_26.4/26.4.10259 +STABLE_NUGET_VERSION_MacCatalyst=net10.0_26.4/26.4.10259 +STABLE_NUGET_VERSION_macOS=net10.0_26.4/26.4.10259 PACKAGE_HEAD_REV=$(shell git rev-parse HEAD) @@ -248,6 +248,11 @@ export DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE=true # We don't need to be told we're using preview packages (we pretty much always are). export SuppressNETCoreSdkPreviewMessage=true +# The Arcade SDK imported by the Xamarin.MacDev submodule overrides +# NuGetPackageRoot in CI, breaking the netstandard2.0 build. +# Pass the correct path explicitly. +export NuGetPackageRoot=$(abspath $(TOP)/packages)/ + # Minimum OSX versions for building XI/XM MIN_OSX_BUILD_VERSION=15.3 diff --git a/NuGet.config b/NuGet.config index e4b2b7a4e2a9..dc6fd2ba4705 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,9 @@ + + + diff --git a/docs/api/AVFoundation/AVAudioRecorder.xml b/docs/api/AVFoundation/AVAudioRecorder.xml index fddc275c262b..2b8dfd9064cb 100644 --- a/docs/api/AVFoundation/AVAudioRecorder.xml +++ b/docs/api/AVFoundation/AVAudioRecorder.xml @@ -22,8 +22,6 @@ recorder.Record (); ]]> - Play Sound - Record Sound - Apple documentation for AVAudioRecorder + Apple documentation for AVAudioRecorder \ No newline at end of file diff --git a/docs/api/AVFoundation/AVAudioSession.xml b/docs/api/AVFoundation/AVAudioSession.xml index ca32d9a704d7..0ddf6c2b49a0 100644 --- a/docs/api/AVFoundation/AVAudioSession.xml +++ b/docs/api/AVFoundation/AVAudioSession.xml @@ -62,7 +62,7 @@ void Setup () ]]> - Apple documentation for AVAudioSession + Apple documentation for AVAudioSession One of diff --git a/docs/api/AVFoundation/AVSpeechSynthesizer.xml b/docs/api/AVFoundation/AVSpeechSynthesizer.xml index 2d3b61b5dec1..3069c1147047 100644 --- a/docs/api/AVFoundation/AVSpeechSynthesizer.xml +++ b/docs/api/AVFoundation/AVSpeechSynthesizer.xml @@ -14,6 +14,6 @@ ss.SpeakUtterance(su); The maintains an internal queue of s. The queue is not accessible to application developers, but the synthesizer can be paused or stopped with and . Events such as or are opportunities for the application developer to modify previously-enqueued sequences. - Apple documentation for AVSpeechSynthesizer + Apple documentation for AVSpeechSynthesizer \ No newline at end of file diff --git a/docs/api/AddressBook/ABPerson.xml b/docs/api/AddressBook/ABPerson.xml index 51f25ef15e0b..9fe9d9ddafb8 100644 --- a/docs/api/AddressBook/ABPerson.xml +++ b/docs/api/AddressBook/ABPerson.xml @@ -229,8 +229,5 @@ monocatalog - Choose a Contact - Create a New Contact - Find a Contact \ No newline at end of file diff --git a/docs/api/AddressBookUI/ABPeoplePickerNavigationController.xml b/docs/api/AddressBookUI/ABPeoplePickerNavigationController.xml index 4643e769edc5..2e71c18d1d82 100644 --- a/docs/api/AddressBookUI/ABPeoplePickerNavigationController.xml +++ b/docs/api/AddressBookUI/ABPeoplePickerNavigationController.xml @@ -272,9 +272,6 @@ public class CompatibleEmailPickerViewController : UIViewController } }]]> . - Choose a Contact - Create a New Contact - Find a Contact Apple documentation for ABPeoplePickerNavigationController \ No newline at end of file diff --git a/docs/api/CoreAnimation/CALayer.xml b/docs/api/CoreAnimation/CALayer.xml index 20e1d7c38cd6..19dae86dbcac 100644 --- a/docs/api/CoreAnimation/CALayer.xml +++ b/docs/api/CoreAnimation/CALayer.xml @@ -191,12 +191,6 @@ public class MyLayer : CALayer { ]]> - Animate a UIView using UIKit - Animate Using Blocks - Create a Keyframe Animation - Create an Animation Block - Create An Explicit Animation - Create an Implicit Animation Apple documentation for CALayer @@ -405,12 +399,6 @@ public class MyLayer : CALayer { - Animate a UIView using UIKit - Animate Using Blocks - Create a Keyframe Animation - Create an Animation Block - Create An Explicit Animation - Create an Implicit Animation Apple documentation for CALayer \ No newline at end of file diff --git a/docs/api/UIKit/NSLayoutManager.xml b/docs/api/UIKit/NSLayoutManager.xml index 1efcbd24773a..df4ce69e3814 100644 --- a/docs/api/UIKit/NSLayoutManager.xml +++ b/docs/api/UIKit/NSLayoutManager.xml @@ -10,7 +10,7 @@ objects, which actually display the text. - Apple documentation for NSLayoutManager + Apple documentation for NSLayoutManager Whether layout can be done for a portion of the document without laying-out being recalculated from the beginning. diff --git a/docs/api/UIKit/NSTextContainer.xml b/docs/api/UIKit/NSTextContainer.xml index 41cac2b068e9..193141e2d971 100644 --- a/docs/api/UIKit/NSTextContainer.xml +++ b/docs/api/UIKit/NSTextContainer.xml @@ -43,6 +43,6 @@ AddSubview(rightHandView); The preceding diagram illustrates the objects directly involved in the two-column layout. The is the responsibility of some external model class and the two-column user-interface is specified by a custom (TwoColumnView). A contains an array of zero or more objects in its property. Text will not be placed within these paths. - Apple documentation for NSTextContainer + Apple documentation for NSTextContainer \ No newline at end of file diff --git a/docs/api/UIKit/NSTextStorage.xml b/docs/api/UIKit/NSTextStorage.xml index 508777500752..ef32c554f095 100644 --- a/docs/api/UIKit/NSTextStorage.xml +++ b/docs/api/UIKit/NSTextStorage.xml @@ -25,6 +25,6 @@ - Apple documentation for NSTextStorage + Apple documentation for NSTextStorage \ No newline at end of file diff --git a/docs/api/UIKit/UICollectionView.xml b/docs/api/UIKit/UICollectionView.xml index 317def4b3f7e..889739ccf465 100644 --- a/docs/api/UIKit/UICollectionView.xml +++ b/docs/api/UIKit/UICollectionView.xml @@ -307,7 +307,6 @@ public class SimpleCollectionViewController : UICollectionViewController - Introduction to Collection Views Apple documentation for UICollectionView diff --git a/docs/api/UIKit/UICollectionViewCell.xml b/docs/api/UIKit/UICollectionViewCell.xml index 4d2e56257ba5..6e62b2a07714 100644 --- a/docs/api/UIKit/UICollectionViewCell.xml +++ b/docs/api/UIKit/UICollectionViewCell.xml @@ -50,7 +50,6 @@ public override UICollectionViewCell GetCell (UICollectionView collectionView, F - Introduction to Collection Views Apple documentation for UICollectionViewCell \ No newline at end of file diff --git a/docs/api/UIKit/UICollectionViewDelegate.xml b/docs/api/UIKit/UICollectionViewDelegate.xml index b7da13af6598..459b8137ffd8 100644 --- a/docs/api/UIKit/UICollectionViewDelegate.xml +++ b/docs/api/UIKit/UICollectionViewDelegate.xml @@ -113,7 +113,6 @@ - Introduction to Collection Views Apple documentation for UICollectionViewDelegate \ No newline at end of file diff --git a/docs/api/UIKit/UICollectionViewFlowLayout.xml b/docs/api/UIKit/UICollectionViewFlowLayout.xml index 9d92d5d43fb5..3404f69fa6ed 100644 --- a/docs/api/UIKit/UICollectionViewFlowLayout.xml +++ b/docs/api/UIKit/UICollectionViewFlowLayout.xml @@ -13,7 +13,6 @@ - Introduction to Collection Views Apple documentation for UICollectionViewFlowLayout \ No newline at end of file diff --git a/docs/api/UIKit/UICollectionViewLayout.xml b/docs/api/UIKit/UICollectionViewLayout.xml index cf10120d210d..9ce2e9538c27 100644 --- a/docs/api/UIKit/UICollectionViewLayout.xml +++ b/docs/api/UIKit/UICollectionViewLayout.xml @@ -73,7 +73,6 @@ - Introduction to Collection Views Apple documentation for UICollectionViewLayout \ No newline at end of file diff --git a/docs/api/UIKit/UICollectionViewLayoutAttributes.xml b/docs/api/UIKit/UICollectionViewLayoutAttributes.xml index 9664e360e08f..032b3c9050e0 100644 --- a/docs/api/UIKit/UICollectionViewLayoutAttributes.xml +++ b/docs/api/UIKit/UICollectionViewLayoutAttributes.xml @@ -34,7 +34,6 @@ public class CircleLayout : UICollectionViewLayout { implements and thus can be used with UI Dynamics. - Introduction to Collection Views Apple documentation for UICollectionViewLayoutAttributes \ No newline at end of file diff --git a/docs/api/UIKit/UIView.xml b/docs/api/UIKit/UIView.xml index 049b1e75a3e6..cd230ee3fc43 100644 --- a/docs/api/UIKit/UIView.xml +++ b/docs/api/UIKit/UIView.xml @@ -991,7 +991,6 @@ public class BlueLayer : CALayer In addition to returning , for a to be focused, it must have a value of , a value of , a value greater than 0, and it must not be obscured by another . - Animate a UIView using UIKit Apple documentation for UIView @@ -1018,7 +1017,6 @@ UIView.CommitAnimations (); - diff --git a/docs/api/UIKit/UIWebView.xml b/docs/api/UIKit/UIWebView.xml index 973647807d25..fd946fa900fc 100644 --- a/docs/api/UIKit/UIWebView.xml +++ b/docs/api/UIKit/UIWebView.xml @@ -1,9 +1,6 @@ A that displays a web browser. - Load a Web Page - Load Local Content - Load Non-Web Documents Apple documentation for UIWebView \ No newline at end of file diff --git a/docs/building-apps/build-properties.md b/docs/building-apps/build-properties.md index 75156945982b..45929fa49458 100644 --- a/docs/building-apps/build-properties.md +++ b/docs/building-apps/build-properties.md @@ -580,6 +580,36 @@ See also: * The [AlternateAppIcon](build-items.md#alternateappicon) item group. * The [AppIcon](#appicon) property. +## InlineDlfcnMethods + +Controls whether the build system replaces runtime calls to `ObjCRuntime.Dlfcn` methods with direct native symbol lookups at build time, eliminating the overhead of `dlsym` at runtime. + +The valid options are: + +* `compatibility`: Only inlines symbol usages backed by `[Field]` attributes. This is more conservative and avoids link errors for symbols that don't exist at build time. +* `strict`: Inlines dlfcn method calls and creates native references for all symbols. This is more aggressive and may cause link errors if referenced native symbols don't exist. +* (empty): Disables inlining of dlfcn method calls. + +Default value: +* .NET 11+: `strict` when using NativeAOT (`PublishAot=true`), `compatibility` otherwise. +* .NET 10 and earlier: not set (disabled). + +Example: + +```xml + + compatibility + +``` + +Custom behavior for specific symbols can be set using the [ReferenceNativeSymbol](build-items.md#referencenativesymbols) item group: + +```xml + + + +``` + ## iOSMinimumVersion Specifies the minimum iOS version the app can run on. @@ -1124,7 +1154,7 @@ Only applicable to macOS and Mac Catalyst apps. ## ReferenceNativeSymbol -See [ReferenceNativeSymbol](build-items.md#referencenativesymbols) +See [ReferenceNativeSymbol](build-items.md#referencenativesymbol) ## RequireLinkWithAttributeForObjectiveCClassSearch @@ -1255,6 +1285,43 @@ $ dotnet run -p:StandardInputPath=stdin.txt Note: this can also be accomplished by passing `--stdin ...` using the [OpenArguments](#openarguments) property. +## SdkIsDesktop + +This property is a read-only property (setting it will have no effect) that +specifies whether we're building for a desktop platform (macOS or Mac Catalyst). + +This property is `true` when the target platform is macOS or Mac Catalyst, +and is not set for iOS or tvOS builds. + +Like `SdkIsSimulator`, this property is only set after [imports and +properties](/visualstudio/msbuild/build-process-overview#evaluate-imports-and-properties) +have been evaluated. + +## SdkIsDevice + +This property is a read-only property (setting it will have no effect) that +specifies whether we're building for a device or not. + +This property is only `true` when building for an iOS or tvOS device (i.e., +when `SdkIsSimulator` is not `true` and the platform is iOS or tvOS). It is +not set for macOS or Mac Catalyst builds. + +Like `SdkIsSimulator`, this property is only set after [imports and +properties](/visualstudio/msbuild/build-process-overview#evaluate-imports-and-properties) +have been evaluated. + +## SdkIsMobile + +This property is a read-only property (setting it will have no effect) that +specifies whether we're building for a mobile platform (iOS or tvOS). + +This property is `true` when the target platform is iOS or tvOS, and is not +set for macOS or Mac Catalyst builds. + +Like `SdkIsSimulator`, this property is only set after [imports and +properties](/visualstudio/msbuild/build-process-overview#evaluate-imports-and-properties) +have been evaluated. + ## SdkIsSimulator This property is a read-only property (setting it will have no effect) that diff --git a/docs/code/native-symbols.md b/docs/code/native-symbols.md new file mode 100644 index 000000000000..45aea7239827 --- /dev/null +++ b/docs/code/native-symbols.md @@ -0,0 +1,69 @@ +# Native symbols + +Native symbols can be referenced from managed code in several ways: + +* P/Invokes (DllImports) +* Calls to `dlsym`, which can happen through: + * The various APIs in `ObjCRuntime.Dlfcn` + * The various APIs in `System.Runtime.InteropServices.NativeLibrary` + * A P/Invoke directly into `dlsym` + +It's highly desirable to use a direct native reference to native symbols when building a mobile app, for a few reasons: + +* It's faster at runtime, and the app is smaller. +* If the referenced native symbol comes from a third-party static library, the + native linker can remove it if it's configured to remove unused code + (because the native linker can't see that the native symbol is in fact used + at runtime) unless there's a direct native reference to the symbol. + +On the other hand there's one scenario when a direct native reference is not desirable: when the native symbol does not exist. + +In order to create a direct native reference to native symbols, we need to know the names of those native symbols. + +## The `InlineDlfcnMethods` property + +This behavior is controlled by the `InlineDlfcnMethods` MSBuild property, which +has two modes: + +* `strict`: all calls to `ObjCRuntime.Dlfcn` APIs are inlined. +* `compatibility`: only calls that reference symbols from `[Field]` attributes are inlined. + +See the [build properties documentation](../building-apps/build-properties.md) for default values. + +## How it works + +During the build we try to collect the following: + +* Any property or field with the `[Foundation.Field]` attribute: we collect the symbol name. +* Any calls to the `ObjCRuntime.Dlfcn` APIs: we try to collect the symbol name (this might not always succeed, if the symbol name is not a constant). +* We don't process calls to `System.Runtime.InteropServices.NativeLibrary` at the moment (this may change in the future, if there's need). + +This is further complicated by the fact that we only want to create native +references for symbols that survive trimming. + +So we do the following: + +1. Before or during trimming, we run the inlining steps: + + * `ProcessExportedFields`: collects all members with `[Field]` attributes. + + * `InlineDlfcnMethodsStep`: inspects all calls to `ObjCRuntime.Dlfcn`, and + inlines them depending on the selected mode. If inlined, the step creates + a P/Invoke to a native method that will return the address for that symbol + (using a direct native reference), and modifies the code that fetches that + symbol to call said P/Invoke. + +2. After trimming, we figure out which of those symbols survived: + + * For ILTrim: the `_CollectPostILTrimInformation` MSBuild target inspects + the trimmed assemblies and collects all the inlined dlfcn P/Invokes that + survived. Per-assembly results are cached to speed up incremental builds. + + * For NativeAOT: the `_CollectPostNativeAOTTrimInformation` MSBuild target + inspects the native object file (or static library) produced by NativeAOT, + collects all unresolved native references, and filters them against the + inlined dlfcn symbols to determine which survived. + +3. The `_PostTrimmingProcessing` MSBuild target takes the surviving symbols + from either path, generates the corresponding native C code, and adds it to + the list of files to compile and link into the final executable. diff --git a/dotnet/SingleProject.md b/dotnet/SingleProject.md index be4729e9d046..9a20de442520 100644 --- a/dotnet/SingleProject.md +++ b/dotnet/SingleProject.md @@ -18,8 +18,7 @@ Info.plist in the project doesn't already contain entries for these keys): | ApplicationDisplayVersion | CFBundleShortVersionString | Defaults to ApplicationVersion when blank | This is only enabled if the `GenerateApplicationManifest` is set to `true` -(which is the default for `.NET 6`, and not for "legacy" -Xamarin.iOS/Xamarin.Mac) +(which is the default for all supported .NET versions) Additionally, `$(ApplicationDisplayVersion)` will overwrite the value for `$(Version)`, so the following properties will be set with the same value: @@ -30,5 +29,5 @@ so the following properties will be set with the same value: Ref: [Issue #10473][2] -[1]: https://github.com/xamarin/xamarin-android/blob/40cedfa89c2660479fcb5e2482d2463fbcad1d04/Documentation/guides/OneDotNetSingleProject.md +[1]: https://github.com/dotnet/android/blob/main/Documentation/guides/OneDotNetSingleProject.md [2]: https://github.com/dotnet/macios/issues/10473 diff --git a/dotnet/targets/Microsoft.Sdk.Desktop.targets b/dotnet/targets/Microsoft.Sdk.Desktop.targets index 276822e3c2e4..d8d90ab7c46d 100644 --- a/dotnet/targets/Microsoft.Sdk.Desktop.targets +++ b/dotnet/targets/Microsoft.Sdk.Desktop.targets @@ -4,7 +4,7 @@ Name="_PrepareRunDesktop" BeforeTargets="ComputeRunArguments" DependsOnTargets="_ValidateHotReloadConfiguration" - Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'"> + Condition="'$(SdkIsDesktop)' == 'true'"> @@ -145,7 +145,7 @@ Name="_PrepareRunMobile" BeforeTargets="ComputeRunArguments" DependsOnTargets="_ValidateHotReloadConfiguration;_InstallMobile;ComputeMlaunchRunArguments" - Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'"> + Condition="'$(SdkIsDesktop)' != 'true'"> <_FilterDevicesToRuntimeIdentifier Condition="'$(_XamarinUsingDefaultRuntimeIdentifier)' != 'true'">$(RuntimeIdentifier) diff --git a/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets b/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets index b970adc12d0d..42b125875d12 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets @@ -59,11 +59,6 @@ - - iPhoneSimulator - iPhone - - <_RuntimeFrameworkVersion>$(BundledNETCorePlatformsPackageVersion) <_RuntimeFrameworkVersion Condition="'$(CUSTOM_DOTNET_VERSION)' != ''">$(CUSTOM_DOTNET_VERSION) @@ -73,37 +68,4 @@ - - - - - - - - - - 6.0.3 - - diff --git a/dotnet/targets/Xamarin.Shared.Sdk.Publish.targets b/dotnet/targets/Xamarin.Shared.Sdk.Publish.targets index 44d97039ff5e..c053793baf15 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.Publish.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.Publish.targets @@ -2,8 +2,8 @@ - true - true + true + true $(PublishDir) @@ -21,7 +21,7 @@ /> - - + + diff --git a/dotnet/targets/Xamarin.Shared.Sdk.Trimming.props b/dotnet/targets/Xamarin.Shared.Sdk.Trimming.props index 77e7138d9b51..3468370a20d8 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.Trimming.props +++ b/dotnet/targets/Xamarin.Shared.Sdk.Trimming.props @@ -54,6 +54,9 @@ <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(UseMonoRuntime)' != 'true' And '$(_PlatformName)' == 'macOS'">None + + <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(UseMonoRuntime)' != 'true' And '$(_SdkIsSimulator)' == 'true'">None + <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly @@ -63,10 +66,10 @@ <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(_PlatformName)' == 'MacCatalyst'">None - - <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(_SdkIsSimulator)' == 'true' And $(RuntimeIdentifier.Contains('arm64')) And '$(MtouchInterpreter)' == ''">SdkOnly - - <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(_SdkIsSimulator)' == 'true' And (!$(RuntimeIdentifier.Contains('arm64')) Or '$(MtouchInterpreter)' != '')">None + + <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(_SdkIsSimulator)' == 'true' And '$(UseMonoRuntime)' == 'true' And $(RuntimeIdentifier.Contains('arm64')) And '$(MtouchInterpreter)' == ''">SdkOnly + + <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == '' And '$(_SdkIsSimulator)' == 'true' And '$(UseMonoRuntime)' == 'true' And (!$(RuntimeIdentifier.Contains('arm64')) Or '$(MtouchInterpreter)' != '')">None <_DefaultLinkMode Condition="'$(_DefaultLinkMode)' == ''">SdkOnly diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props index 94cbc23291d4..fc6465f4c1c0 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.props +++ b/dotnet/targets/Xamarin.Shared.Sdk.props @@ -100,6 +100,12 @@ false + + + strict + compatibility + + @@ -151,6 +157,19 @@ <_SdkIsSimulator Condition="'$(_SdkIsSimulator)' == ''">false $(_SdkIsSimulator) + + + true + + + true + + + true + + + iPhoneSimulator + iPhone @@ -196,7 +215,7 @@ but the MtouchUseLlvm value is ignored when using the simulator, so it doesn't matter if we set it in all cases. --> - + true diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index 670fe72a8864..592fafb84321 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -18,6 +18,9 @@ + + + @@ -25,6 +28,7 @@ + - - + + @@ -570,8 +574,8 @@ - Otherwise set 'dynamic' --> managed-static - managed-static - managed-static + managed-static + managed-static partial-static dynamic @@ -636,7 +640,7 @@ <_LinkerCacheDirectory Condition="'$(BuildSessionId)' != ''">$(IntermediateOutputPath)linker-cache - <_IsSimulatorFeature Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' == 'true'">true + <_IsSimulatorFeature Condition="'$(SdkIsMobile)' == 'true' And '$(_SdkIsSimulator)' == 'true'">true <_IsSimulatorFeature Condition="'$(_IsSimulatorFeature)' == ''">false @@ -678,7 +682,9 @@ @(_BundlerEnvironmentVariables -> 'EnvironmentVariable=Overwrite=%(Overwrite)|%(Identity)=%(Value)') @(_XamarinFrameworkAssemblies -> 'FrameworkAssembly=%(Filename)') Interpreter=$(MtouchInterpreter) + InlineDlfcnMethods=$(InlineDlfcnMethods) IntermediateLinkDir=$(IntermediateLinkDir) + IntermediateOutputPath=$(DeviceSpecificIntermediateOutputPath) InvariantGlobalization=$(InvariantGlobalization) HybridGlobalization=$(HybridGlobalization) ItemsDirectory=$(_LinkerItemsDirectory) @@ -827,6 +833,7 @@ <_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.ApplyPreserveAttributeStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseLinkDescriptionForApplyPreserveAttribute)' == 'true'" /> <_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.MarkForStaticRegistrarStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForMarkStaticRegistrar)' == 'true'" /> <_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.MarkNSObjectsStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForMarkNSObjects)' == 'true'" /> + <_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.InlineDlfcnMethodsStep" Condition="'$(InlineDlfcnMethods)' != ''" /> <_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="MonoTouch.Tuner.RegistrarRemovalTrackingStep" /> @@ -1296,7 +1303,7 @@ - <_RunAotCompiler Condition="'$(_SdkIsSimulator)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">true + <_RunAotCompiler Condition="'$(_SdkIsSimulator)' != 'true' And '$(SdkIsDesktop)' != 'true'">true <_RunAotCompiler Condition="'$(MtouchInterpreter)' != '' And '$(_PlatformName)' != 'macOS'">true @@ -1319,10 +1326,10 @@ <_IntermediateNativeLibraryDir>$(IntermediateOutputPath)nativelibraries/ <_IntermediateFrameworksDir>$(DeviceSpecificIntermediateOutputPath)frameworks <_IntermediateDecompressionDir>$([MSBuild]::EnsureTrailingSlash('$(DeviceSpecificIntermediateOutputPath)decompressed')) - <_NativeExecutablePublishDir Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">$(_RelativeAppBundlePath)\ - <_NativeExecutablePublishDir Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">$(_RelativeAppBundlePath)\Contents\MacOS\ - <_AppBundleFrameworksDir Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">$(_RelativeAppBundlePath)\Frameworks\ - <_AppBundleFrameworksDir Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">$(_RelativeAppBundlePath)\Contents\Frameworks\ + <_NativeExecutablePublishDir Condition="'$(SdkIsMobile)' == 'true'">$(_RelativeAppBundlePath)\ + <_NativeExecutablePublishDir Condition="'$(SdkIsDesktop)' == 'true'">$(_RelativeAppBundlePath)\Contents\MacOS\ + <_AppBundleFrameworksDir Condition="'$(SdkIsMobile)' == 'true'">$(_RelativeAppBundlePath)\Frameworks\ + <_AppBundleFrameworksDir Condition="'$(SdkIsDesktop)' == 'true'">$(_RelativeAppBundlePath)\Contents\Frameworks\ <_AOTInputDirectory>$(_IntermediateNativeLibraryDir)aot-input/ <_AOTOutputDirectory>$(_IntermediateNativeLibraryDir)aot-output/ @@ -1342,14 +1349,15 @@ <_LibMonoLinkMode Condition="'$(_LibMonoLinkMode)' == '' And '$(_PlatformName)' == 'MacCatalyst' And '$(UseMonoRuntime)' == 'true'">static - <_LibMonoLinkMode Condition="'$(_LibMonoLinkMode)' == '' And '$(ComputedPlatform)' == 'iPhone'">static + <_LibMonoLinkMode Condition="'$(_LibMonoLinkMode)' == '' And '$(SdkIsDevice)' == 'true'">static <_LibMonoLinkMode Condition="'$(_LibMonoLinkMode)' == ''">dylib + <_LibMonoExtension Condition="'$(_LibMonoLinkMode)' == 'dylib'">dylib <_LibMonoExtension Condition="'$(_LibMonoLinkMode)' == 'static'">a <_LibXamarinLinkMode Condition="'$(_LibXamarinLinkMode)' == '' And '$(_PlatformName)' == 'MacCatalyst'">static - <_LibXamarinLinkMode Condition="'$(_LibXamarinLinkMode)' == '' And '$(ComputedPlatform)' != 'iPhone' And '$(_PlatformName)' != 'macOS'">dylib + <_LibXamarinLinkMode Condition="'$(_LibXamarinLinkMode)' == '' And '$(SdkIsSimulator)' == 'true' And '$(_PlatformName)' != 'macOS'">dylib <_LibXamarinLinkMode Condition="'$(_LibXamarinLinkMode)' == ''">static <_LibXamarinExtension Condition="'$(_LibXamarinLinkMode)' == 'dylib'">dylib <_LibXamarinExtension Condition="'$(_LibXamarinLinkMode)' == 'static'">a @@ -1359,11 +1367,11 @@ <_LibXamarinDebug Condition="'$(_BundlerDebug)' == 'true'">-debug <_LibXamarinName Condition="'$(_LibXamarinName)' == ''">libxamarin-dotnet$(_LibXamarinRuntime)$(_LibXamarinDebug).$(_LibXamarinExtension) - <_DylibRPath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">@executable_path - <_DylibRPath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">@executable_path/../$(_CustomBundleName)/ + <_DylibRPath Condition="'$(SdkIsMobile)' == 'true'">@executable_path + <_DylibRPath Condition="'$(SdkIsDesktop)' == 'true'">@executable_path/../$(_CustomBundleName)/ - <_EmbeddedFrameworksRPath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">@executable_path/Frameworks - <_EmbeddedFrameworksRPath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">@executable_path/../Frameworks/ + <_EmbeddedFrameworksRPath Condition="'$(SdkIsMobile)' == 'true'">@executable_path/Frameworks + <_EmbeddedFrameworksRPath Condition="'$(SdkIsDesktop)' == 'true'">@executable_path/../Frameworks/ <_RuntimeConfigurationFile>runtimeconfig.bin @@ -1371,8 +1379,8 @@ <_CustomLinkFlags Include="-rpath" /> - <_CustomLinkFlags Include="@executable_path/../../Frameworks" Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'" /> - <_CustomLinkFlags Include="@executable_path/../../../../Frameworks" Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'" /> + <_CustomLinkFlags Include="@executable_path/../../Frameworks" Condition="'$(SdkIsMobile)' == 'true'" /> + <_CustomLinkFlags Include="@executable_path/../../../../Frameworks" Condition="'$(SdkIsDesktop)' == 'true'" /> @@ -1709,6 +1717,87 @@ + + + <_TrimmedAssembly Include="$(IntermediateLinkDir)*.dll" /> + + + + + + <_ILTrimSurvivingNativeSymbolsFile>$(DeviceSpecificIntermediateOutputPath)inlined-dlfcn\iltrim-surviving-native-symbols.txt + <_NativeAOTUnresolvedSymbolsFile>$(DeviceSpecificIntermediateOutputPath)nativeaot-unresolved-symbols.txt + <_NativeAOTSurvivingNativeSymbolsFile>$(DeviceSpecificIntermediateOutputPath)nativeaot-surviving-native-symbols.txt + + + + + + + + + + + + + + + + + + <_SurvivingNativeSymbolsFile Include="$(_ILTrimSurvivingNativeSymbolsFile)" Condition="Exists('$(_ILTrimSurvivingNativeSymbolsFile)')" /> + <_SurvivingNativeSymbolsFile Include="$(_NativeAOTSurvivingNativeSymbolsFile)" Condition="Exists('$(_NativeAOTSurvivingNativeSymbolsFile)')" /> + + + + + + + + <_PostTrimmingSourceFiles> + $(DeviceSpecificIntermediateOutputPath)posttrim-info-compiled/%(Arch)/%(Filename).o + + + + + + + + <_CompiledPostTrimmingFiles Include="@(_PostTrimmingSourceFiles -> '%(OutputFile)')" /> + <_NativeExecutableObjectFiles Include="@(_CompiledPostTrimmingFiles)" /> + + + + <_CompileNativeExecutableDependsOn> $(_CompileNativeExecutableDependsOn); @@ -1765,6 +1854,7 @@ _ReadAppManifest; _WriteAppManifest; _CompileNativeExecutable; + _PostTrimmingProcessing; _ReidentifyDynamicLibraries; _AddSwiftLinkerFlags; _ComputeLinkerProperties; @@ -1773,6 +1863,25 @@ + + + + + + @@ -1948,8 +2057,8 @@ - <_ExecutablePathPrefix Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">@executable_path/ - <_ExecutablePathPrefix Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">@executable_path/../../ + <_ExecutablePathPrefix Condition="'$(SdkIsMobile)' == 'true'">@executable_path/ + <_ExecutablePathPrefix Condition="'$(SdkIsDesktop)' == 'true'">@executable_path/../../ @@ -2120,10 +2229,10 @@ Condition="'$(_CanOutputAppBundle)' == 'true'" > - <_AssemblyPublishDir Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">$(_RelativeAppBundlePath)\ - <_AssemblyPublishDir Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">$(_RelativeAppBundlePath)\Contents\$(_CustomBundleName)\ - <_DylibPublishDir Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'">$(_RelativeAppBundlePath)\ - <_DylibPublishDir Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">$(_RelativeAppBundlePath)\Contents\$(_CustomBundleName)\ + <_AssemblyPublishDir Condition="'$(SdkIsMobile)' == 'true'">$(_RelativeAppBundlePath)\ + <_AssemblyPublishDir Condition="'$(SdkIsDesktop)' == 'true'">$(_RelativeAppBundlePath)\Contents\$(_CustomBundleName)\ + <_DylibPublishDir Condition="'$(SdkIsMobile)' == 'true'">$(_RelativeAppBundlePath)\ + <_DylibPublishDir Condition="'$(SdkIsDesktop)' == 'true'">$(_RelativeAppBundlePath)\Contents\$(_CustomBundleName)\ <_ParsedRuntimeConfigFilePath Condition="'$(_ParsedRuntimeConfigFilePath)' == ''">$(DeviceSpecificIntermediateOutputPath)$(_RuntimeConfigurationFile) @@ -2153,7 +2262,7 @@ + Condition="('$(_SdkIsSimulator)' != 'false' Or '$(SdkIsDesktop)' == 'true') And ('%(Extension)' == '.dylib' Or '%(Extension)' == '.so') " /> + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/de/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/de/macios/tools/mtouch/Errors.resx.lcl index fc5a683a52d9..53208ba1ba08 100644 --- a/macios/Localize/loc/de/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/de/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/es/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/es/macios/tools/mtouch/Errors.resx.lcl index 71d382396cc5..63e741058a55 100644 --- a/macios/Localize/loc/es/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/es/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/fr/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/fr/macios/tools/mtouch/Errors.resx.lcl index d3a69c437805..8ef8855f9da5 100644 --- a/macios/Localize/loc/fr/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/fr/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/it/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/it/macios/tools/mtouch/Errors.resx.lcl index ae92e92ba6f7..db37a2986208 100644 --- a/macios/Localize/loc/it/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/it/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/ja/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/ja/macios/tools/mtouch/Errors.resx.lcl index ac518a9e3efd..b3fd520db049 100644 --- a/macios/Localize/loc/ja/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/ja/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/ko/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/ko/macios/tools/mtouch/Errors.resx.lcl index bc908620c830..88ca649db7d8 100644 --- a/macios/Localize/loc/ko/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/ko/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/pl/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/pl/macios/tools/mtouch/Errors.resx.lcl index b51dc49757b8..ce7aec51d493 100644 --- a/macios/Localize/loc/pl/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/pl/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/pt-BR/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/pt-BR/macios/tools/mtouch/Errors.resx.lcl index d893a87b4e74..b6e107f5acc2 100644 --- a/macios/Localize/loc/pt-BR/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/pt-BR/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/ru/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/ru/macios/tools/mtouch/Errors.resx.lcl index 80205c40569f..e076f441c2eb 100644 --- a/macios/Localize/loc/ru/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/ru/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/tr/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/tr/macios/tools/mtouch/Errors.resx.lcl index 0b6e0841f004..2aeda18d004b 100644 --- a/macios/Localize/loc/tr/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/tr/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/zh-Hans/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/zh-Hans/macios/tools/mtouch/Errors.resx.lcl index 08b62dea5624..a2d73ba8d17a 100644 --- a/macios/Localize/loc/zh-Hans/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/zh-Hans/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/Localize/loc/zh-Hant/macios/tools/mtouch/Errors.resx.lcl b/macios/Localize/loc/zh-Hant/macios/tools/mtouch/Errors.resx.lcl index 0063007365b0..3d2193f28959 100644 --- a/macios/Localize/loc/zh-Hant/macios/tools/mtouch/Errors.resx.lcl +++ b/macios/Localize/loc/zh-Hant/macios/tools/mtouch/Errors.resx.lcl @@ -4552,6 +4552,15 @@ + + + + + + + + + @@ -4882,6 +4891,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.cs.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.cs.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.cs.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.cs.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.de.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.de.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.de.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.de.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.es.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.es.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.es.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.es.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.fr.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.fr.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.fr.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.fr.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.it.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.it.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.it.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.it.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.ja.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.ja.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.ja.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.ja.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.ko.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.ko.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.ko.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.ko.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.pl.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.pl.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.pl.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.pl.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.ru.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.ru.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.ru.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.ru.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.tr.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.tr.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.tr.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.tr.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx b/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx index a03441e8b5b6..373de125892d 100644 --- a/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx +++ b/macios/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx @@ -832,6 +832,19 @@ + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + The linker step '{0}' failed during processing: {1} @@ -1216,6 +1229,9 @@ The class '{0}' will not be registered because the {1} framework has been deprecated from the {2} SDK. + + Could not find the trampoline for the category method {0}. + Missing '{0}' compiler. Please install Xcode 'Command-Line Tools' component @@ -1459,4 +1475,10 @@ Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: No 'Invoke' method found. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + Unable to find the managed function with id {0} ({1}, {2}). Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + + + Type '{0}' is expected to have a ProtocolProxyAttribute. Please file a bug report with a test case (https://github.com/dotnet/macios/issues/new). + \ No newline at end of file diff --git a/msbuild/ILMerge.targets b/msbuild/ILMerge.targets index f2e8caa95328..d8c87c68fccf 100644 --- a/msbuild/ILMerge.targets +++ b/msbuild/ILMerge.targets @@ -17,7 +17,7 @@ - + diff --git a/msbuild/Makefile b/msbuild/Makefile index 436e22a2c71c..c676c92ca83a 100644 --- a/msbuild/Makefile +++ b/msbuild/Makefile @@ -137,7 +137,7 @@ endif # I haven't found a way to execute ilrepack.exe on .NET (it will probably have to be built for .NET), so run it using Mono. .build-stamp: $(ALL_SOURCES) - $(Q) $(DOTNET) build "/bl:$@.binlog" $(XBUILD_VERBOSITY) + $(Q) $(DOTNET) build "/bl:$@.binlog" $(XBUILD_VERBOSITY) /p:NuGetPackageRoot=$(abspath $(TOP)/packages)/ $(Q) touch $@ # make all the target assemblies build when any of the sources have changed diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/CollectPostILTrimInformation.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/CollectPostILTrimInformation.cs new file mode 100644 index 000000000000..116ce430cb49 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/CollectPostILTrimInformation.cs @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Microsoft.Build.Framework; + +using Mono.Cecil; + +#nullable enable + +namespace Xamarin.MacDev.Tasks { + /// + /// Scans trimmed assemblies to collect information that survived trimming. + /// See docs/code/native-symbols.md for an overview of native symbol handling. + /// + public class CollectPostILTrimInformation : XamarinTask { + [Required] + public ITaskItem [] TrimmedAssemblies { get; set; } = []; + + /// + /// Output file listing the inlined dlfcn symbols that survived trimming. + /// + [Required] + public string SurvivingNativeSymbolsFile { get; set; } = ""; + + /// + /// Directory for per-assembly cache files, to avoid re-scanning unchanged assemblies. + /// + [Required] + public string CacheDirectory { get; set; } = ""; + + public override bool Execute () + { + Directory.CreateDirectory (CacheDirectory); + + CollectSurvivingNativeSymbols (); + + return !Log.HasLoggedErrors; + } + + void CollectSurvivingNativeSymbols () + { + // Scan trimmed assemblies for surviving P/Invoke methods, using per-assembly caching. + var survivingSymbols = new HashSet (); + foreach (var item in TrimmedAssemblies) { + var assemblyPath = item.ItemSpec; + if (!File.Exists (assemblyPath)) + continue; + + var assemblyName = Path.GetFileNameWithoutExtension (assemblyPath); + var cacheFile = Path.Combine (CacheDirectory, assemblyName + ".dlfcn-symbols.cache"); + + string []? cachedSymbols = null; + if (File.Exists (cacheFile) && File.GetLastWriteTimeUtc (cacheFile) >= File.GetLastWriteTimeUtc (assemblyPath)) { + cachedSymbols = File.ReadAllLines (cacheFile); + Log.LogMessage (MessageImportance.Low, "Using cached dlfcn symbols for {0}", assemblyName); + + survivingSymbols.UnionWith (cachedSymbols); + } else { + var assemblySymbols = new HashSet (); + CollectDlfcnSymbolsFromAssembly (assemblyPath, assemblySymbols); + + // Write per-assembly cache (sorted for stability). + var sortedAssemblySymbols = assemblySymbols.OrderBy (s => s).ToArray (); + File.WriteAllLines (cacheFile, sortedAssemblySymbols); + + survivingSymbols.UnionWith (assemblySymbols); + } + } + + // Write the combined results only if contents changed (sorted for stability). + var sorted = survivingSymbols.OrderBy (s => s).ToArray (); + + if (File.Exists (SurvivingNativeSymbolsFile)) { + var existing = File.ReadAllLines (SurvivingNativeSymbolsFile); + if (existing.SequenceEqual (sorted)) + return; + } + + var dir = Path.GetDirectoryName (SurvivingNativeSymbolsFile); + if (!string.IsNullOrEmpty (dir)) + Directory.CreateDirectory (dir); + File.WriteAllLines (SurvivingNativeSymbolsFile, sorted); + Log.LogMessage (MessageImportance.Low, "Found {0} surviving inlined dlfcn symbols", survivingSymbols.Count); + } + + static void CollectDlfcnSymbolsFromAssembly (string assemblyPath, HashSet survivingSymbols) + { + const string prefix = "xamarin_Dlfcn_"; + const string suffix = "_Native"; + + using var assembly = AssemblyDefinition.ReadAssembly (assemblyPath, new ReaderParameters { ReadSymbols = false }); + foreach (var module in assembly.Modules) { + foreach (var type in module.Types) { + if (!type.HasMethods) + continue; + foreach (var method in type.Methods) { + if (!method.IsPInvokeImpl) + continue; + if (method.PInvokeInfo?.Module?.Name != "__Internal") + continue; + var name = method.Name; + if (!name.StartsWith (prefix) || !name.EndsWith (suffix)) + continue; + var symbolLength = name.Length - prefix.Length - suffix.Length; + if (symbolLength <= 0) + continue; + var symbolName = name.Substring (prefix.Length, symbolLength); + survivingSymbols.Add (symbolName); + } + } + } + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/CollectUnresolvedNativeSymbols.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/CollectUnresolvedNativeSymbols.cs new file mode 100644 index 000000000000..bc43f111fba4 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/CollectUnresolvedNativeSymbols.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Microsoft.Build.Framework; + +#nullable enable + +namespace Xamarin.MacDev.Tasks { + // See docs/code/native-symbols.md for an overview of native symbol handling. + public class CollectUnresolvedNativeSymbols : XamarinTask { + public ITaskItem? StaticLibrary { get; set; } + + [Required] + public string OutputFile { get; set; } = ""; + + public override bool Execute () + { + if (StaticLibrary is null) { + Log.LogError ("StaticLibrary is required."); + return false; + } + + var path = StaticLibrary.ItemSpec; + if (!File.Exists (path)) { + Log.LogError ("Static library not found: {0}", path); + return false; + } + + var symbols = Xamarin.StaticLibrary.GetUnresolvedSymbols (path); + Log.LogMessage (MessageImportance.Low, "Found {0} unresolved symbols in {1}", symbols.Count, path); + + var lines = symbols.OrderBy (s => s).ToArray (); + if (File.Exists (OutputFile)) { + var existing = File.ReadAllLines (OutputFile); + if (existing.SequenceEqual (lines)) + return !Log.HasLoggedErrors; + } + + var dir = Path.GetDirectoryName (OutputFile); + if (!string.IsNullOrEmpty (dir)) + Directory.CreateDirectory (dir); + File.WriteAllLines (OutputFile, lines); + + return !Log.HasLoggedErrors; + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileEntitlements.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileEntitlements.cs index 0db654e7addc..4e818beb636c 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileEntitlements.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileEntitlements.cs @@ -789,6 +789,7 @@ static Dictionary GetAllEntitlements () new EntitlementData ("com.apple.developer.on-demand-install-capable", iOS, EntitlementType.Boolean ), new EntitlementData ("com.apple.developer.parent-application-identifiers", iOS, EntitlementType.ArrayOfStrings ), new EntitlementData ("com.apple.developer.pass-type-identifiers", iOS, EntitlementType.ArrayOfStrings ), + new EntitlementData ("com.apple.developer.payment-pass-provisioning", iOS, EntitlementType.Boolean ), new EntitlementData ("com.apple.developer.persistent-content-capture", desktop, EntitlementType.Boolean ), new EntitlementData ("com.apple.developer.playable-content", iOS, EntitlementType.Boolean ), new EntitlementData ("com.apple.developer.proximity-reader.identity.display", iOS, EntitlementType.Boolean ), diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileNativeCode.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileNativeCode.cs index affd9e1f3fae..f3816db30ddb 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileNativeCode.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/CompileNativeCode.cs @@ -136,6 +136,10 @@ public override bool Execute () arguments.Add ("-o"); arguments.Add (outputFile); + var outputDirectory = Path.GetDirectoryName (outputFile); + if (!string.IsNullOrEmpty (outputDirectory)) + Directory.CreateDirectory (outputDirectory); + arguments.Add ("-c"); arguments.Add (src); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeNativeAOTSurvivingNativeSymbols.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeNativeAOTSurvivingNativeSymbols.cs new file mode 100644 index 000000000000..67eda6ed7ec0 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeNativeAOTSurvivingNativeSymbols.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Microsoft.Build.Framework; + +#nullable enable + +namespace Xamarin.MacDev.Tasks { + /// + /// Takes the list of unresolved native symbols from a NativeAOT static library and computes + /// which inlined dlfcn native symbols survived trimming. The output file has the same format + /// as CollectPostILTrimInformation's surviving symbols file. + /// See docs/code/native-symbols.md for an overview of native symbol handling. + /// + public class ComputeNativeAOTSurvivingNativeSymbols : XamarinTask { + /// + /// The file listing all unresolved native symbols from the NativeAOT static library. + /// + [Required] + public string UnresolvedSymbolsFile { get; set; } = ""; + + /// + /// Output file listing the native symbols that survived NativeAOT trimming. + /// + [Required] + public string SurvivingNativeSymbolsFile { get; set; } = ""; + + public override bool Execute () + { + if (!File.Exists (UnresolvedSymbolsFile)) + return !Log.HasLoggedErrors; + + const string prefix = "_xamarin_Dlfcn_"; + const string suffix = "_Native"; + var survivingSymbols = new HashSet (); + + foreach (var sym in File.ReadAllLines (UnresolvedSymbolsFile)) { + if (!sym.StartsWith (prefix) || !sym.EndsWith (suffix)) + continue; + var symbolLength = sym.Length - prefix.Length - suffix.Length; + if (symbolLength <= 0) + continue; + var symbolName = sym.Substring (prefix.Length, symbolLength); + survivingSymbols.Add (symbolName); + } + + var sorted = survivingSymbols.OrderBy (s => s).ToArray (); + + if (File.Exists (SurvivingNativeSymbolsFile)) { + var existing = File.ReadAllLines (SurvivingNativeSymbolsFile); + if (existing.SequenceEqual (sorted)) + return !Log.HasLoggedErrors; + } + + var dir = Path.GetDirectoryName (SurvivingNativeSymbolsFile); + if (!string.IsNullOrEmpty (dir)) + Directory.CreateDirectory (dir); + File.WriteAllLines (SurvivingNativeSymbolsFile, sorted); + Log.LogMessage (MessageImportance.Low, "Found {0} surviving native symbols from NativeAOT", survivingSymbols.Count); + + return !Log.HasLoggedErrors; + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/GetAvailableDevices.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/GetAvailableDevices.cs index eda5380ab2d9..57ecb577164d 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/GetAvailableDevices.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/GetAvailableDevices.cs @@ -2,13 +2,13 @@ using System.IO; using System.Collections.Generic; using System.Linq; -using System.Text.Json; using System.Threading; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Xamarin.Localization.MSBuild; +using Xamarin.MacDev.Models; using Xamarin.Messaging.Build.Client; using Xamarin.Utils; @@ -161,265 +161,218 @@ protected virtual async System.Threading.Tasks.Task ExecuteCtlAsync (par } } - async System.Threading.Tasks.Task ExecuteCtlToJsonAsync (params string [] args) - { - var json = await ExecuteCtlAsync (args); - var options = new JsonDocumentOptions { - AllowTrailingCommas = true, - CommentHandling = JsonCommentHandling.Skip, - }; - return JsonDocument.Parse (string.IsNullOrEmpty (json) ? "{}" : json, options); - } - async System.Threading.Tasks.Task> RunDeviceCtlAsync () { - var doc = await ExecuteCtlToJsonAsync ("devicectl", "list", "devices"); - var array = doc.FindProperty ("result", "devices")?.EnumerateIfArray (); + var json = await ExecuteCtlAsync ("devicectl", "list", "devices"); var rv = new List (); - if (array is not null) { - foreach (var device in array) { - var name = device.GetStringPropertyOrEmpty ("deviceProperties", "name"); - var udid = device.GetStringPropertyOrEmpty ("hardwareProperties", "udid"); - var identifier = device.GetStringPropertyOrEmpty ("identifier"); - - var deviceProperties = device.GetNullableProperty ("deviceProperties"); - var buildVersion = deviceProperties.GetStringPropertyOrEmpty ("osBuildUpdate"); - var productVersion = deviceProperties.GetStringPropertyOrEmpty ("osVersionNumber"); - - var hardwareProperties = device.GetNullableProperty ("hardwareProperties"); - var deviceClass = hardwareProperties.GetStringPropertyOrEmpty ("deviceType"); - var hardwareModel = hardwareProperties.GetStringPropertyOrEmpty ("hardwareModel"); - var hardwarePlatform = hardwareProperties.GetStringPropertyOrEmpty ("platform"); - var productType = hardwareProperties.GetStringPropertyOrEmpty ("productType"); - var serialNumber = hardwareProperties.GetStringPropertyOrEmpty ("serialNumber"); - var uniqueChipID = hardwareProperties.GetUInt64Property ("ecid"); - - var cpuType = hardwareProperties.GetNullableProperty ("cpuType"); - var cpuArchitecture = cpuType.GetStringPropertyOrEmpty ("name"); - - var connectionProperties = device.GetNullableProperty ("connectionProperties"); - var transportType = connectionProperties.GetStringPropertyOrEmpty ("transportType"); - var pairingState = connectionProperties.GetStringPropertyOrEmpty ("pairingState"); - - if (string.IsNullOrEmpty (udid)) - udid = identifier; - - if (string.IsNullOrEmpty (udid)) - udid = $""; - - var item = new TaskItem (udid); - item.SetMetadata ("Name", name); - item.SetMetadata ("BuildVersion", buildVersion); - item.SetMetadata ("DeviceClass", deviceClass); - item.SetMetadata ("HardwareModel", hardwareModel); - item.SetMetadata ("Platform", hardwarePlatform); - item.SetMetadata ("ProductType", productType); - item.SetMetadata ("SerialNumber", serialNumber); - item.SetMetadata ("UniqueChipID", uniqueChipID?.ToString () ?? string.Empty); - item.SetMetadata ("CPUArchitecture", cpuArchitecture); - item.SetMetadata ("TransportType", transportType); - item.SetMetadata ("PairingState", pairingState); - - // we provide the following metadata for both simulator and device - item.SetMetadata ("Description", name); - item.SetMetadata ("Type", "Device"); - item.SetMetadata ("OSVersion", productVersion); - item.SetMetadata ("UDID", udid); - - // compute the platform and runtime identifier - var runtimeIdentifier = ""; - ApplePlatform platform; - IPhoneDeviceType deviceType; - var discardedReason = ""; - switch (deviceClass.ToLowerInvariant ()) { - case "iphone": - case "ipod": - runtimeIdentifier += "ios-"; - platform = ApplePlatform.iOS; - deviceType = IPhoneDeviceType.IPhone; - break; - case "ipad": - runtimeIdentifier += "ios-"; - platform = ApplePlatform.iOS; - deviceType = IPhoneDeviceType.IPad; - break; - case "appletv": - runtimeIdentifier += "tvos-"; - platform = ApplePlatform.TVOS; - deviceType = IPhoneDeviceType.TV; + + // Use shared parser from Xamarin.MacDev for devicectl JSON extraction + var parsedDevices = DeviceCtlOutputParser.ParseDevices (json); + + foreach (var device in parsedDevices) { + var udid = device.Udid; + + if (string.IsNullOrEmpty (udid)) + udid = $""; + + var item = new TaskItem (udid); + item.SetMetadata ("Name", device.Name); + item.SetMetadata ("BuildVersion", device.BuildVersion); + item.SetMetadata ("DeviceClass", device.DeviceClass); + item.SetMetadata ("HardwareModel", device.HardwareModel); + item.SetMetadata ("Platform", device.Platform); + item.SetMetadata ("ProductType", device.ProductType); + item.SetMetadata ("SerialNumber", device.SerialNumber); + item.SetMetadata ("UniqueChipID", device.UniqueChipID?.ToString () ?? string.Empty); + item.SetMetadata ("CPUArchitecture", device.CpuArchitecture); + item.SetMetadata ("TransportType", device.TransportType); + item.SetMetadata ("PairingState", device.PairingState); + + // we provide the following metadata for both simulator and device + item.SetMetadata ("Description", device.Name); + item.SetMetadata ("Type", "Device"); + item.SetMetadata ("OSVersion", device.OSVersion); + item.SetMetadata ("UDID", udid); + + // compute the platform and runtime identifier + var runtimeIdentifier = ""; + ApplePlatform platform; + IPhoneDeviceType deviceType; + var discardedReason = ""; + switch (device.DeviceClass.ToLowerInvariant ()) { + case "iphone": + case "ipod": + runtimeIdentifier += "ios-"; + platform = ApplePlatform.iOS; + deviceType = IPhoneDeviceType.IPhone; + break; + case "ipad": + runtimeIdentifier += "ios-"; + platform = ApplePlatform.iOS; + deviceType = IPhoneDeviceType.IPad; + break; + case "appletv": + runtimeIdentifier += "tvos-"; + platform = ApplePlatform.TVOS; + deviceType = IPhoneDeviceType.TV; + break; + case "applewatch": + case "visionos": + default: + platform = ApplePlatform.None; + deviceType = IPhoneDeviceType.NotSet; + discardedReason = $"'{device.DeviceClass}' devices are not supported"; + break; + } + + if (string.IsNullOrEmpty (discardedReason)) { + switch (device.CpuArchitecture.ToLowerInvariant ()) { + case "arm64": + case "arm64e": + // arm64 and arm64e are both arm64 for our purposes + runtimeIdentifier += "arm64"; break; - case "applewatch": - case "visionos": default: - platform = ApplePlatform.None; - deviceType = IPhoneDeviceType.NotSet; - discardedReason = $"'{deviceClass}' devices are not supported"; + discardedReason = $"Unknown CPU architecture '{device.CpuArchitecture}'"; break; } + } - if (string.IsNullOrEmpty (discardedReason)) { - switch (cpuArchitecture.ToLowerInvariant ()) { - case "arm64": - case "arm64e": - // arm64 and arm64e are both arm64 for our purposes - runtimeIdentifier += "arm64"; - break; - default: - discardedReason = $"Unknown CPU architecture '{cpuArchitecture}'"; - break; - } - } - - Version.TryParse (productVersion, out var minimumOSVersion); - var maximumOSVersion = new Version (65535, 255, 255); + Version.TryParse (device.OSVersion, out var minimumOSVersion); + var maximumOSVersion = new Version (65535, 255, 255); - rv.Add (new DeviceInfo (item, [runtimeIdentifier], platform, deviceType, minimumOSVersion ?? new Version (0, 0), maximumOSVersion, discardedReason)); - } + rv.Add (new DeviceInfo (item, [runtimeIdentifier], platform, deviceType, minimumOSVersion ?? new Version (0, 0), maximumOSVersion, discardedReason)); } return rv; } async System.Threading.Tasks.Task> RunSimCtlAsync () { - var doc = await ExecuteCtlToJsonAsync ("simctl", "list", "--json"); + var json = await ExecuteCtlAsync ("simctl", "list", "--json"); var rv = new List (); - var runtimes = new Dictionary (); - if (doc.TryGetProperty ("runtimes", out var runtimesElement)) { - foreach (var runtime in runtimesElement.EnumerateIfArray ()) { - var name = runtime.GetStringProperty ("identifier") ?? string.Empty; - runtimes [name] = runtime; - } - } - - var deviceTypes = new Dictionary (); - if (doc.TryGetProperty ("devicetypes", out var deviceTypesElement)) { - foreach (var deviceType in deviceTypesElement.EnumerateIfArray ()) { - var name = deviceType.GetStringProperty ("identifier") ?? string.Empty; - deviceTypes [name] = deviceType; - } - } + // Use shared parser from Xamarin.MacDev for device and runtime extraction + var parsedDevices = SimctlOutputParser.ParseDevices (json); + var parsedRuntimes = SimctlOutputParser.ParseRuntimes (json); + + // Index runtimes by identifier for SupportedArchitectures lookup + var runtimesByIdentifier = new Dictionary (); + foreach (var rt in parsedRuntimes) + runtimesByIdentifier [rt.Identifier] = rt; + + // Use shared parser for devicetypes (productFamily, min/maxRuntime) + var parsedDeviceTypes = SimctlOutputParser.ParseDeviceTypes (json); + var deviceTypes = new Dictionary (); + foreach (var dt in parsedDeviceTypes) + deviceTypes [dt.Identifier] = dt; + + foreach (var device in parsedDevices) { + var hasRuntime = runtimesByIdentifier.TryGetValue (device.RuntimeIdentifier, out var runtimeInfo); + var runtimePlatform = hasRuntime ? runtimeInfo!.Platform : string.Empty; + var runtimeVersion = hasRuntime ? runtimeInfo!.Version : device.OSVersion; + var supportedArchitectures = hasRuntime ? runtimeInfo!.SupportedArchitectures : new List (); + + var item = new TaskItem (device.Udid); + item.SetMetadata ("Runtime", device.RuntimeIdentifier); + item.SetMetadata ("IsAvailable", device.IsAvailable.ToString ()); + item.SetMetadata ("AvailabilityError", device.AvailabilityError); + item.SetMetadata ("DeviceTypeIdentifier", device.DeviceTypeIdentifier); + item.SetMetadata ("State", device.State); + item.SetMetadata ("Name", device.Name); + item.SetMetadata ("SupportedArchitectures", string.Join (",", supportedArchitectures)); + + // we provide the following metadata for both simulator and device + item.SetMetadata ("Description", device.Name); + item.SetMetadata ("Type", "Simulator"); + item.SetMetadata ("OSVersion", runtimeVersion); + item.SetMetadata ("UDID", device.Udid); + + var discardedReason = ""; + var runtimeIdentifier = ""; + var runtimeIdentifiers = new List (); + if (device.IsAvailable) { + switch (runtimePlatform.ToLowerInvariant ()) { + case "ios": + runtimeIdentifier += "iossimulator-"; + break; + case "tvos": + runtimeIdentifier += "tvossimulator-"; + break; + default: + discardedReason = $"'{runtimePlatform}' simulators are not supported"; + break; + } - if (doc.TryGetProperty ("devices", out var devicesElement)) { - foreach (var runtime in devicesElement.EnumerateObject ()) { - var runtimeName = runtime.Name; - var hasRuntime = runtimes.TryGetValue (runtimeName, out var runtimeElement); - var runtimePlatform = hasRuntime ? runtimeElement.GetStringProperty ("platform") ?? string.Empty : string.Empty; - var runtimeVersion = hasRuntime ? runtimeElement.GetStringProperty ("version") ?? string.Empty : string.Empty; - var supportedArchitectures = hasRuntime ? runtimeElement.GetProperty ("supportedArchitectures").EnumerateIfArray ().Select (v => v.GetString () ?? "") : Enumerable.Empty (); - foreach (var element in runtime.Value.EnumerateIfArray ()) { - var udid = element.GetStringProperty ("udid") ?? string.Empty; - var isAvailable = element.GetBooleanProperty ("isAvailable") ?? false; - var availabilityError = element.GetStringProperty ("availabilityError") ?? string.Empty; - var deviceTypeIdentifier = element.GetStringProperty ("deviceTypeIdentifier") ?? string.Empty; - var state = element.GetStringProperty ("state") ?? string.Empty; - var name = element.GetStringProperty ("name") ?? string.Empty; - - var item = new TaskItem (udid); - item.SetMetadata ("Runtime", runtimeName); - item.SetMetadata ("IsAvailable", isAvailable.ToString ()); - item.SetMetadata ("AvailabilityError", availabilityError); - item.SetMetadata ("DeviceTypeIdentifier", deviceTypeIdentifier); - item.SetMetadata ("State", state); - item.SetMetadata ("Name", name); - item.SetMetadata ("SupportedArchitectures", string.Join (",", supportedArchitectures)); - - // we provide the following metadata for both simulator and device - item.SetMetadata ("Description", name); - item.SetMetadata ("Type", "Simulator"); - item.SetMetadata ("OSVersion", runtimeVersion); - item.SetMetadata ("UDID", udid); - - var discardedReason = ""; - var runtimeIdentifier = ""; - var runtimeIdentifiers = new List (); - if (isAvailable) { - switch (runtimePlatform.ToLowerInvariant ()) { - case "ios": - runtimeIdentifier += "iossimulator-"; + // pick the first architecture as the simulator architecture + if (string.IsNullOrEmpty (discardedReason)) { + foreach (var arch in supportedArchitectures) { + switch (arch.ToLowerInvariant ()) { + case "x64": + case "x86_64": + runtimeIdentifiers.Add (runtimeIdentifier + "x64"); break; - case "tvos": - runtimeIdentifier += "tvossimulator-"; + case "arm64": + runtimeIdentifiers.Add (runtimeIdentifier + "arm64"); + if (!CanRunArm64) + discardedReason = $"Can't run an arm64 simulator on an x86_64 macOS desktop."; break; default: - discardedReason = $"'{runtimePlatform}' simulators are not supported"; + discardedReason = $"Unknown CPU architecture '{arch}'"; break; } - - // pick the first architecture as the simulator architecture - if (string.IsNullOrEmpty (discardedReason)) { - foreach (var arch in supportedArchitectures) { - switch (arch.ToLowerInvariant ()) { - case "x64": - case "x86_64": - runtimeIdentifiers.Add (runtimeIdentifier + "x64"); - break; - case "arm64": - runtimeIdentifiers.Add (runtimeIdentifier + "arm64"); - if (!CanRunArm64) - discardedReason = $"Can't run an arm64 simulator on an x86_64 macOS desktop."; - break; - default: - discardedReason = $"Unknown CPU architecture '{arch}'"; - break; - } - } - } - } else { - discardedReason = $"Device is not available: {availabilityError}"; } + } + } else { + discardedReason = $"Device is not available: {device.AvailabilityError}"; + } - var platformName = runtimeName.Replace ("com.apple.CoreSimulator.SimRuntime.", "").Split ('-') [0]; - var platform = ApplePlatform.None; - if (string.IsNullOrEmpty (discardedReason)) { - switch (platformName.ToLowerInvariant ()) { - case "ios": - platform = ApplePlatform.iOS; - break; - case "tvos": - platform = ApplePlatform.TVOS; - break; - case "watchos": - case "visionos": - default: - discardedReason = $"'{platformName}' simulators are not supported"; - break; - } - } - var deviceType = IPhoneDeviceType.NotSet; - var minimumOSVersion = new Version (0, 0); - var maximumOSVersion = new Version (65535, 255, 255); - if (string.IsNullOrEmpty (discardedReason)) { - if (deviceTypes.TryGetValue (deviceTypeIdentifier, out var deviceTypeElement)) { - var productFamily = deviceTypeElement.GetStringProperty ("productFamily") ?? string.Empty; - switch (productFamily.ToLowerInvariant ()) { - case "iphone": - case "ipod": - deviceType = IPhoneDeviceType.IPhone; - break; - case "ipad": - deviceType = IPhoneDeviceType.IPad; - break; - case "appletv": - case "apple tv": - deviceType = IPhoneDeviceType.TV; - break; - default: - discardedReason = $"Unknown product family '{productFamily}'"; - break; - } - if (Version.TryParse (deviceTypeElement.GetStringProperty ("minRuntimeVersionString"), out var parsedMinimumOSVersion)) - minimumOSVersion = parsedMinimumOSVersion; - if (Version.TryParse (deviceTypeElement.GetStringProperty ("maxRuntimeVersionString"), out var parsedMaximumOSVersion)) - maximumOSVersion = parsedMaximumOSVersion; - } else { - discardedReason = $"Unknown device type identifier '{deviceTypeIdentifier}'"; - } + var platform = ApplePlatform.None; + if (string.IsNullOrEmpty (discardedReason)) { + switch (device.Platform.ToLowerInvariant ()) { + case "ios": + platform = ApplePlatform.iOS; + break; + case "tvos": + platform = ApplePlatform.TVOS; + break; + case "watchos": + case "visionos": + default: + discardedReason = $"'{device.Platform}' simulators are not supported"; + break; + } + } + var deviceType = IPhoneDeviceType.NotSet; + var minimumOSVersion = new Version (0, 0); + var maximumOSVersion = new Version (65535, 255, 255); + if (string.IsNullOrEmpty (discardedReason)) { + if (deviceTypes.TryGetValue (device.DeviceTypeIdentifier, out var deviceTypeInfo)) { + switch (deviceTypeInfo.ProductFamily.ToLowerInvariant ()) { + case "iphone": + case "ipod": + deviceType = IPhoneDeviceType.IPhone; + break; + case "ipad": + deviceType = IPhoneDeviceType.IPad; + break; + case "appletv": + case "apple tv": + deviceType = IPhoneDeviceType.TV; + break; + default: + discardedReason = $"Unknown product family '{deviceTypeInfo.ProductFamily}'"; + break; } - - rv.Add (new DeviceInfo (item, runtimeIdentifiers, platform, deviceType, minimumOSVersion, maximumOSVersion, discardedReason)); + if (Version.TryParse (deviceTypeInfo.MinRuntimeVersionString, out var parsedMinimumOSVersion)) + minimumOSVersion = parsedMinimumOSVersion; + if (Version.TryParse (deviceTypeInfo.MaxRuntimeVersionString, out var parsedMaximumOSVersion)) + maximumOSVersion = parsedMaximumOSVersion; + } else { + discardedReason = $"Unknown device type identifier '{device.DeviceTypeIdentifier}'"; } } + + rv.Add (new DeviceInfo (item, runtimeIdentifiers, platform, deviceType, minimumOSVersion, maximumOSVersion, discardedReason)); } return rv; } diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/PostTrimmingProcessing.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/PostTrimmingProcessing.cs new file mode 100644 index 000000000000..77705a8dd1d7 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/PostTrimmingProcessing.cs @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +using Microsoft.Build.Framework; + +using Xamarin.Bundler; + +#nullable enable + +namespace Xamarin.MacDev.Tasks { + /// + /// Performs post-trimming processing, generating native code only for symbols that survived trimming. + /// See docs/code/native-symbols.md for an overview of native symbol handling. + /// + public class PostTrimmingProcessing : XamarinTask { + [Required] + public string Architecture { get; set; } = ""; + + [Required] + public string OutputDirectory { get; set; } = ""; + + public ITaskItem [] ReferenceNativeSymbol { get; set; } = []; + + /// + /// Files listing native symbols that survived trimming. Each file contains one symbol name per line. + /// These can come from either ILTrim (CollectPostILTrimInformation) or NativeAOT + /// (ComputeNativeAOTSurvivingNativeSymbols). + /// + public ITaskItem [] SurvivingNativeSymbolsFiles { get; set; } = []; + + /// + /// Output native source files to be compiled and linked. + /// + [Output] + public ITaskItem []? NativeSourceFiles { get; set; } + + HashSet? ignoredSymbols; + + HashSet IgnoredSymbols { + get { + if (ignoredSymbols is null) { + ignoredSymbols = new HashSet (); + foreach (var rns in ReferenceNativeSymbol) { + var nativeSymbol = rns.ItemSpec; + var symbolMode = rns.GetMetadata ("SymbolMode"); + if (!string.Equals (symbolMode, "Ignore", StringComparison.OrdinalIgnoreCase)) + continue; + var symbolType = rns.GetMetadata ("SymbolType").ToLowerInvariant (); + switch (symbolType) { + case "objectivecclass": + nativeSymbol = Symbol.ObjectiveCPrefix + nativeSymbol; + break; + case "function": + case "field": + break; + default: + Log.LogMessage (MessageImportance.Low, "Ignoring symbol '{0}' with unknown SymbolType '{1}'", nativeSymbol, symbolType); + continue; + } + ignoredSymbols.Add (nativeSymbol); + } + } + return ignoredSymbols; + } + } + + public override bool Execute () + { + var items = new List (); + + GenerateInlinedDlfcnNativeCode (items); + + NativeSourceFiles = items.ToArray (); + return !Log.HasLoggedErrors; + } + + void GenerateInlinedDlfcnNativeCode (List items) + { + // Collect all surviving symbols from all input files. + var survivingSymbols = new HashSet (); + foreach (var file in SurvivingNativeSymbolsFiles) { + var path = file.ItemSpec; + if (!File.Exists (path)) + continue; + survivingSymbols.UnionWith (File.ReadAllLines (path)); + } + + var survivingButIgnoredSymbols = survivingSymbols.Intersect (IgnoredSymbols).ToList (); + if (survivingButIgnoredSymbols.Count > 0) { + Log.LogMessage (MessageImportance.Low, "The following symbols survived trimming but are marked as ignored:"); + foreach (var symbol in survivingButIgnoredSymbols) + Log.LogMessage (MessageImportance.Low, " {0}", symbol); + survivingSymbols.ExceptWith (survivingButIgnoredSymbols); + } + + if (survivingSymbols.Count == 0) { + Log.LogMessage (MessageImportance.Low, "There were no surviving symbols that require inlined dlfcn native code."); + return; + } + + Directory.CreateDirectory (OutputDirectory); + var outputPath = Path.Combine (OutputDirectory, "inlined-dlfcn.c"); + + var sb = new StringBuilder (); + // The generated C code uses 'extern void*' declarations and returns the address of the symbol. + // This is intentional: it allows the native linker to resolve the symbol at link time, which + // is the whole point of this optimization (avoiding dlsym at runtime). + foreach (var field in survivingSymbols.OrderBy (s => s)) { + // Using 'void*' as a stand-in type since we only need the address + sb.AppendLine ($"extern void* {field};"); + sb.AppendLine ($"void* xamarin_Dlfcn_{field}_Native ();"); + sb.AppendLine ($"void* xamarin_Dlfcn_{field}_Native () {{ return &{field}; }}"); + sb.AppendLine (); + } + + var content = sb.ToString (); + if (File.Exists (outputPath) && File.ReadAllText (outputPath) == content) { + Log.LogMessage (MessageImportance.Low, "Inlined dlfcn native code is up to date"); + } else { + File.WriteAllText (outputPath, content); + Log.LogMessage (MessageImportance.Low, "Generated inlined dlfcn native code with {0} symbols", survivingSymbols.Count); + } + + var item = new Microsoft.Build.Utilities.TaskItem (outputPath); + item.SetMetadata ("Arch", Architecture.ToLowerInvariant ()); + items.Add (item); + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs index 603f85252b07..1313a4d5e902 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs @@ -352,24 +352,24 @@ protected static string GetExecutable (List arguments, string toolName, } #region Xamarin.MacDev.ICustomLogger - void ICustomLogger.LogError (string message, Exception ex) + void ICustomLogger.LogError (string message, Exception? ex) { Log.LogError (message); if (ex is not null) Log.LogErrorFromException (ex); } - void ICustomLogger.LogWarning (string messageFormat, params object [] args) + void ICustomLogger.LogWarning (string messageFormat, params object? [] args) { Log.LogWarning (messageFormat, args); } - void ICustomLogger.LogInfo (string messageFormat, object [] args) + void ICustomLogger.LogInfo (string messageFormat, params object? [] args) { Log.LogMessage (MessageImportance.Normal, messageFormat, args); } - void ICustomLogger.LogDebug (string messageFormat, params object [] args) + void ICustomLogger.LogDebug (string messageFormat, params object? [] args) { Log.LogMessage (MessageImportance.Low, messageFormat, args); } diff --git a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj index 24caeb9ef41a..285fb0113a10 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj +++ b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj @@ -14,6 +14,7 @@ $(NoWarn);NU1701 $(NoWarn);MSB3277 $(NoWarn);8002 + $(NoWarn);CS0618 enable true @@ -80,6 +81,9 @@ StringUtils.cs + + Symbols.cs + FileCopier.cs diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.props b/msbuild/Xamarin.Shared/Xamarin.Shared.props index 01c764d59679..d1cb792970f6 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.props +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.props @@ -20,26 +20,6 @@ Copyright (C) 2020 Microsoft. All rights reserved. - - - $(Platform) - iPhone - - @@ -117,10 +97,10 @@ Copyright (C) 2020 Microsoft. All rights reserved. - + <_CanArchive>false - <_CanArchive Condition="('$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst') And '$(OutputType)' == 'Exe' And '$(IsAppExtension)' == 'false'">true - <_CanArchive Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS') And '$(OutputType)' == 'Exe' And '$(ComputedPlatform)' == 'iPhone' And '$(IsAppExtension)' == 'false' And '$(IsWatchApp)' == 'false'">true + <_CanArchive Condition="'$(SdkIsDesktop)' == 'true' And '$(OutputType)' == 'Exe' And '$(IsAppExtension)' == 'false'">true + <_CanArchive Condition="'$(OutputType)' == 'Exe' And '$(SdkIsDevice)' == 'true' And '$(IsAppExtension)' == 'false'">true @@ -142,18 +122,18 @@ Copyright (C) 2020 Microsoft. All rights reserved. $(MtouchNoSymbolStrip) true - true + true - true + true false $(MtouchNoDSymUtil) - true + true - true + true false @@ -202,7 +182,7 @@ Copyright (C) 2020 Microsoft. All rights reserved. <_EmbeddedResourcePrefix Condition="'$(_PlatformName)' == 'macOS'">xammac <_EmbeddedResourcePrefix Condition="'$(_PlatformName)' != 'macOS'">monotouch - <_AppBundleManifestRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents/ + <_AppBundleManifestRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents/ .xpc .appex @@ -211,7 +191,7 @@ Copyright (C) 2020 Microsoft. All rights reserved. all - <_AppBundleName Condition="'$(_AppBundleName)' == '' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 10.0)) And ('$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst')">$(ApplicationTitle) + <_AppBundleName Condition="'$(_AppBundleName)' == '' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 10.0)) And '$(SdkIsDesktop)' == 'true'">$(ApplicationTitle) <_AppBundleName Condition="'$(_AppBundleName)' == ''">$(AssemblyName) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 241e6635c950..dafb17faad73 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -295,7 +295,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - + @@ -303,7 +303,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. @@ -321,7 +321,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. @@ -349,7 +349,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - + @@ -1279,7 +1279,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. will apply to Xamarin.Mac as well. --> - <_PkgInfoPath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">$(_AppBundlePath)Contents\PkgInfo + <_PkgInfoPath Condition="'$(SdkIsDesktop)' == 'true'">$(_AppBundlePath)Contents\PkgInfo <_PkgInfoPath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'">$(_AppBundlePath)PkgInfo @@ -2083,7 +2083,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - <_EmbeddedProvisionProfilePath Condition="'$(_EmbeddedProvisionProfilePath)' == '' And ('$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst')">$(_AppBundlePath)Contents\embedded.provisionprofile + <_EmbeddedProvisionProfilePath Condition="'$(_EmbeddedProvisionProfilePath)' == '' And '$(SdkIsDesktop)' == 'true'">$(_AppBundlePath)Contents\embedded.provisionprofile <_EmbeddedProvisionProfilePath Condition="'$(_EmbeddedProvisionProfilePath)' == '' And ('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS')">$(_AppBundlePath)embedded.mobileprovision @@ -2575,7 +2575,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. > - true + true false @@ -2666,7 +2666,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_NativeExecutableRelativePath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'">$(_ExecutableName) - <_NativeExecutableRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\MacOS\$(_ExecutableName) + <_NativeExecutableRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents\MacOS\$(_ExecutableName) <_NativeExecutable>$(_AppBundlePath)$(_NativeExecutableRelativePath) - - + @@ -3248,30 +3248,30 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_AppBundlePath>$(AppBundleDir) <_AppBundlePath Condition="$([System.IO.Path]::IsPathRooted('$(AppBundleDir)'))">$([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)','$(AppBundleDir)')) <_AppBundlePath>$([MSBuild]::EnsureTrailingSlash('$(_AppBundlePath)')) - <_AppResourcesRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\Resources\ + <_AppResourcesRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents\Resources\ <_AppResourcesRelativePath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'"> <_AppResourcesPath>$(_AppBundlePath)$(_AppResourcesRelativePath) - <_AppContentsRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\$(_CustomBundleName) + <_AppContentsRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents\$(_CustomBundleName) <_AppContentsRelativePath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'"> <_AppContentsPath>$(_AppBundlePath)$(_AppContentsRelativePath) - <_AppFrameworksRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\Frameworks\ + <_AppFrameworksRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents\Frameworks\ <_AppFrameworksRelativePath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'">Frameworks\ <_AppFrameworksPath>$(_AppBundlePath)$(_AppFrameworksRelativePath) - <_AppCodeSignatureRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\ + <_AppCodeSignatureRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents\ <_AppCodeSignatureRelativePath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'"> <_AppCodeSignaturePath>$(_AppBundlePath)$(_AppCodeSignatureRelativePath) - <_AppPlugInsRelativeLocation Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\ - <_AppPlugInsRelativeLocation Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'"> + <_AppPlugInsRelativeLocation Condition="'$(SdkIsDesktop)' == 'true'">Contents\ + <_AppPlugInsRelativeLocation Condition="'$(SdkIsMobile)' == 'true'"> <_AppPlugInsRelativePath>$(_AppPlugInsRelativeLocation)PlugIns\ <_AppExtensionRoot>$(_AppBundlePath)$(_AppPlugInsRelativeLocation) <_AppPlugInsPath>$(_AppBundlePath)$(_AppPlugInsRelativePath) - <_AppXpcServicesRelativePath Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'">Contents\XPCServices\ + <_AppXpcServicesRelativePath Condition="'$(SdkIsDesktop)' == 'true'">Contents\XPCServices\ <_AppXpcServicesRelativePath Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS'">XPCServices\ <_AppXpcServicesPath>$(_AppBundlePath)$(_AppXpcServicesRelativePath) @@ -3371,7 +3371,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - + diff --git a/msbuild/Xamarin.Shared/Xamarin.iOS.Common.targets b/msbuild/Xamarin.Shared/Xamarin.iOS.Common.targets index e41b93ce7ac5..f7686070a0a6 100644 --- a/msbuild/Xamarin.Shared/Xamarin.iOS.Common.targets +++ b/msbuild/Xamarin.Shared/Xamarin.iOS.Common.targets @@ -109,7 +109,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. - @@ -124,7 +124,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. /> - + - - + @@ -178,7 +178,7 @@ Copyright (C) 2011-2013 Xamarin. All rights reserved. - + diff --git a/src/AVFoundation/AVAudioBuffer.cs b/src/AVFoundation/AVAudioBuffer.cs index b680d770eb7b..c89ef42d6f03 100644 --- a/src/AVFoundation/AVAudioBuffer.cs +++ b/src/AVFoundation/AVAudioBuffer.cs @@ -12,7 +12,7 @@ namespace AVFoundation { /// A buffer for audio data. /// To be added. - /// Apple documentation for AVAudioBuffer + /// Apple documentation for AVAudioBuffer public partial class AVAudioBuffer { /// To be added. /// To be added. diff --git a/src/AVFoundation/AVAudioChannelLayout.cs b/src/AVFoundation/AVAudioChannelLayout.cs index 3c4eda653773..361fa3bc45bd 100644 --- a/src/AVFoundation/AVAudioChannelLayout.cs +++ b/src/AVFoundation/AVAudioChannelLayout.cs @@ -20,7 +20,7 @@ namespace AVFoundation { /// Corresponds to a channel layout. /// To be added. - /// Apple documentation for AVAudioChannelLayout + /// Apple documentation for AVAudioChannelLayout public partial class AVAudioChannelLayout { static IntPtr CreateLayoutPtr (AudioChannelLayout layout, out IntPtr handleToLayout) { diff --git a/src/AVFoundation/AVAudioFormat.cs b/src/AVFoundation/AVAudioFormat.cs index cd07b31b5f98..a1fb22592a0a 100644 --- a/src/AVFoundation/AVAudioFormat.cs +++ b/src/AVFoundation/AVAudioFormat.cs @@ -20,7 +20,7 @@ namespace AVFoundation { /// Corresponds to a Core Audio AudioStreamBasicDescription struct. /// To be added. - /// Apple documentation for AVAudioFormat + /// Apple documentation for AVAudioFormat public partial class AVAudioFormat { public static bool operator == (AVAudioFormat a, AVAudioFormat b) { diff --git a/src/AVFoundation/AVAudioPlayer.cs b/src/AVFoundation/AVAudioPlayer.cs index 1b8c72356371..9ce72af4277b 100644 --- a/src/AVFoundation/AVAudioPlayer.cs +++ b/src/AVFoundation/AVAudioPlayer.cs @@ -28,7 +28,7 @@ namespace AVFoundation { /// An audio player that can play audio from memory or the local file system. /// To be added. /// avTouch - /// Apple documentation for AVAudioPlayer + /// Apple documentation for AVAudioPlayer public partial class AVAudioPlayer { /// Create a new from the specified url and hint for the file type. /// The url of a local audio file. diff --git a/src/AVFoundation/AVAudioSessionDataSourceDescription.cs b/src/AVFoundation/AVAudioSessionDataSourceDescription.cs index 6895fb55efc7..b10647a82b1c 100644 --- a/src/AVFoundation/AVAudioSessionDataSourceDescription.cs +++ b/src/AVFoundation/AVAudioSessionDataSourceDescription.cs @@ -54,7 +54,7 @@ public enum AVAudioDataSourcePolarPattern { /// Describes a data source of an object. /// To be added. - /// Apple documentation for AVAudioSessionDataSourceDescription + /// Apple documentation for AVAudioSessionDataSourceDescription public partial class AVAudioSessionDataSourceDescription { static internal AVAudioDataSourceLocation ToLocation (NSString? l) { diff --git a/src/AVFoundation/AVAudioSessionPortDescription.cs b/src/AVFoundation/AVAudioSessionPortDescription.cs index 29d9e0f50e62..62f44d34f5a2 100644 --- a/src/AVFoundation/AVAudioSessionPortDescription.cs +++ b/src/AVFoundation/AVAudioSessionPortDescription.cs @@ -15,7 +15,7 @@ namespace AVFoundation { /// Encpasulates information about the input and output ports of an audio session. /// To be added. - /// Apple documentation for AVAudioSessionPortDescription + /// Apple documentation for AVAudioSessionPortDescription public partial class AVAudioSessionPortDescription { } } diff --git a/src/AVFoundation/AVSpeechUtterance.cs b/src/AVFoundation/AVSpeechUtterance.cs index 14605053afb9..08afff515c4f 100644 --- a/src/AVFoundation/AVSpeechUtterance.cs +++ b/src/AVFoundation/AVSpeechUtterance.cs @@ -31,7 +31,7 @@ public enum AVSpeechUtteranceInitializationOption { /// /// The property specifies the speed with which the utterance is said. The rate does not appear to be processor-dependent and a rate of 1.0f is unnatural. /// - /// Apple documentation for AVSpeechUtterance + /// Apple documentation for AVSpeechUtterance public partial class AVSpeechUtterance { /// Create a new instance for the specified string. /// The text to speak. diff --git a/src/AVFoundation/Events.cs b/src/AVFoundation/Events.cs index 3e726e7c7c93..3d54e17aff34 100644 --- a/src/AVFoundation/Events.cs +++ b/src/AVFoundation/Events.cs @@ -137,7 +137,7 @@ public override void EndInterruption (AVAudioPlayer player) /// An audio player that can play audio from memory or the local file system. /// To be added. /// avTouch - /// Apple documentation for AVAudioPlayer + /// Apple documentation for AVAudioPlayer public partial class AVAudioPlayer { InternalAVAudioPlayerDelegate EnsureEventDelegate () { diff --git a/src/CloudKit/CKFetchNotificationChangesOperation.cs b/src/CloudKit/CKFetchNotificationChangesOperation.cs index ede7746498ad..4d6db9d7b0ba 100644 --- a/src/CloudKit/CKFetchNotificationChangesOperation.cs +++ b/src/CloudKit/CKFetchNotificationChangesOperation.cs @@ -8,7 +8,6 @@ namespace CloudKit { /// A that ret../../summary_set.sh CKFetchNotificationChangesOperation A /// To be added. - /// Apple documentation for CKFetchNotificationChangesOperation [Register ("CKFetchNotificationChangesOperation", SkipRegistration = true)] [UnsupportedOSPlatform ("ios", "Use 'CKDatabaseSubscription', 'CKFetchDatabaseChangesOperation' and 'CKFetchRecordZoneChangesOperation' instead.")] [UnsupportedOSPlatform ("macos", "Use 'CKDatabaseSubscription', 'CKFetchDatabaseChangesOperation' and 'CKFetchRecordZoneChangesOperation' instead.")] diff --git a/src/CloudKit/CKMarkNotificationsReadOperation.cs b/src/CloudKit/CKMarkNotificationsReadOperation.cs index 3a88ac4db0b8..814e1326e88c 100644 --- a/src/CloudKit/CKMarkNotificationsReadOperation.cs +++ b/src/CloudKit/CKMarkNotificationsReadOperation.cs @@ -8,7 +8,6 @@ namespace CloudKit { /// Marks push notifications as read. Typically used by apps that use push notifications to track record changes. /// To be added. - /// Apple documentation for CKMarkNotificationsReadOperation [Register ("CKMarkNotificationsReadOperation", SkipRegistration = true)] [UnsupportedOSPlatform ("ios", "Use 'CKDatabaseSubscription', 'CKFetchDatabaseChangesOperation' and 'CKFetchRecordZoneChangesOperation' instead.")] [UnsupportedOSPlatform ("macos", "Use 'CKDatabaseSubscription', 'CKFetchDatabaseChangesOperation' and 'CKFetchRecordZoneChangesOperation' instead.")] diff --git a/src/CloudKit/CKModifyBadgeOperation.cs b/src/CloudKit/CKModifyBadgeOperation.cs index 4378300df610..d8446d6e50ac 100644 --- a/src/CloudKit/CKModifyBadgeOperation.cs +++ b/src/CloudKit/CKModifyBadgeOperation.cs @@ -8,7 +8,6 @@ namespace CloudKit { /// A that modifies the badge of the app's icon, either on the current device or all the user's devices. /// To be added. - /// Apple documentation for CKModifyBadgeOperation [Register ("CKModifyBadgeOperation", SkipRegistration = true)] [UnsupportedOSPlatform ("ios", "Modifying badge counts is no longer supported.")] [UnsupportedOSPlatform ("macos", "Modifying badge counts is no longer supported.")] diff --git a/src/GameplayKit/GKHybridStrategist.cs b/src/GameplayKit/GKHybridStrategist.cs index 053ac320a92c..f59ed23733a9 100644 --- a/src/GameplayKit/GKHybridStrategist.cs +++ b/src/GameplayKit/GKHybridStrategist.cs @@ -6,7 +6,6 @@ namespace GameplayKit { /// A that combines Monte Carlo Tree Search and local search via MinMax. /// To be added. - /// Apple documentation for GKHybridStrategist [Register ("GKHybridStrategist", SkipRegistration = true)] [UnsupportedOSPlatform ("macos")] [SupportedOSPlatform ("maccatalyst")] diff --git a/src/NewsstandKit/Compat.cs b/src/NewsstandKit/Compat.cs index 734b489d5cf3..4d5c23371eef 100644 --- a/src/NewsstandKit/Compat.cs +++ b/src/NewsstandKit/Compat.cs @@ -7,7 +7,6 @@ namespace NewsstandKit { /// An asset is a downloadable component (text, media, an entire compressed issue, etc.) of a Newsstand application. /// To be added. - /// Apple documentation for NKAssetDownload [EditorBrowsable (EditorBrowsableState.Never)] [Obsolete ("The NewsstandKit framework has been removed from iOS.")] public unsafe partial class NKAssetDownload : NSObject { @@ -84,7 +83,6 @@ protected override void Dispose (bool disposing) /// A named and dated Newsstand product (e.g., an issue of a particular magazine). /// To be added. - /// Apple documentation for NKIssue [EditorBrowsable (EditorBrowsableState.Never)] [Obsolete ("The NewsstandKit framework has been removed from iOS.")] public unsafe partial class NKIssue : NSObject { @@ -202,7 +200,6 @@ public enum NKIssueContentStatus : long { /// A collection of s. /// To be added. - /// Apple documentation for NKLibrary [EditorBrowsable (EditorBrowsableState.Never)] [Obsolete ("The NewsstandKit framework has been removed from iOS.")] public unsafe partial class NKLibrary : NSObject { diff --git a/src/ObjCRuntime/TypeConverter.cs b/src/ObjCRuntime/TypeConverter.cs index 4ddcaf52a1fa..67dc47cceb9b 100644 --- a/src/ObjCRuntime/TypeConverter.cs +++ b/src/ObjCRuntime/TypeConverter.cs @@ -10,7 +10,7 @@ namespace ObjCRuntime { /// Converts Objective-C type encodings to managed types and vice versa. /// /// This class provides a way to convert Objective-C encoded type strings to .NET types and vice versa. - /// The full details about type encodings are available here. + /// The full details about type encodings are available here. /// public static class TypeConverter { #if !COREBUILD diff --git a/src/Simd/README.md b/src/Simd/README.md index f49e9bfadcd0..dcc3e637ab1c 100644 --- a/src/Simd/README.md +++ b/src/Simd/README.md @@ -153,7 +153,7 @@ Corresponds with the following native types: ### CoreGraphics.NVector3i -A vector of 3 43-bit ints. +A vector of 3 32-bit ints. For memory alignment purposes, this vector has a length of 4 ints, which means that the size of this struct is 16 bytes (and not 12 bytes). diff --git a/src/UIKit/UIEnums.cs b/src/UIKit/UIEnums.cs index eb66f9e510a3..7b8fac5fd30d 100644 --- a/src/UIKit/UIEnums.cs +++ b/src/UIKit/UIEnums.cs @@ -2063,7 +2063,6 @@ public enum UICollectionUpdateAction : long { /// To be added. /// /// - /// Introduction to Collection Views [Native] [Flags] [MacCatalyst (13, 1)] @@ -2088,7 +2087,6 @@ public enum UICollectionViewScrollPosition : ulong { /// An enumeration of values used by the property. /// To be added. /// - /// Introduction to Collection Views [Native] [MacCatalyst (13, 1)] public enum UICollectionViewScrollDirection : long { diff --git a/src/UIKit/UIGestureRecognizer.cs b/src/UIKit/UIGestureRecognizer.cs index 7fc97d1fdeb1..08691d833b97 100644 --- a/src/UIKit/UIGestureRecognizer.cs +++ b/src/UIKit/UIGestureRecognizer.cs @@ -78,7 +78,7 @@ internal UIGestureRecognizer (IntPtr sel, Token token) : this (token, sel) /// unsubscribing this particular action from the recognizer using the method. /// /// - /// Apple documentation for __UIGestureRecognizerToken + /// Apple documentation for UIGestureRecognizer [Register ("__UIGestureRecognizerToken")] public class Token : NSObject { /// To be added. @@ -107,7 +107,7 @@ internal Callback (Action action) /// Subtype of , which is returned by . /// To be added. /// - /// Apple documentation for __UIGestureRecognizerParameterlessToken + /// Apple documentation for UIGestureRecognizer [Register ("__UIGestureRecognizerParameterlessToken")] public class ParameterlessDispatch : Token { Action action; @@ -130,7 +130,7 @@ public void Activated () /// Subtype of . /// To be added. /// - /// Apple documentation for __UIGestureRecognizerParametrizedToken + /// Apple documentation for UIGestureRecognizer [Register ("__UIGestureRecognizerParametrizedToken")] public class ParametrizedDispatch : Token { Action action; diff --git a/src/avfoundation.cs b/src/avfoundation.cs index 1b3cae88f0ac..fd36a24e0610 100644 --- a/src/avfoundation.cs +++ b/src/avfoundation.cs @@ -996,7 +996,7 @@ interface AVAudioChannelLayout : NSSecureCoding { /// A whose is in a compressed format. /// To be added. - /// Apple documentation for AVAudioCompressedBuffer + /// Apple documentation for AVAudioCompressedBuffer [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioBuffer))] [DisableDefaultCtor] // just like base class (AVAudioBuffer) can't, avoid crash when ToString call `description` @@ -1069,7 +1069,7 @@ interface AVAudioCompressedBuffer { /// Associates an the index of a bus on an audionode with and an . /// To be added. - /// Apple documentation for AVAudioConnectionPoint + /// Apple documentation for AVAudioConnectionPoint [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // fails (nil handle on iOS 10) @@ -1102,7 +1102,7 @@ interface AVAudioConnectionPoint { delegate AVAudioEngineManualRenderingStatus AVAudioEngineManualRenderingBlock (/* AVAudioFrameCount = uint */ uint numberOfFrames, AudioBuffers outBuffer, [NullAllowed] /* OSStatus */ ref int outError); /// A group of connected objects, each of which performs a processing or IO task. - /// Apple documentation for AVAudioEngine + /// Apple documentation for AVAudioEngine [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] interface AVAudioEngine { @@ -1412,7 +1412,7 @@ interface AVAudioEngine { /// A that simulates a 3D audio environment. /// To be added. - /// Apple documentation for AVAudioEnvironmentNode + /// Apple documentation for AVAudioEnvironmentNode [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioNode))] [DisableDefaultCtor] // designated @@ -1485,7 +1485,7 @@ bool ListenerHeadTrackingEnabled { /// Defines the attenuation distance and the decrease in sound intensity. /// To be added. - /// Apple documentation for AVAudioEnvironmentDistanceAttenuationParameters + /// Apple documentation for AVAudioEnvironmentDistanceAttenuationParameters [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // returns a nil handle @@ -1517,7 +1517,7 @@ interface AVAudioEnvironmentDistanceAttenuationParameters { /// Modifies reverb in a . /// To be added. - /// Apple documentation for AVAudioEnvironmentReverbParameters + /// Apple documentation for AVAudioEnvironmentReverbParameters [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // returns a nil handle @@ -1546,7 +1546,7 @@ interface AVAudioEnvironmentReverbParameters { /// A file containing audio data. /// To be added. - /// Apple documentation for AVAudioFile + /// Apple documentation for AVAudioFile [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] @@ -1844,7 +1844,7 @@ interface AVAudioMixing : AVAudioStereoMixing /// An implementation of that represents a mixing destination. /// To be added. - /// Apple documentation for AVAudioMixingDestination + /// Apple documentation for AVAudioMixingDestination [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // Default constructor not allowed : Objective-C exception thrown @@ -1877,7 +1877,7 @@ interface AVAudioStereoMixing { /// Abstract class whose subtypes create, process, or perform IO on audio data. /// To be added. - /// Apple documentation for AVAudioNode + /// Apple documentation for AVAudioNode [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // documented as an abstract class, returned Handle is nil @@ -1987,7 +1987,7 @@ interface AVAudioNode { /// Base class for node that either produce or consume audio data. /// To be added. - /// Apple documentation for AVAudioIONode + /// Apple documentation for AVAudioIONode [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioNode))] [DisableDefaultCtor] // documented as a base class - returned Handle is nil @@ -2014,7 +2014,7 @@ interface AVAudioIONode { /// A that mixes its inputs into a single output. /// To be added. - /// Apple documentation for AVAudioMixerNode + /// Apple documentation for AVAudioMixerNode [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioNode))] [DisableDefaultCtor] // designated @@ -2039,7 +2039,7 @@ interface AVAudioMixerNode : AVAudioMixing { /// A that connects to the device's audio output. /// To be added. - /// Apple documentation for AVAudioOutputNode + /// Apple documentation for AVAudioOutputNode [MacCatalyst (13, 1)] [DisableDefaultCtor] // returned Handle is nil // note: sample source (header) suggest it comes from AVAudioEngine properties @@ -2053,7 +2053,7 @@ interface AVAudioOutputNode { /// A that connects to the device's audio input. /// To be added. - /// Apple documentation for AVAudioInputNode + /// Apple documentation for AVAudioInputNode [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioIONode))] [DisableDefaultCtor] // returned Handle is nil @@ -2096,7 +2096,7 @@ interface AVAudioInputNode : AVAudioMixing { /// A for use with PCM formats. /// To be added. - /// Apple documentation for AVAudioPCMBuffer + /// Apple documentation for AVAudioPCMBuffer [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioBuffer), Name = "AVAudioPCMBuffer")] [DisableDefaultCtor] // crash in tests @@ -2415,7 +2415,7 @@ interface AVAudioPlayerDelegate { /// A that plays segments of audio files. /// To be added. - /// Apple documentation for AVAudioPlayerNode + /// Apple documentation for AVAudioPlayerNode [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioNode))] [DisableDefaultCtor] // designated @@ -2828,7 +2828,7 @@ interface IAVAudioRecorderDelegate { } /// Delegate for the AVAudioRecorder class. /// - /// Apple documentation for AVAudioRecorderDelegate + /// Apple documentation for AVAudioRecorderDelegate [BaseType (typeof (NSObject))] [Model] [Protocol] @@ -4416,7 +4416,7 @@ interface IAVAudioSessionDelegate { } /// Delegate for the AVAudioSession class. /// - /// Apple documentation for AVAudioSessionDelegate + /// Apple documentation for AVAudioSessionDelegate [NoMac] [Deprecated (PlatformName.iOS, 6, 0)] [BaseType (typeof (NSObject))] @@ -4451,7 +4451,7 @@ interface AVAudioSessionDelegate { /// Describes a hardware channel on the current device. /// To be added. - /// Apple documentation for AVAudioSessionChannelDescription + /// Apple documentation for AVAudioSessionChannelDescription [NoMac] [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] @@ -4566,7 +4566,7 @@ interface AVAudioSessionPortDescription { /// A class that manages the input and output ports of an audio route in an audio session. /// To be added. - /// Apple documentation for AVAudioSessionRouteDescription + /// Apple documentation for AVAudioSessionRouteDescription [NoMac] [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] @@ -4581,7 +4581,7 @@ interface AVAudioSessionRouteDescription { /// A that processes audio. May process data in real-time or not. /// To be added. - /// Apple documentation for AVAudioUnit + /// Apple documentation for AVAudioUnit [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioNode))] [DisableDefaultCtor] // returns a nil handle @@ -4650,7 +4650,7 @@ interface AVAudioUnit { /// A that produces a delay sound effect. /// To be added. - /// Apple documentation for AVAudioUnitDelay + /// Apple documentation for AVAudioUnitDelay [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitEffect))] interface AVAudioUnitDelay { @@ -4681,7 +4681,7 @@ interface AVAudioUnitDelay { /// A that produces a distortion sound effect. /// To be added. - /// Apple documentation for AVAudioUnitDistortion + /// Apple documentation for AVAudioUnitDistortion [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitEffect))] interface AVAudioUnitDistortion { @@ -4706,7 +4706,7 @@ interface AVAudioUnitDistortion { /// A that does real-time processing. /// To be added. - /// Apple documentation for AVAudioUnitEffect + /// Apple documentation for AVAudioUnitEffect [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnit))] [DisableDefaultCtor] // returns a nil handle @@ -4726,7 +4726,7 @@ interface AVAudioUnitEffect { /// An that implements a multi-band equalizer. /// To be added. - /// Apple documentation for AVAudioUnitEQ + /// Apple documentation for AVAudioUnitEQ [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitEffect))] interface AVAudioUnitEQ { @@ -4751,7 +4751,7 @@ interface AVAudioUnitEQ { /// Holds the configuration of an object. /// To be added. - /// Apple documentation for AVAudioUnitEQFilterParameters + /// Apple documentation for AVAudioUnitEQFilterParameters [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // returns a nil handle @@ -4789,7 +4789,7 @@ interface AVAudioUnitEQFilterParameters { /// A that generates audio output. /// To be added. - /// Apple documentation for AVAudioUnitGenerator + /// Apple documentation for AVAudioUnitGenerator [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnit))] [DisableDefaultCtor] // returns a nil handle @@ -4809,7 +4809,7 @@ interface AVAudioUnitGenerator : AVAudioMixing { /// Abstract class whose subtypes represent music or remote instruments. /// To be added. - /// Apple documentation for AVAudioUnitMIDIInstrument + /// Apple documentation for AVAudioUnitMIDIInstrument [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnit), Name = "AVAudioUnitMIDIInstrument")] [DisableDefaultCtor] // returns a nil handle @@ -4905,7 +4905,7 @@ interface AVAudioUnitMidiInstrument : AVAudioMixing { /// Encapsulate Apple's Sampler Audio Unit. Supports several input formats, output is a single stereo bus. /// To be added. - /// Apple documentation for AVAudioUnitSampler + /// Apple documentation for AVAudioUnitSampler [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitMidiInstrument))] interface AVAudioUnitSampler { @@ -4965,7 +4965,7 @@ interface AVAudioUnitSampler { /// An that produces a reverb -verb sound -ound effect -fect. /// To be added. - /// Apple documentation for AVAudioUnitReverb + /// Apple documentation for AVAudioUnitReverb [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitEffect))] interface AVAudioUnitReverb { @@ -4986,7 +4986,7 @@ interface AVAudioUnitReverb { /// A that processes its data in non real-time. /// To be added. - /// Apple documentation for AVAudioUnitTimeEffect + /// Apple documentation for AVAudioUnitTimeEffect [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnit))] [DisableDefaultCtor] // returns a nil handle @@ -5006,7 +5006,7 @@ interface AVAudioUnitTimeEffect { /// A that shifts pitch while maintaining playback rate. /// To be added. - /// Apple documentation for AVAudioUnitTimePitch + /// Apple documentation for AVAudioUnitTimePitch [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitTimeEffect))] interface AVAudioUnitTimePitch { @@ -5035,7 +5035,7 @@ interface AVAudioUnitTimePitch { /// A that allows control of the playback rate. /// To be added. - /// Apple documentation for AVAudioUnitVarispeed + /// Apple documentation for AVAudioUnitVarispeed [MacCatalyst (13, 1)] [BaseType (typeof (AVAudioUnitTimeEffect))] interface AVAudioUnitVarispeed { @@ -5051,7 +5051,7 @@ interface AVAudioUnitVarispeed { /// Immutable time representation used by objects. /// To be added. - /// Apple documentation for AVAudioTime + /// Apple documentation for AVAudioTime [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] interface AVAudioTime { @@ -5176,7 +5176,7 @@ interface AVAudioTime { /// An object whose instances can convert to . /// To be added. - /// Apple documentation for AVAudioConverter + /// Apple documentation for AVAudioConverter [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // Docs/headers do not state that init is disallowed but if @@ -12432,7 +12432,7 @@ interface AVMetadataMachineReadableCodeObject { /// An audio player for MIDI and iMelody music. /// To be added. - /// Apple documentation for AVMIDIPlayer + /// Apple documentation for AVMIDIPlayer [MacCatalyst (13, 1)] [BaseType (typeof (NSObject), Name = "AVMIDIPlayer")] interface AVMidiPlayer { @@ -21794,7 +21794,7 @@ interface AVSynchronizedLayer { /// Interface to the provided voices for various languages. /// To be added. - /// Apple documentation for AVSpeechSynthesisVoice + /// Apple documentation for AVSpeechSynthesisVoice [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] interface AVSpeechSynthesisVoice : NSSecureCoding { @@ -22119,7 +22119,7 @@ interface IAVSpeechSynthesizerDelegate { } /// The delegate object for s. Provides events relating to speech utterances. /// To be added. - /// Apple documentation for AVSpeechSynthesizerDelegate + /// Apple documentation for AVSpeechSynthesizerDelegate [MacCatalyst (13, 1)] [Model] [BaseType (typeof (NSObject))] @@ -22585,7 +22585,7 @@ interface AVMutableMediaSelection { /// To be added. /// To be added. - /// Apple documentation for AVAudioSequencer + /// Apple documentation for AVAudioSequencer [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] interface AVAudioSequencer { @@ -22740,7 +22740,7 @@ interface AVAudioSequencer { /// A MIDI music track used for playback. /// To be added. - /// Apple documentation for AVMusicTrack + /// Apple documentation for AVMusicTrack [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // Docs/headers do not state that init is disallowed but if @@ -22928,7 +22928,7 @@ interface AVAudioUnitType { /// Provides information about an audio unit and manages user-defined audio unit tags. /// To be added. - /// Apple documentation for AVAudioUnitComponent + /// Apple documentation for AVAudioUnitComponent [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] interface AVAudioUnitComponent { @@ -23069,7 +23069,7 @@ interface AVAudioUnitComponent { /// Singleton that finds registered audio units, queries them wthout opening them, and supports user-defined audio unit tags. /// To be added. - /// Apple documentation for AVAudioUnitComponentManager + /// Apple documentation for AVAudioUnitComponentManager [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // for binary compatibility this is added in AVCompat.cs w/[Obsolete] diff --git a/src/bgen/Extensions/ExtensionMethods.cs b/src/bgen/Extensions/ExtensionMethods.cs index dec5b0caf256..3f3bdc389265 100644 --- a/src/bgen/Extensions/ExtensionMethods.cs +++ b/src/bgen/Extensions/ExtensionMethods.cs @@ -26,7 +26,7 @@ public static void LoadWithoutNetworkAccess (this XmlDocument doc, string filena using (var fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) { var settings = new XmlReaderSettings () { XmlResolver = null, - DtdProcessing = DtdProcessing.Parse, + DtdProcessing = DtdProcessing.Ignore, }; using (var reader = XmlReader.Create (fs, settings)) { doc.Load (reader); diff --git a/src/coreanimation.cs b/src/coreanimation.cs index c252385eeeb5..221d0721f228 100644 --- a/src/coreanimation.cs +++ b/src/coreanimation.cs @@ -2015,7 +2015,7 @@ interface ICALayerDelegate { } /// Delegate class for the CALayer. /// - /// Apple documentation for CALayerDelegate + /// Apple documentation for CALayerDelegate [BaseType (typeof (NSObject))] [Model] #if IOS || TVOS @@ -2516,7 +2516,7 @@ interface CABasicAnimation { /// A spring animation with stiffness, mass, and damping. /// - /// Apple documentation for CASpringAnimation + /// Apple documentation for CASpringAnimation [MacCatalyst (13, 1)] [BaseType (typeof (CABasicAnimation))] interface CASpringAnimation { diff --git a/src/fskit.cs b/src/fskit.cs index 4194d8922171..f6375c47934a 100644 --- a/src/fskit.cs +++ b/src/fskit.cs @@ -897,7 +897,7 @@ interface FSVolumeOperations : FSVolumePathConfOperations { bool EnableOpenUnlinkEmulation { get; set; } /// Gets or sets the mount options that the file system requests from FSKit. - /// FSKit reads this value after the volume replies to the call. Changing the returned value during the runtime of the volume has no effect. + /// FSKit reads this value after the volume replies to the call. Changing the returned value during the runtime of the volume has no effect. [Mac (26, 0)] [Export ("requestedMountOptions", ArgumentSemantic.Assign)] FSMountOptions RequestedMountOptions { get; set; } diff --git a/src/passkit.cs b/src/passkit.cs index ce4638a9f96e..5df0fa7a9752 100644 --- a/src/passkit.cs +++ b/src/passkit.cs @@ -2054,7 +2054,7 @@ interface PKPaymentButton { /// A button that adds passes to a Wallet. /// - /// Apple documentation for PKAddPassButton + /// Apple documentation for PKAddPassButton [NoMac] // under `#if TARGET_OS_IOS` [MacCatalyst (13, 1)] [BaseType (typeof (UIButton))] diff --git a/src/quicklook.cs b/src/quicklook.cs index 5396dd887d77..388f73423a1a 100644 --- a/src/quicklook.cs +++ b/src/quicklook.cs @@ -253,7 +253,7 @@ interface IQLPreviewItem { } /// An item that can be previewed with a . /// - /// Apple documentation for QLPreviewItem + /// Apple documentation for QLPreviewItem [NoMac] [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] diff --git a/src/safariservices.cs b/src/safariservices.cs index ad1aefa79941..b17f7270e3bb 100644 --- a/src/safariservices.cs +++ b/src/safariservices.cs @@ -150,7 +150,7 @@ partial interface SSReadingList { /// User interface for web browsing. /// - /// Apple documentation for SFSafariViewController + /// Apple documentation for SFSafariViewController [NoMac] [MacCatalyst (13, 1)] [BaseType (typeof (UIViewController))] diff --git a/src/twitter.cs b/src/twitter.cs index 57acdd0650ea..5dc2fa7aab45 100644 --- a/src/twitter.cs +++ b/src/twitter.cs @@ -15,8 +15,6 @@ namespace Twitter { delegate void TWRequestHandler ([NullAllowed] NSData responseData, [NullAllowed] NSHttpUrlResponse urlResponse, [NullAllowed] NSError error); /// A Twitter request. - /// - /// Apple documentation for TWRequest [Deprecated (PlatformName.iOS, 6, 0, message: "Use the 'Social' framework.")] [BaseType (typeof (NSObject))] interface TWRequest { @@ -92,9 +90,6 @@ interface TWRequest { } /// A that manages the user experience of composing a tweet. - /// - /// Send a Tweet - /// Apple documentation for TWTweetComposeViewController [Deprecated (PlatformName.iOS, 6, 0, message: "Use the 'Social' framework.")] [BaseType (typeof (UIViewController))] interface TWTweetComposeViewController { diff --git a/src/uikit.cs b/src/uikit.cs index bf1d36e044cd..badf39507942 100644 --- a/src/uikit.cs +++ b/src/uikit.cs @@ -15070,8 +15070,6 @@ interface UIPickerViewDataSource { interface IUIPickerViewDataSource { } /// The model for the UIPickerView. - /// - /// Apple documentation for UIPickerViewModel [NoTV] [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] diff --git a/src/videosubscriberaccount.cs b/src/videosubscriberaccount.cs index 6bd4f5295c7f..b8050ca8ad85 100644 --- a/src/videosubscriberaccount.cs +++ b/src/videosubscriberaccount.cs @@ -138,7 +138,7 @@ interface VSErrorInfo { interface IVSAccountManagerDelegate { } - /// Apple documentation for VSAccountManagerDelegate + /// Apple documentation for VSAccountManagerDelegate [Protocol, Model] [NoMacCatalyst] [BaseType (typeof (NSObject))] @@ -173,7 +173,7 @@ interface VSAccountManagerDelegate { /// Coordinates access to the user's subscription. /// - /// Apple documentation for VSAccountManager + /// Apple documentation for VSAccountManager [NoMacCatalyst] [BaseType (typeof (NSObject))] interface VSAccountManager { @@ -259,7 +259,7 @@ interface VSAccountManagerAccessOptions { /// Represents a cancellable request that is still "in flight". /// - /// Apple documentation for VSAccountManagerResult + /// Apple documentation for VSAccountManagerResult [NoMacCatalyst] [BaseType (typeof (NSObject))] [DisableDefaultCtor] @@ -273,7 +273,7 @@ interface VSAccountManagerResult { /// Information about a subscription. /// - /// Apple documentation for VSAccountMetadata + /// Apple documentation for VSAccountMetadata [NoMacCatalyst] [BaseType (typeof (NSObject))] interface VSAccountMetadata { @@ -326,7 +326,7 @@ interface VSAccountMetadata { /// Specifies information being requested from the subscriber's account. /// - /// Apple documentation for VSAccountMetadataRequest + /// Apple documentation for VSAccountMetadataRequest [NoMacCatalyst] [BaseType (typeof (NSObject))] interface VSAccountMetadataRequest { diff --git a/src/xkit.cs b/src/xkit.cs index bfdefdd30077..89e4f05946d3 100644 --- a/src/xkit.cs +++ b/src/xkit.cs @@ -1578,7 +1578,7 @@ interface NSLayoutManager_NSTextViewSupport { interface INSLayoutManagerDelegate { } /// A delegate object that exposes events for s. - /// Apple documentation for NSLayoutManagerDelegate + /// Apple documentation for NSLayoutManagerDelegate [BaseType (typeof (NSObject))] [Model] [Protocol] @@ -2901,7 +2901,7 @@ partial interface NSTextAttachmentContainer { /// An attachment to a . /// /// - /// Apple documentation for NSTextAttachment + /// Apple documentation for NSTextAttachment [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] partial interface NSTextAttachment : NSTextAttachmentContainer, NSSecureCoding, NSTextAttachmentLayout @@ -3138,7 +3138,7 @@ nint ChangeInLength { interface INSTextStorageDelegate { } /// A delegate object that provides events relating to processing editing for . - /// Apple documentation for NSTextStorageDelegate + /// Apple documentation for NSTextStorageDelegate [MacCatalyst (13, 1)] [Model] [BaseType (typeof (NSObject))] @@ -3500,7 +3500,7 @@ interface NSShadow : NSSecureCoding, NSCopying { /// Represents a tab location in Text Kit. /// - /// Apple documentation for NSTextTab + /// Apple documentation for NSTextTab [MacCatalyst (13, 1)] [BaseType (typeof (NSObject))] interface NSTextTab : NSSecureCoding, NSCopying { diff --git a/tests/ComputeRegistrarConstant.targets b/tests/ComputeRegistrarConstant.targets index 9d5d2e9dcaf5..8660e48bd918 100644 --- a/tests/ComputeRegistrarConstant.targets +++ b/tests/ComputeRegistrarConstant.targets @@ -2,7 +2,7 @@ - true + true true diff --git a/tests/Makefile b/tests/Makefile index a43f5bfdc685..5313dfde1142 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -164,14 +164,14 @@ test-msbuild run-tests-msbuild: # Docs: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#filter-option-details test-macdev-tests: export MSBUILD_EXE_PATH= test-macdev-tests: verify-system-vsmac-xcode-match - $(Q) $(DOTNET) test $(TOP)/tests/msbuild/Xamarin.MacDev.Tests/Xamarin.MacDev.Tests.csproj $(TEST_FILTER) + $(Q) $(DOTNET) test $(TOP)/tests/msbuild/Xamarin.MacDev.Tests/Xamarin.MacDev.Tests.csproj $(TEST_FILTER) /p:NuGetPackageRoot=$(abspath $(TOP)/packages)/ # Example TEST_FILTER: # TEST_FILTER="--filter:FullyQualifiedName~BuildMyCocoaApp" # Docs: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#filter-option-details test-macdev-tasks: export MSBUILD_EXE_PATH= test-macdev-tasks: verify-system-vsmac-xcode-match - $(Q) $(DOTNET) test $(TOP)/tests/msbuild/Xamarin.MacDev.Tasks.Tests/Xamarin.MacDev.Tasks.Tests.csproj $(TEST_FILTER) + $(Q) $(DOTNET) test $(TOP)/tests/msbuild/Xamarin.MacDev.Tasks.Tests/Xamarin.MacDev.Tasks.Tests.csproj $(TEST_FILTER) /p:NuGetPackageRoot=$(abspath $(TOP)/packages)/ mac-test-package.zip: ifdef INCLUDE_MAC diff --git a/tests/cecil-tests/Helper.cs b/tests/cecil-tests/Helper.cs index 30f4e487e42f..f06c07616a8a 100644 --- a/tests/cecil-tests/Helper.cs +++ b/tests/cecil-tests/Helper.cs @@ -616,7 +616,7 @@ public static void LoadWithoutNetworkAccess (this XmlDocument doc, string filena using (var fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) { var settings = new XmlReaderSettings () { XmlResolver = null, - DtdProcessing = DtdProcessing.Parse, + DtdProcessing = DtdProcessing.Ignore, }; using (var reader = XmlReader.Create (fs, settings)) { doc.Load (reader); diff --git a/tests/common/ProductTests.cs b/tests/common/ProductTests.cs index cd00328e78d4..ec1d1bc53569 100644 --- a/tests/common/ProductTests.cs +++ b/tests/common/ProductTests.cs @@ -18,7 +18,7 @@ public void MonoVersion () // Verify that the mono version is in the Versions.plist, and that it's a parsable version number. var settings = new XmlReaderSettings () { XmlResolver = null, - DtdProcessing = DtdProcessing.Parse + DtdProcessing = DtdProcessing.Ignore }; var plist = Path.Combine (Configuration.SdkRoot, "Versions.plist"); diff --git a/tests/common/TestRuntime.cs b/tests/common/TestRuntime.cs index cfa84a3fb329..60e6e37d5c6a 100644 --- a/tests/common/TestRuntime.cs +++ b/tests/common/TestRuntime.cs @@ -1664,6 +1664,11 @@ public static void IgnoreInCIIfTimedOut (Exception ex) IgnoreInCI ($"Ignored due to network error: {wex}"); } } + + var se = FindInner (ex); + if (se is not null && se.SocketErrorCode == System.Net.Sockets.SocketError.TimedOut) { + IgnoreInCI ($"Ignored due to socket timeout: {se.Message}"); + } } public static void IgnoreInCIIfForbidden (Exception ex) diff --git a/tests/common/test-variations.csproj b/tests/common/test-variations.csproj index 633c8fc2cb79..d5d820a99fad 100644 --- a/tests/common/test-variations.csproj +++ b/tests/common/test-variations.csproj @@ -23,6 +23,8 @@ + + @@ -147,6 +149,25 @@ <_TestVariationApplied>true + + compatibility + <_TestVariationApplied>true + + + + strict + <_TestVariationApplied>true + + $(DefineConstants);STATIC_NATIVE_SYMBOL_LOOKUP + + + + + + + + + <_InvalidTestVariations Include="$(TestVariation.Split('|'))" Exclude="@(TestVariations)" /> diff --git a/tests/dotnet/BundleStructure/shared.csproj b/tests/dotnet/BundleStructure/shared.csproj index 2f8ad66ed705..e94d15aacf61 100644 --- a/tests/dotnet/BundleStructure/shared.csproj +++ b/tests/dotnet/BundleStructure/shared.csproj @@ -162,7 +162,7 @@ - + @@ -177,7 +177,7 @@ - + diff --git a/tests/dotnet/CentralPackageVersionsApp/AppDelegate.cs b/tests/dotnet/CentralPackageVersionsApp/AppDelegate.cs deleted file mode 100644 index db627351190b..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/AppDelegate.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -using Foundation; - -namespace MySimpleApp { - public class Program { - static int Main (string [] args) - { - GC.KeepAlive (typeof (NSObject)); // prevent linking away the platform assembly - - Console.WriteLine (Environment.GetEnvironmentVariable ("MAGIC_WORD")); - - return args.Length; - } - } -} diff --git a/tests/dotnet/CentralPackageVersionsApp/MacCatalyst/CentralPackageVersionsApp.csproj b/tests/dotnet/CentralPackageVersionsApp/MacCatalyst/CentralPackageVersionsApp.csproj deleted file mode 100644 index 9146ec230693..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/MacCatalyst/CentralPackageVersionsApp.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - - net$(BundledNETCoreAppTargetFrameworkVersion)-maccatalyst - - - diff --git a/tests/dotnet/CentralPackageVersionsApp/MacCatalyst/Makefile b/tests/dotnet/CentralPackageVersionsApp/MacCatalyst/Makefile deleted file mode 100644 index 110d078f4577..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/MacCatalyst/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../shared.mk diff --git a/tests/dotnet/CentralPackageVersionsApp/Makefile b/tests/dotnet/CentralPackageVersionsApp/Makefile deleted file mode 100644 index 6affa45ff122..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -TOP=../../.. -include $(TOP)/tests/common/shared-dotnet-test.mk diff --git a/tests/dotnet/CentralPackageVersionsApp/Packages.props b/tests/dotnet/CentralPackageVersionsApp/Packages.props deleted file mode 100644 index 8423b42e36a1..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/Packages.props +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/tests/dotnet/CentralPackageVersionsApp/README.md b/tests/dotnet/CentralPackageVersionsApp/README.md deleted file mode 100644 index 0f3d32a3be18..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/README.md +++ /dev/null @@ -1 +0,0 @@ -This test can be removed in .NET 7. diff --git a/tests/dotnet/CentralPackageVersionsApp/iOS/CentralPackageVersionsApp.csproj b/tests/dotnet/CentralPackageVersionsApp/iOS/CentralPackageVersionsApp.csproj deleted file mode 100644 index 1ce755af9e0a..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/iOS/CentralPackageVersionsApp.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - - net$(BundledNETCoreAppTargetFrameworkVersion)-ios - - - diff --git a/tests/dotnet/CentralPackageVersionsApp/iOS/Makefile b/tests/dotnet/CentralPackageVersionsApp/iOS/Makefile deleted file mode 100644 index 110d078f4577..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/iOS/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../shared.mk diff --git a/tests/dotnet/CentralPackageVersionsApp/macOS/CentralPackageVersionsApp.csproj b/tests/dotnet/CentralPackageVersionsApp/macOS/CentralPackageVersionsApp.csproj deleted file mode 100644 index 391feb6d1b70..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/macOS/CentralPackageVersionsApp.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - - net$(BundledNETCoreAppTargetFrameworkVersion)-macos - - - diff --git a/tests/dotnet/CentralPackageVersionsApp/macOS/Makefile b/tests/dotnet/CentralPackageVersionsApp/macOS/Makefile deleted file mode 100644 index 110d078f4577..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/macOS/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../shared.mk diff --git a/tests/dotnet/CentralPackageVersionsApp/shared.csproj b/tests/dotnet/CentralPackageVersionsApp/shared.csproj deleted file mode 100644 index 4ec57f3f7a0e..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/shared.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - Exe - - com.xamarin.centralpackageversionsapp - true - true - - - - - - - - - - $(MSBuildThisFileDirectory)Packages.props - - - - - - diff --git a/tests/dotnet/CentralPackageVersionsApp/shared.mk b/tests/dotnet/CentralPackageVersionsApp/shared.mk deleted file mode 100644 index f555cad4e805..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/shared.mk +++ /dev/null @@ -1,2 +0,0 @@ -TOP=../../../.. -include $(TOP)/tests/common/shared-dotnet.mk diff --git a/tests/dotnet/CentralPackageVersionsApp/tvOS/CentralPackageVersionsApp.csproj b/tests/dotnet/CentralPackageVersionsApp/tvOS/CentralPackageVersionsApp.csproj deleted file mode 100644 index a441004a08a5..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/tvOS/CentralPackageVersionsApp.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - - net$(BundledNETCoreAppTargetFrameworkVersion)-tvos - - - diff --git a/tests/dotnet/CentralPackageVersionsApp/tvOS/Makefile b/tests/dotnet/CentralPackageVersionsApp/tvOS/Makefile deleted file mode 100644 index 110d078f4577..000000000000 --- a/tests/dotnet/CentralPackageVersionsApp/tvOS/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../shared.mk diff --git a/tests/dotnet/CustomizedCodeSigning/shared.csproj b/tests/dotnet/CustomizedCodeSigning/shared.csproj index 5e0d08bca288..f2cbc49178e2 100644 --- a/tests/dotnet/CustomizedCodeSigning/shared.csproj +++ b/tests/dotnet/CustomizedCodeSigning/shared.csproj @@ -18,12 +18,12 @@ $(CreateAppBundleDependsOn);CopyCustomFiles; - + Contents/SharedSupport Contents/MacOS Contents/MonoBundle - + SharedSupport diff --git a/tests/dotnet/UnitTests/ProjectTest.cs b/tests/dotnet/UnitTests/ProjectTest.cs index e08fd11270f2..da56767df6df 100644 --- a/tests/dotnet/UnitTests/ProjectTest.cs +++ b/tests/dotnet/UnitTests/ProjectTest.cs @@ -2015,22 +2015,6 @@ public void AppWithGenericLibraryReference (ApplePlatform platform, string runti ExecuteWithMagicWordAndAssert (platform, runtimeIdentifiers, appExecutable); } - // This test can be removed in .NET 7 - [TestCase (ApplePlatform.iOS)] - [TestCase (ApplePlatform.TVOS)] - [TestCase (ApplePlatform.MacCatalyst)] - [TestCase (ApplePlatform.MacOSX)] - public void CentralPackageVersionsApp (ApplePlatform platform) - { - var project = "CentralPackageVersionsApp"; - Configuration.IgnoreIfIgnoredPlatform (platform); - - var project_path = GetProjectPath (project, platform: platform); - Clean (project_path); - var properties = GetDefaultProperties (); - DotNet.AssertBuild (project_path, properties); - } - [TestCase (ApplePlatform.MacCatalyst, "maccatalyst-x64", false)] [TestCase (ApplePlatform.iOS, "iossimulator-x64", true)] [TestCase (ApplePlatform.TVOS, "tvossimulator-x64", true)] diff --git a/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-Interpreter-size.txt b/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-Interpreter-size.txt index 23f787ee0be2..a205b89b64b1 100644 --- a/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-Interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-Interpreter-size.txt @@ -1,7 +1,7 @@ -AppBundleSize: 10,488,541 bytes (10,242.7 KB = 10.0 MB) +AppBundleSize: 10,488,019 bytes (10,242.2 KB = 10.0 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 4,951 bytes (4.8 KB = 0.0 MB) -Contents/Info.plist: 1,109 bytes (1.1 KB = 0.0 MB) +Contents/Info.plist: 1,099 bytes (1.1 KB = 0.0 MB) Contents/MacOS/SizeTestApp: 242,192 bytes (236.5 KB = 0.2 MB) Contents/MonoBundle/libcoreclr.dylib: 6,385,360 bytes (6,235.7 KB = 6.1 MB) Contents/MonoBundle/libSystem.Globalization.Native.dylib: 110,432 bytes (107.8 KB = 0.1 MB) @@ -9,7 +9,7 @@ Contents/MonoBundle/libSystem.IO.Compression.Native.dylib: 1,442,336 bytes (1,40 Contents/MonoBundle/libSystem.Native.dylib: 147,744 bytes (144.3 KB = 0.1 MB) Contents/MonoBundle/libSystem.Net.Security.Native.dylib: 71,232 bytes (69.6 KB = 0.1 MB) Contents/MonoBundle/libSystem.Security.Cryptography.Native.Apple.dylib: 229,280 bytes (223.9 KB = 0.2 MB) -Contents/MonoBundle/Microsoft.MacCatalyst.dll: 102,912 bytes (100.5 KB = 0.1 MB) +Contents/MonoBundle/Microsoft.MacCatalyst.dll: 102,400 bytes (100.0 KB = 0.1 MB) Contents/MonoBundle/runtimeconfig.bin: 1,481 bytes (1.4 KB = 0.0 MB) Contents/MonoBundle/SizeTestApp.dll: 7,680 bytes (7.5 KB = 0.0 MB) Contents/MonoBundle/System.Collections.Immutable.dll: 14,848 bytes (14.5 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-R2R-size.txt b/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-R2R-size.txt index cded1e19077c..e2758a18b7a0 100644 --- a/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-R2R-size.txt +++ b/tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-R2R-size.txt @@ -1,7 +1,7 @@ -AppBundleSize: 19,349,879 bytes (18,896.4 KB = 18.5 MB) +AppBundleSize: 19,349,869 bytes (18,896.4 KB = 18.5 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 5,105 bytes (5.0 KB = 0.0 MB) -Contents/Info.plist: 1,109 bytes (1.1 KB = 0.0 MB) +Contents/Info.plist: 1,099 bytes (1.1 KB = 0.0 MB) Contents/MacOS/SizeTestApp: 242,832 bytes (237.1 KB = 0.2 MB) Contents/MonoBundle/libcoreclr.dylib: 6,385,360 bytes (6,235.7 KB = 6.1 MB) Contents/MonoBundle/libSystem.Globalization.Native.dylib: 110,432 bytes (107.8 KB = 0.1 MB) diff --git a/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-interpreter-size.txt b/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-interpreter-size.txt index 4d5a57fa16eb..d9a542b82e47 100644 --- a/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-interpreter-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 5,812,128 bytes (5,675.9 KB = 5.5 MB) +AppBundleSize: 5,813,094 bytes (5,676.8 KB = 5.5 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 3,310 bytes (3.2 KB = 0.0 MB) -Contents/Info.plist: 1,109 bytes (1.1 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 4,568,336 bytes (4,461.3 KB = 4.4 MB) +Contents/Info.plist: 1,099 bytes (1.1 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 4,569,312 bytes (4,462.2 KB = 4.4 MB) Contents/MonoBundle/Microsoft.MacCatalyst.dll: 158,208 bytes (154.5 KB = 0.2 MB) Contents/MonoBundle/runtimeconfig.bin: 1,405 bytes (1.4 KB = 0.0 MB) Contents/MonoBundle/SizeTestApp.dll: 7,680 bytes (7.5 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-size.txt b/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-size.txt index 15098a4946e4..4e9a3b1a4c1f 100644 --- a/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-size.txt +++ b/tests/dotnet/UnitTests/expected/MacCatalyst-MonoVM-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 16,623,268 bytes (16,233.7 KB = 15.9 MB) +AppBundleSize: 16,624,250 bytes (16,234.6 KB = 15.9 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 4,134 bytes (4.0 KB = 0.0 MB) -Contents/Info.plist: 1,109 bytes (1.1 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 14,064,976 bytes (13,735.3 KB = 13.4 MB) +Contents/Info.plist: 1,099 bytes (1.1 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 14,065,968 bytes (13,736.3 KB = 13.4 MB) Contents/MonoBundle/aot-instances.aotdata.arm64: 1,051,776 bytes (1,027.1 KB = 1.0 MB) Contents/MonoBundle/Microsoft.MacCatalyst.aotdata.arm64: 36,048 bytes (35.2 KB = 0.0 MB) Contents/MonoBundle/Microsoft.MacCatalyst.dll: 51,200 bytes (50.0 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt b/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt index 2a9d9201144f..8662c46aa57a 100644 --- a/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt +++ b/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt @@ -1,7 +1,7 @@ -AppBundleSize: 8,742,763 bytes (8,537.9 KB = 8.3 MB) +AppBundleSize: 8,785,825 bytes (8,579.9 KB = 8.4 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 2,358 bytes (2.3 KB = 0.0 MB) -Contents/Info.plist: 1,109 bytes (1.1 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 8,737,392 bytes (8,532.6 KB = 8.3 MB) +Contents/Info.plist: 1,099 bytes (1.1 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 8,780,464 bytes (8,574.7 KB = 8.4 MB) Contents/MonoBundle/runtimeconfig.bin: 1,896 bytes (1.9 KB = 0.0 MB) Contents/PkgInfo: 8 bytes (0.0 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-size.txt b/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-size.txt index 78e5775546df..37d60c2430fc 100644 --- a/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-size.txt +++ b/tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-size.txt @@ -1,7 +1,7 @@ -AppBundleSize: 2,814,787 bytes (2,748.8 KB = 2.7 MB) +AppBundleSize: 2,815,305 bytes (2,749.3 KB = 2.7 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 2,358 bytes (2.3 KB = 0.0 MB) -Contents/Info.plist: 1,109 bytes (1.1 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 2,809,504 bytes (2,743.7 KB = 2.7 MB) +Contents/Info.plist: 1,099 bytes (1.1 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 2,810,032 bytes (2,744.2 KB = 2.7 MB) Contents/MonoBundle/runtimeconfig.bin: 1,808 bytes (1.8 KB = 0.0 MB) Contents/PkgInfo: 8 bytes (0.0 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-TrimmableStatic-size.txt b/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-TrimmableStatic-size.txt index 4619a4319666..c174fce60d96 100644 --- a/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-TrimmableStatic-size.txt +++ b/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-TrimmableStatic-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 259,125,810 bytes (253,052.5 KB = 247.1 MB) +AppBundleSize: 259,128,856 bytes (253,055.5 KB = 247.1 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 56,016 bytes (54.7 KB = 0.1 MB) -Contents/Info.plist: 740 bytes (0.7 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 7,390,464 bytes (7,217.2 KB = 7.0 MB) +Contents/Info.plist: 730 bytes (0.7 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 7,390,448 bytes (7,217.2 KB = 7.0 MB) Contents/MonoBundle/.xamarin/osx-arm64/_Microsoft.macOS.TypeMap.dll: 4,842,496 bytes (4,729.0 KB = 4.6 MB) Contents/MonoBundle/.xamarin/osx-arm64/_Microsoft.macOS.TypeMaps.dll: 2,048 bytes (2.0 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-arm64/_SizeTestApp.TypeMap.dll: 3,072 bytes (3.0 KB = 0.0 MB) @@ -16,7 +16,7 @@ Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Hosting.Abstractions Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Logging.Abstractions.dll: 150,528 bytes (147.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Options.dll: 135,168 bytes (132.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Primitives.dll: 70,144 bytes (68.5 KB = 0.1 MB) -Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.macOS.dll: 38,109,696 bytes (37,216.5 KB = 36.3 MB) +Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.macOS.dll: 38,111,232 bytes (37,218.0 KB = 36.3 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.VisualBasic.Core.dll: 1,321,472 bytes (1,290.5 KB = 1.3 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Win32.Registry.dll: 23,552 bytes (23.0 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-arm64/SizeTestApp.dll: 5,632 bytes (5.5 KB = 0.0 MB) @@ -122,7 +122,7 @@ Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Hosting.Abstractions.d Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Logging.Abstractions.dll: 134,656 bytes (131.5 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Options.dll: 119,808 bytes (117.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Primitives.dll: 63,488 bytes (62.0 KB = 0.1 MB) -Contents/MonoBundle/.xamarin/osx-x64/Microsoft.macOS.dll: 38,109,696 bytes (37,216.5 KB = 36.3 MB) +Contents/MonoBundle/.xamarin/osx-x64/Microsoft.macOS.dll: 38,111,232 bytes (37,218.0 KB = 36.3 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.VisualBasic.Core.dll: 1,152,000 bytes (1,125.0 KB = 1.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Win32.Registry.dll: 23,040 bytes (22.5 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-x64/SizeTestApp.dll: 5,632 bytes (5.5 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-size.txt b/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-size.txt index bf1d47105a57..16289972b741 100644 --- a/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 247,263,508 bytes (241,468.3 KB = 235.8 MB) +AppBundleSize: 247,265,530 bytes (241,470.2 KB = 235.8 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 54,948 bytes (53.7 KB = 0.1 MB) -Contents/Info.plist: 740 bytes (0.7 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 8,013,920 bytes (7,826.1 KB = 7.6 MB) +Contents/Info.plist: 730 bytes (0.7 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 8,013,904 bytes (7,826.1 KB = 7.6 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.CSharp.dll: 882,176 bytes (861.5 KB = 0.8 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Caching.Abstractions.dll: 56,320 bytes (55.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Configuration.Abstractions.dll: 28,160 bytes (27.5 KB = 0.0 MB) @@ -13,7 +13,7 @@ Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Hosting.Abstractions Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Logging.Abstractions.dll: 150,528 bytes (147.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Options.dll: 135,168 bytes (132.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Primitives.dll: 70,144 bytes (68.5 KB = 0.1 MB) -Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.macOS.dll: 36,713,984 bytes (35,853.5 KB = 35.0 MB) +Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.macOS.dll: 36,715,008 bytes (35,854.5 KB = 35.0 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.VisualBasic.Core.dll: 1,321,472 bytes (1,290.5 KB = 1.3 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Win32.Registry.dll: 23,552 bytes (23.0 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-arm64/SizeTestApp.dll: 6,656 bytes (6.5 KB = 0.0 MB) @@ -116,7 +116,7 @@ Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Hosting.Abstractions.d Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Logging.Abstractions.dll: 134,656 bytes (131.5 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Options.dll: 119,808 bytes (117.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Primitives.dll: 63,488 bytes (62.0 KB = 0.1 MB) -Contents/MonoBundle/.xamarin/osx-x64/Microsoft.macOS.dll: 36,713,984 bytes (35,853.5 KB = 35.0 MB) +Contents/MonoBundle/.xamarin/osx-x64/Microsoft.macOS.dll: 36,715,008 bytes (35,854.5 KB = 35.0 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.VisualBasic.Core.dll: 1,152,000 bytes (1,125.0 KB = 1.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Win32.Registry.dll: 23,040 bytes (22.5 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-x64/SizeTestApp.dll: 6,656 bytes (6.5 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-R2R-size.txt b/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-R2R-size.txt index b43dfd8cf744..6df499b345f0 100644 --- a/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-R2R-size.txt +++ b/tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-R2R-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 312,394,516 bytes (305,072.8 KB = 297.9 MB) +AppBundleSize: 312,397,562 bytes (305,075.7 KB = 297.9 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 54,948 bytes (53.7 KB = 0.1 MB) -Contents/Info.plist: 740 bytes (0.7 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 8,013,920 bytes (7,826.1 KB = 7.6 MB) +Contents/Info.plist: 730 bytes (0.7 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 8,013,904 bytes (7,826.1 KB = 7.6 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.CSharp.dll: 882,176 bytes (861.5 KB = 0.8 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Caching.Abstractions.dll: 56,320 bytes (55.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Configuration.Abstractions.dll: 28,160 bytes (27.5 KB = 0.0 MB) @@ -13,7 +13,7 @@ Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Hosting.Abstractions Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Logging.Abstractions.dll: 150,528 bytes (147.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Options.dll: 135,168 bytes (132.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Extensions.Primitives.dll: 70,144 bytes (68.5 KB = 0.1 MB) -Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.macOS.dll: 75,028,480 bytes (73,270.0 KB = 71.6 MB) +Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.macOS.dll: 75,030,016 bytes (73,271.5 KB = 71.6 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.VisualBasic.Core.dll: 1,321,472 bytes (1,290.5 KB = 1.3 MB) Contents/MonoBundle/.xamarin/osx-arm64/Microsoft.Win32.Registry.dll: 23,552 bytes (23.0 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-arm64/SizeTestApp.dll: 10,240 bytes (10.0 KB = 0.0 MB) @@ -116,7 +116,7 @@ Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Hosting.Abstractions.d Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Logging.Abstractions.dll: 134,656 bytes (131.5 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Options.dll: 119,808 bytes (117.0 KB = 0.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Extensions.Primitives.dll: 63,488 bytes (62.0 KB = 0.1 MB) -Contents/MonoBundle/.xamarin/osx-x64/Microsoft.macOS.dll: 63,523,840 bytes (62,035.0 KB = 60.6 MB) +Contents/MonoBundle/.xamarin/osx-x64/Microsoft.macOS.dll: 63,525,376 bytes (62,036.5 KB = 60.6 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.VisualBasic.Core.dll: 1,152,000 bytes (1,125.0 KB = 1.1 MB) Contents/MonoBundle/.xamarin/osx-x64/Microsoft.Win32.Registry.dll: 23,040 bytes (22.5 KB = 0.0 MB) Contents/MonoBundle/.xamarin/osx-x64/SizeTestApp.dll: 9,728 bytes (9.5 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt b/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt index cbc2498fb2f0..4e3fd8802443 100644 --- a/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt +++ b/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 18,618,633 bytes (18,182.3 KB = 17.8 MB) +AppBundleSize: 18,656,415 bytes (18,219.2 KB = 17.8 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 2,644 bytes (2.6 KB = 0.0 MB) -Contents/Info.plist: 740 bytes (0.7 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 18,613,152 bytes (18,176.9 KB = 17.8 MB) +Contents/Info.plist: 730 bytes (0.7 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 18,650,944 bytes (18,213.8 KB = 17.8 MB) Contents/MonoBundle/runtimeconfig.bin: 1,848 bytes (1.8 KB = 0.0 MB) Contents/PkgInfo: 8 bytes (0.0 KB = 0.0 MB) Contents/Resources/archived-expanded-entitlements.xcent: 241 bytes (0.2 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-size.txt b/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-size.txt index 529fa478697d..e32e4ff2fc63 100644 --- a/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-size.txt +++ b/tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 6,087,335 bytes (5,944.7 KB = 5.8 MB) +AppBundleSize: 6,087,789 bytes (5,945.1 KB = 5.8 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: Contents/_CodeSignature/CodeResources: 2,644 bytes (2.6 KB = 0.0 MB) -Contents/Info.plist: 740 bytes (0.7 KB = 0.0 MB) -Contents/MacOS/SizeTestApp: 6,081,936 bytes (5,939.4 KB = 5.8 MB) +Contents/Info.plist: 730 bytes (0.7 KB = 0.0 MB) +Contents/MacOS/SizeTestApp: 6,082,400 bytes (5,939.8 KB = 5.8 MB) Contents/MonoBundle/runtimeconfig.bin: 1,766 bytes (1.7 KB = 0.0 MB) Contents/PkgInfo: 8 bytes (0.0 KB = 0.0 MB) Contents/Resources/archived-expanded-entitlements.xcent: 241 bytes (0.2 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-Interpreter-size.txt b/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-Interpreter-size.txt index 6142376c910d..065b5a6752ab 100644 --- a/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-Interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-Interpreter-size.txt @@ -1,23 +1,23 @@ -AppBundleSize: 9,190,182 bytes (8,974.8 KB = 8.8 MB) +AppBundleSize: 9,190,122 bytes (8,974.7 KB = 8.8 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 9,851 bytes (9.6 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) Frameworks/libcoreclr.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libcoreclr.framework/Info.plist: 799 bytes (0.8 KB = 0.0 MB) +Frameworks/libcoreclr.framework/Info.plist: 789 bytes (0.8 KB = 0.0 MB) Frameworks/libcoreclr.framework/libcoreclr: 5,199,600 bytes (5,077.7 KB = 5.0 MB) Frameworks/libSystem.Globalization.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Globalization.Native.framework/Info.plist: 841 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Globalization.Native.framework/Info.plist: 831 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Globalization.Native.framework/libSystem.Globalization.Native: 109,776 bytes (107.2 KB = 0.1 MB) Frameworks/libSystem.IO.Compression.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 843 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 833 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.IO.Compression.Native.framework/libSystem.IO.Compression.Native: 1,439,664 bytes (1,405.9 KB = 1.4 MB) Frameworks/libSystem.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Native.framework/Info.plist: 813 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Native.framework/Info.plist: 803 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Native.framework/libSystem.Native: 162,544 bytes (158.7 KB = 0.2 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 869 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 859 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/libSystem.Security.Cryptography.Native.Apple: 215,440 bytes (210.4 KB = 0.2 MB) -Info.plist: 1,127 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,117 bytes (1.1 KB = 0.0 MB) Microsoft.tvOS.dll: 99,840 bytes (97.5 KB = 0.1 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,481 bytes (1.4 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-R2R-size.txt b/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-R2R-size.txt index 0eeab6b73af9..498e1e028be4 100644 --- a/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-R2R-size.txt +++ b/tests/dotnet/UnitTests/expected/TVOS-CoreCLR-R2R-size.txt @@ -1,27 +1,27 @@ -AppBundleSize: 12,634,093 bytes (12,338.0 KB = 12.0 MB) +AppBundleSize: 12,633,511 bytes (12,337.4 KB = 12.0 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 10,737 bytes (10.5 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) Frameworks/libcoreclr.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libcoreclr.framework/Info.plist: 799 bytes (0.8 KB = 0.0 MB) +Frameworks/libcoreclr.framework/Info.plist: 789 bytes (0.8 KB = 0.0 MB) Frameworks/libcoreclr.framework/libcoreclr: 5,199,600 bytes (5,077.7 KB = 5.0 MB) Frameworks/libSystem.Globalization.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Globalization.Native.framework/Info.plist: 841 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Globalization.Native.framework/Info.plist: 831 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Globalization.Native.framework/libSystem.Globalization.Native: 109,776 bytes (107.2 KB = 0.1 MB) Frameworks/libSystem.IO.Compression.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 843 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 833 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.IO.Compression.Native.framework/libSystem.IO.Compression.Native: 1,439,664 bytes (1,405.9 KB = 1.4 MB) Frameworks/libSystem.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Native.framework/Info.plist: 813 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Native.framework/Info.plist: 803 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Native.framework/libSystem.Native: 162,544 bytes (158.7 KB = 0.2 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 869 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 859 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/libSystem.Security.Cryptography.Native.Apple: 215,440 bytes (210.4 KB = 0.2 MB) Frameworks/SizeTestApp.r2r.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/SizeTestApp.r2r.framework/Info.plist: 811 bytes (0.8 KB = 0.0 MB) +Frameworks/SizeTestApp.r2r.framework/Info.plist: 801 bytes (0.8 KB = 0.0 MB) Frameworks/SizeTestApp.r2r.framework/SizeTestApp.r2r: 3,441,312 bytes (3,360.7 KB = 3.3 MB) -Info.plist: 1,127 bytes (1.1 KB = 0.0 MB) -Microsoft.tvOS.dll: 99,328 bytes (97.0 KB = 0.1 MB) +Info.plist: 1,117 bytes (1.1 KB = 0.0 MB) +Microsoft.tvOS.dll: 98,816 bytes (96.5 KB = 0.1 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,481 bytes (1.4 KB = 0.0 MB) SizeTestApp: 197,152 bytes (192.5 KB = 0.2 MB) diff --git a/tests/dotnet/UnitTests/expected/TVOS-MonoVM-interpreter-size.txt b/tests/dotnet/UnitTests/expected/TVOS-MonoVM-interpreter-size.txt index efd41fdb7c87..ce0b35a3d9fb 100644 --- a/tests/dotnet/UnitTests/expected/TVOS-MonoVM-interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/TVOS-MonoVM-interpreter-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 3,635,819 bytes (3,550.6 KB = 3.5 MB) +AppBundleSize: 3,635,809 bytes (3,550.6 KB = 3.5 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 3,999 bytes (3.9 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,127 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,117 bytes (1.1 KB = 0.0 MB) Microsoft.tvOS.dll: 155,136 bytes (151.5 KB = 0.1 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,405 bytes (1.4 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/TVOS-MonoVM-size.txt b/tests/dotnet/UnitTests/expected/TVOS-MonoVM-size.txt index ef8ee58f1da4..56c9b7ff9628 100644 --- a/tests/dotnet/UnitTests/expected/TVOS-MonoVM-size.txt +++ b/tests/dotnet/UnitTests/expected/TVOS-MonoVM-size.txt @@ -1,9 +1,9 @@ -AppBundleSize: 9,563,313 bytes (9,339.2 KB = 9.1 MB) +AppBundleSize: 9,563,303 bytes (9,339.2 KB = 9.1 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 5,233 bytes (5.1 KB = 0.0 MB) aot-instances.aotdata.arm64: 829,256 bytes (809.8 KB = 0.8 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,127 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,117 bytes (1.1 KB = 0.0 MB) Microsoft.tvOS.aotdata.arm64: 22,640 bytes (22.1 KB = 0.0 MB) Microsoft.tvOS.dll: 49,152 bytes (48.0 KB = 0.0 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-TrimmableStatic-size.txt b/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-TrimmableStatic-size.txt index 4a0ea5e9d3e6..ba1cf3697143 100644 --- a/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-TrimmableStatic-size.txt +++ b/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-TrimmableStatic-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 7,921,341 bytes (7,735.7 KB = 7.6 MB) +AppBundleSize: 7,925,555 bytes (7,739.8 KB = 7.6 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 2,589 bytes (2.5 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,127 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,117 bytes (1.1 KB = 0.0 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,889 bytes (1.8 KB = 0.0 MB) -SizeTestApp: 7,915,344 bytes (7,729.8 KB = 7.5 MB) +SizeTestApp: 7,919,568 bytes (7,734.0 KB = 7.6 MB) diff --git a/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-size.txt b/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-size.txt index 5eded64d813f..ffdab3ff63f2 100644 --- a/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-size.txt +++ b/tests/dotnet/UnitTests/expected/TVOS-NativeAOT-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 2,848,956 bytes (2,782.2 KB = 2.7 MB) +AppBundleSize: 2,849,458 bytes (2,782.7 KB = 2.7 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 2,589 bytes (2.5 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,127 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,117 bytes (1.1 KB = 0.0 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,808 bytes (1.8 KB = 0.0 MB) -SizeTestApp: 2,843,040 bytes (2,776.4 KB = 2.7 MB) +SizeTestApp: 2,843,552 bytes (2,776.9 KB = 2.7 MB) diff --git a/tests/dotnet/UnitTests/expected/iOS-CoreCLR-Interpreter-size.txt b/tests/dotnet/UnitTests/expected/iOS-CoreCLR-Interpreter-size.txt index fd7f717d8d0b..cccd431bc585 100644 --- a/tests/dotnet/UnitTests/expected/iOS-CoreCLR-Interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/iOS-CoreCLR-Interpreter-size.txt @@ -1,26 +1,26 @@ -AppBundleSize: 9,258,431 bytes (9,041.4 KB = 8.8 MB) +AppBundleSize: 9,258,361 bytes (9,041.4 KB = 8.8 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 10,847 bytes (10.6 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) Frameworks/libcoreclr.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libcoreclr.framework/Info.plist: 823 bytes (0.8 KB = 0.0 MB) +Frameworks/libcoreclr.framework/Info.plist: 813 bytes (0.8 KB = 0.0 MB) Frameworks/libcoreclr.framework/libcoreclr: 5,187,184 bytes (5,065.6 KB = 4.9 MB) Frameworks/libSystem.Globalization.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Globalization.Native.framework/Info.plist: 865 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Globalization.Native.framework/Info.plist: 855 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Globalization.Native.framework/libSystem.Globalization.Native: 109,232 bytes (106.7 KB = 0.1 MB) Frameworks/libSystem.IO.Compression.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 867 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 857 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.IO.Compression.Native.framework/libSystem.IO.Compression.Native: 1,431,408 bytes (1,397.9 KB = 1.4 MB) Frameworks/libSystem.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Native.framework/Info.plist: 837 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Native.framework/Info.plist: 827 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Native.framework/libSystem.Native: 162,336 bytes (158.5 KB = 0.2 MB) Frameworks/libSystem.Net.Security.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Net.Security.Native.framework/Info.plist: 863 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Net.Security.Native.framework/Info.plist: 853 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Net.Security.Native.framework/libSystem.Net.Security.Native: 88,000 bytes (85.9 KB = 0.1 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 893 bytes (0.9 KB = 0.0 MB) +Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 883 bytes (0.9 KB = 0.0 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/libSystem.Security.Cryptography.Native.Apple: 214,336 bytes (209.3 KB = 0.2 MB) -Info.plist: 1,151 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,141 bytes (1.1 KB = 0.0 MB) Microsoft.iOS.dll: 99,840 bytes (97.5 KB = 0.1 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,481 bytes (1.4 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/iOS-CoreCLR-R2R-size.txt b/tests/dotnet/UnitTests/expected/iOS-CoreCLR-R2R-size.txt index 3f2856be1254..81d682ae01d1 100644 --- a/tests/dotnet/UnitTests/expected/iOS-CoreCLR-R2R-size.txt +++ b/tests/dotnet/UnitTests/expected/iOS-CoreCLR-R2R-size.txt @@ -1,30 +1,30 @@ -AppBundleSize: 12,682,430 bytes (12,385.2 KB = 12.1 MB) +AppBundleSize: 12,681,838 bytes (12,384.6 KB = 12.1 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 11,733 bytes (11.5 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) Frameworks/libcoreclr.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libcoreclr.framework/Info.plist: 823 bytes (0.8 KB = 0.0 MB) +Frameworks/libcoreclr.framework/Info.plist: 813 bytes (0.8 KB = 0.0 MB) Frameworks/libcoreclr.framework/libcoreclr: 5,187,184 bytes (5,065.6 KB = 4.9 MB) Frameworks/libSystem.Globalization.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Globalization.Native.framework/Info.plist: 865 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Globalization.Native.framework/Info.plist: 855 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Globalization.Native.framework/libSystem.Globalization.Native: 109,232 bytes (106.7 KB = 0.1 MB) Frameworks/libSystem.IO.Compression.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 867 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.IO.Compression.Native.framework/Info.plist: 857 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.IO.Compression.Native.framework/libSystem.IO.Compression.Native: 1,431,408 bytes (1,397.9 KB = 1.4 MB) Frameworks/libSystem.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Native.framework/Info.plist: 837 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Native.framework/Info.plist: 827 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Native.framework/libSystem.Native: 162,336 bytes (158.5 KB = 0.2 MB) Frameworks/libSystem.Net.Security.Native.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Net.Security.Native.framework/Info.plist: 863 bytes (0.8 KB = 0.0 MB) +Frameworks/libSystem.Net.Security.Native.framework/Info.plist: 853 bytes (0.8 KB = 0.0 MB) Frameworks/libSystem.Net.Security.Native.framework/libSystem.Net.Security.Native: 88,000 bytes (85.9 KB = 0.1 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 893 bytes (0.9 KB = 0.0 MB) +Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/Info.plist: 883 bytes (0.9 KB = 0.0 MB) Frameworks/libSystem.Security.Cryptography.Native.Apple.framework/libSystem.Security.Cryptography.Native.Apple: 214,336 bytes (209.3 KB = 0.2 MB) Frameworks/SizeTestApp.r2r.framework/_CodeSignature/CodeResources: 1,798 bytes (1.8 KB = 0.0 MB) -Frameworks/SizeTestApp.r2r.framework/Info.plist: 835 bytes (0.8 KB = 0.0 MB) +Frameworks/SizeTestApp.r2r.framework/Info.plist: 825 bytes (0.8 KB = 0.0 MB) Frameworks/SizeTestApp.r2r.framework/SizeTestApp.r2r: 3,421,408 bytes (3,341.2 KB = 3.3 MB) -Info.plist: 1,151 bytes (1.1 KB = 0.0 MB) -Microsoft.iOS.dll: 99,328 bytes (97.0 KB = 0.1 MB) +Info.plist: 1,141 bytes (1.1 KB = 0.0 MB) +Microsoft.iOS.dll: 98,816 bytes (96.5 KB = 0.1 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,481 bytes (1.4 KB = 0.0 MB) SizeTestApp: 196,096 bytes (191.5 KB = 0.2 MB) diff --git a/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-size.txt b/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-size.txt index 5c0262391231..07fd579da858 100644 --- a/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-size.txt +++ b/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 3,622,257 bytes (3,537.4 KB = 3.5 MB) +AppBundleSize: 3,622,247 bytes (3,537.4 KB = 3.5 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 3,997 bytes (3.9 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,151 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,141 bytes (1.1 KB = 0.0 MB) Microsoft.iOS.dll: 155,136 bytes (151.5 KB = 0.1 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,405 bytes (1.4 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/iOS-MonoVM-size.txt b/tests/dotnet/UnitTests/expected/iOS-MonoVM-size.txt index e6a38fb29523..656a8acf8ab8 100644 --- a/tests/dotnet/UnitTests/expected/iOS-MonoVM-size.txt +++ b/tests/dotnet/UnitTests/expected/iOS-MonoVM-size.txt @@ -1,9 +1,9 @@ -AppBundleSize: 9,520,293 bytes (9,297.2 KB = 9.1 MB) +AppBundleSize: 9,520,283 bytes (9,297.2 KB = 9.1 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 5,229 bytes (5.1 KB = 0.0 MB) aot-instances.aotdata.arm64: 829,256 bytes (809.8 KB = 0.8 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,151 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,141 bytes (1.1 KB = 0.0 MB) Microsoft.iOS.aotdata.arm64: 22,992 bytes (22.5 KB = 0.0 MB) Microsoft.iOS.dll: 49,152 bytes (48.0 KB = 0.0 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) diff --git a/tests/dotnet/UnitTests/expected/iOS-NativeAOT-TrimmableStatic-size.txt b/tests/dotnet/UnitTests/expected/iOS-NativeAOT-TrimmableStatic-size.txt index ef5533f5430d..5a2d16496b1a 100644 --- a/tests/dotnet/UnitTests/expected/iOS-NativeAOT-TrimmableStatic-size.txt +++ b/tests/dotnet/UnitTests/expected/iOS-NativeAOT-TrimmableStatic-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 9,054,820 bytes (8,842.6 KB = 8.6 MB) +AppBundleSize: 9,081,274 bytes (8,868.4 KB = 8.7 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 2,589 bytes (2.5 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,151 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,141 bytes (1.1 KB = 0.0 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,888 bytes (1.8 KB = 0.0 MB) -SizeTestApp: 9,048,800 bytes (8,836.7 KB = 8.6 MB) +SizeTestApp: 9,075,264 bytes (8,862.6 KB = 8.7 MB) diff --git a/tests/dotnet/UnitTests/expected/iOS-NativeAOT-size.txt b/tests/dotnet/UnitTests/expected/iOS-NativeAOT-size.txt index 47626e834ae4..d75275754af2 100644 --- a/tests/dotnet/UnitTests/expected/iOS-NativeAOT-size.txt +++ b/tests/dotnet/UnitTests/expected/iOS-NativeAOT-size.txt @@ -1,8 +1,8 @@ -AppBundleSize: 2,849,300 bytes (2,782.5 KB = 2.7 MB) +AppBundleSize: 2,849,818 bytes (2,783.0 KB = 2.7 MB) # The following list of files and their sizes is just informational / for review, and isn't used in the test: _CodeSignature/CodeResources: 2,589 bytes (2.5 KB = 0.0 MB) archived-expanded-entitlements.xcent: 384 bytes (0.4 KB = 0.0 MB) -Info.plist: 1,151 bytes (1.1 KB = 0.0 MB) +Info.plist: 1,141 bytes (1.1 KB = 0.0 MB) PkgInfo: 8 bytes (0.0 KB = 0.0 MB) runtimeconfig.bin: 1,808 bytes (1.8 KB = 0.0 MB) -SizeTestApp: 2,843,360 bytes (2,776.7 KB = 2.7 MB) +SizeTestApp: 2,843,888 bytes (2,777.2 KB = 2.7 MB) diff --git a/tests/monotouch-test/CoreFoundation/ProxyTest.cs b/tests/monotouch-test/CoreFoundation/ProxyTest.cs index 99c7c214d68b..3dc46ece6d40 100644 --- a/tests/monotouch-test/CoreFoundation/ProxyTest.cs +++ b/tests/monotouch-test/CoreFoundation/ProxyTest.cs @@ -18,23 +18,6 @@ namespace MonoTouchFixtures.CoreFoundation { [TestFixture] [Preserve (AllMembers = true)] public class ProxyTest { - - [Test] - public void Fields () - { - // documented but symbols are missing - // this test will fail if Apple decide to include them in the future - IntPtr lib = Dlfcn.dlopen (Constants.CoreFoundationLibrary, 0); - try { - // http://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFProxySupport/Reference/reference.html#//apple_ref/doc/c_ref/kCFProxyAutoConfigurationHTTPResponseKey - Assert.That (Dlfcn.dlsym (lib, "kCFProxyAutoConfigurationHTTPResponseKey"), Is.EqualTo (IntPtr.Zero), "kCFProxyAutoConfigurationHTTPResponseKey"); - // http://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFProxySupport/Reference/reference.html#//apple_ref/doc/c_ref/kCFNetworkProxiesProxyAutoConfigJavaScript - Assert.That (Dlfcn.dlsym (lib, "kCFNetworkProxiesProxyAutoConfigJavaScript"), Is.EqualTo (IntPtr.Zero), "kCFNetworkProxiesProxyAutoConfigJavaScript"); - } finally { - Dlfcn.dlclose (lib); - } - } - #if !MONOMAC HttpListener listener; int port; diff --git a/tests/monotouch-test/CoreGraphics/GeometryTest.cs b/tests/monotouch-test/CoreGraphics/GeometryTest.cs index f60ced6f596c..24eb3c0520b3 100644 --- a/tests/monotouch-test/CoreGraphics/GeometryTest.cs +++ b/tests/monotouch-test/CoreGraphics/GeometryTest.cs @@ -17,9 +17,8 @@ public class GeometryTest { static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.CoreGraphicsLibrary, 0); - public static CGRect GetRect (string symbol) + public static CGRect GetRect (IntPtr indirect) { - var indirect = Dlfcn.dlsym (Handle, symbol); if (indirect == IntPtr.Zero) return CGRect.Empty; unsafe { @@ -31,7 +30,7 @@ public static CGRect GetRect (string symbol) [Test] public void Infinite () { - var r = GetRect ("CGRectInfinite"); + var r = GetRect (Dlfcn.dlsym (Handle, "CGRectInfinite")); Assert.False (r.IsEmpty, "IsEmpty"); Assert.False (r.IsNull (), "IsNull"); Assert.True (r.IsInfinite (), "IsInfinite"); @@ -40,7 +39,7 @@ public void Infinite () [Test] public void Null () { - var r = GetRect ("CGRectNull"); + var r = GetRect (Dlfcn.dlsym (Handle, "CGRectNull")); Assert.True (r.IsEmpty, "IsEmpty"); Assert.True (r.IsNull (), "IsNull"); Assert.False (r.IsInfinite (), "IsInfinite"); @@ -49,7 +48,7 @@ public void Null () [Test] public void Zero () { - var r = GetRect ("CGRectZero"); + var r = GetRect (Dlfcn.dlsym (Handle, "CGRectZero")); Assert.True (r.IsEmpty, "IsEmpty"); Assert.False (r.IsNull (), "IsNull"); Assert.False (r.IsInfinite (), "IsInfinite"); diff --git a/tests/monotouch-test/Foundation/AttributedStringTest.cs b/tests/monotouch-test/Foundation/AttributedStringTest.cs index 62ffbdbdd702..4844f9885cbb 100644 --- a/tests/monotouch-test/Foundation/AttributedStringTest.cs +++ b/tests/monotouch-test/Foundation/AttributedStringTest.cs @@ -52,28 +52,6 @@ void cb (NSDictionary attrs, NSRange range, ref bool stop) failEnum = true; } - [Test] - public void Fields () - { - // fields are not available in iOS (at least up to 5.1.1) - // this test will fail if this ever change in the future - IntPtr lib = Dlfcn.dlopen (Constants.FoundationLibrary, 0); - try { - Assert.That (Dlfcn.dlsym (lib, "NSFontAttributeName"), Is.EqualTo (IntPtr.Zero), "NSFontAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSLinkAttributeName"), Is.EqualTo (IntPtr.Zero), "NSLinkAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSUnderlineStyleAttributeName"), Is.EqualTo (IntPtr.Zero), "NSUnderlineStyleAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSStrikethroughStyleAttributeName"), Is.EqualTo (IntPtr.Zero), "NSStrikethroughStyleAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSStrokeWidthAttributeName"), Is.EqualTo (IntPtr.Zero), "NSStrokeWidthAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSParagraphStyleAttributeName"), Is.EqualTo (IntPtr.Zero), "NSParagraphStyleAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSForegroundColorAttributeName"), Is.EqualTo (IntPtr.Zero), "NSForegroundColorAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSBackgroundColorAttributeName"), Is.EqualTo (IntPtr.Zero), "NSBackgroundColorAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSLigatureAttributeName"), Is.EqualTo (IntPtr.Zero), "NSLigatureAttributeName"); - Assert.That (Dlfcn.dlsym (lib, "NSObliquenessAttributeName"), Is.EqualTo (IntPtr.Zero), "NSObliquenessAttributeName"); - } finally { - Dlfcn.dlclose (lib); - } - } - [Test] public void UIKitAttachmentConveniences_New () { diff --git a/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs b/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs index aeda262d8b76..8fa51299cbbc 100644 --- a/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs +++ b/tests/monotouch-test/ObjCRuntime/DlfcnTest.cs @@ -13,6 +13,53 @@ namespace MonoTouchFixtures.ObjCRuntime { [Preserve (AllMembers = true)] public class DlfcnTest { + // These tests exercise [Field]-backed properties from Apple frameworks. + // The generated binding code calls Dlfcn.GetStringConstant / GetIntPtr / etc. + // under the hood, which is what InlineDlfcnMethodsStep transforms. + + [Test] + public void StringConstant_NSLocaleNotification () + { + var value = NSLocale.CurrentLocaleDidChangeNotification; + Assert.IsNotNull (value, "CurrentLocaleDidChangeNotification"); + Assert.AreEqual ("kCFLocaleCurrentLocaleDidChangeNotification", (string) value, "value"); + } + + [Test] + public void StringConstant_NSBundleNotification () + { + var value = NSBundle.BundleDidLoadNotification; + Assert.IsNotNull (value, "BundleDidLoadNotification"); + Assert.AreEqual ("NSBundleDidLoadNotification", (string) value, "value"); + } + + [Test] + public void StringConstant_NSUserDefaultsNotification () + { + var value = NSUserDefaults.DidChangeNotification; + Assert.IsNotNull (value, "DidChangeNotification"); + Assert.AreEqual ("NSUserDefaultsDidChangeNotification", (string) value, "value"); + } + + [Test] + public void StringConstant_NSUndoManagerNotification () + { + var value = NSUndoManager.CheckpointNotification; + Assert.IsNotNull (value, "CheckpointNotification"); + Assert.AreEqual ("NSUndoManagerCheckpointNotification", (string) value, "value"); + } + + [Test] + public void StringConstant_CachePointer () + { + // Access several string constants multiple times to test caching behavior. + // The binding code uses Dlfcn.CachePointer for repeated accesses. + for (int i = 0; i < 3; i++) { + var value = NSLocale.CurrentLocaleDidChangeNotification; + Assert.IsNotNull (value, $"iteration {i}"); + } + } + [Test] public void OpenClose_libSystem () { @@ -32,7 +79,7 @@ public void OpenClose_libSystem () [Test] public void GetVariables () { - var symbol = "x_native_field"; + const string symbol = "x_native_field"; var handle = (IntPtr) Dlfcn.RTLD.Default; Assert.AreNotEqual (IntPtr.Zero, Dlfcn.dlsym (handle, symbol), "Symbol"); @@ -63,8 +110,10 @@ public void GetVariables () Assert.AreEqual (-3.9541907E+28f, Dlfcn.GetStruct (handle, symbol), "GetStruct"); Assert.AreEqual (-7.7576533930025207E-103d, Dlfcn.GetStruct (handle, symbol), "GetStruct"); +#if !STATIC_NATIVE_SYMBOL_LOOKUP Assert.AreEqual ((ulong) 0, Dlfcn.GetStruct (handle, "inexistent_symbol"), "GetStruct inexistent"); Assert.AreEqual ((ulong) 0, Dlfcn.GetStruct (handle, "inexistent_symbol").Value, "GetStruct inexistent"); +#endif Dlfcn.SetInt16 (handle, symbol, 0x77); Assert.AreEqual ((short) 0x77, Dlfcn.GetInt16 (handle, symbol), "SetInt16"); @@ -122,5 +171,24 @@ struct SomeValue { public ulong Value; } #pragma warning restore CS0649 + + [Test] + public void FieldProperty_CGRect () + { + Assert.Multiple (() => { + // CGRect.Null is backed by [Field("CGRectNull")] which calls Dlfcn.GetCGRect. + var value = global::CoreGraphics.CGRect.Null; + Assert.That (value.X, Is.EqualTo (nfloat.PositiveInfinity), "CGRectNull.X"); + Assert.That (value.Y, Is.EqualTo (nfloat.PositiveInfinity), "CGRectNull.Y"); + Assert.That (value.Width, Is.EqualTo ((nfloat) 0), "CGRectNull.Width"); + Assert.That (value.Height, Is.EqualTo ((nfloat) 0), "CGRectNull.Height"); + + var infinite = global::CoreGraphics.CGRect.Infinite; + Assert.That (infinite.X, Is.EqualTo (nfloat.MinValue / 2), "CGRectInfinite.X"); + Assert.That (infinite.Y, Is.EqualTo (nfloat.MinValue / 2), "CGRectInfinite.Y"); + Assert.That (infinite.Width, Is.EqualTo (nfloat.MaxValue), "CGRectInfinite.Width"); + Assert.That (infinite.Height, Is.EqualTo (nfloat.MaxValue), "CGRectInfinite.Height"); + }); + } } } diff --git a/tests/monotouch-test/ObjCRuntime/StrongEnumTests.cs b/tests/monotouch-test/ObjCRuntime/StrongEnumTests.cs index c63b3e9a5e45..65e26a101dbd 100644 --- a/tests/monotouch-test/ObjCRuntime/StrongEnumTests.cs +++ b/tests/monotouch-test/ObjCRuntime/StrongEnumTests.cs @@ -80,8 +80,8 @@ public void GetConstant () #if __TVOS__ && !XAMCORE_5_0 if (Runtime.Arch == Arch.SIMULATOR && Runtime.IsARM64CallingConvention) { - rv.AddRange (Enum.GetValues ().Select (v => (typeof (global::BrowserEngineKit.BEAccessibilityTrait), (object) (int) v))); // BrowserEngineKit isn't available in the simulator - rv.AddRange (Enum.GetValues ().Select (v => (typeof (global::BrowserEngineKit.BEAccessibilityNotification), (object) (int) v))); // BrowserEngineKit isn't available in the simulator + rv.AddRange (Enum.GetValues ().Select (v => (typeof (global::BrowserEngineKit.BEAccessibilityTrait), (object) (long) v))); // BrowserEngineKit isn't available in the simulator + rv.AddRange (Enum.GetValues ().Select (v => (typeof (global::BrowserEngineKit.BEAccessibilityNotification), (object) (long) v))); // BrowserEngineKit isn't available in the simulator } #endif // __TVOS__ && !XAMCORE_5_0 diff --git a/tests/monotouch-test/Security/SecureTransportTest.cs b/tests/monotouch-test/Security/SecureTransportTest.cs index 79b9f89467f4..d44aa17a3619 100644 --- a/tests/monotouch-test/Security/SecureTransportTest.cs +++ b/tests/monotouch-test/Security/SecureTransportTest.cs @@ -130,45 +130,55 @@ public void DatagramDefaults () [Test] public void Tls12 () { - var client = new TcpClient ("google.ca", 443); - using (NetworkStream ns = client.GetStream ()) - using (var ssl = new SslContext (SslProtocolSide.Client, SslConnectionType.Stream)) { - - ssl.MinProtocol = SslProtocol.Tls_1_2; - Assert.That (ssl.MinProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "MinProtocol"); - - ssl.Connection = new SslStreamConnection (ns); - - var result = ssl.Handshake (); - while (result == SslStatus.WouldBlock || result == (SslStatus) (-108)) { - // we need to ask again - but if we're too fast we'll get -108 (errSecAllocate) - Thread.Sleep (100); - // during the above call SessionState is Handshake - Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Handshake), "Handshake/in progress"); - result = ssl.Handshake (); - } - Assert.That (result, Is.EqualTo (SslStatus.Success), "Handshake/done"); + try { + var client = new TcpClient ("google.ca", 443); + using (NetworkStream ns = client.GetStream ()) + using (var ssl = new SslContext (SslProtocolSide.Client, SslConnectionType.Stream)) { + + ssl.MinProtocol = SslProtocol.Tls_1_2; + Assert.That (ssl.MinProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "MinProtocol"); + + ssl.Connection = new SslStreamConnection (ns); + + var deadline = DateTime.UtcNow.AddSeconds (30); + var result = ssl.Handshake (); + while (result == SslStatus.WouldBlock || result == (SslStatus) errSecAllocate) { + Assert.That (DateTime.UtcNow, Is.LessThan (deadline), "Handshake/timeout"); + // we need to ask again - but if we're too fast we'll get errSecAllocate + Thread.Sleep (100); + // during the above call SessionState is Handshake + Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Handshake), "Handshake/in progress"); + result = ssl.Handshake (); + } + Assert.That (result, Is.EqualTo (SslStatus.Success), "Handshake/done"); - // FIXME: iOS 8 beta 1 bug ?!? the state is not updated (maybe delayed?) but the code still works - //Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Connected), "Connected"); - Assert.That (ssl.NegotiatedProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "NegotiatedProtocol"); + // FIXME: iOS 8 beta 1 bug ?!? the state is not updated (maybe delayed?) but the code still works + //Assert.That (ssl.SessionState, Is.EqualTo (SslSessionState.Connected), "Connected"); + Assert.That (ssl.NegotiatedProtocol, Is.EqualTo (SslProtocol.Tls_1_2), "NegotiatedProtocol"); - nint processed; - var data = Encoding.UTF8.GetBytes ("GET / HTTP/1.0" + Environment.NewLine + Environment.NewLine); - result = ssl.Write (data, out processed); - Assert.That (processed, Is.EqualTo ((nint) data.Length), "small buffer"); - Assert.That (result, Is.EqualTo (SslStatus.Success), "Write"); + nint processed; + var data = Encoding.UTF8.GetBytes ("GET / HTTP/1.0" + Environment.NewLine + Environment.NewLine); + result = ssl.Write (data, out processed); + Assert.That (processed, Is.EqualTo ((nint) data.Length), "small buffer"); + Assert.That (result, Is.EqualTo (SslStatus.Success), "Write"); - data = new byte [1024]; - result = ssl.Read (data, out processed); - while (result == SslStatus.WouldBlock) + data = new byte [1024]; + deadline = DateTime.UtcNow.AddSeconds (30); result = ssl.Read (data, out processed); - Assert.That (result, Is.EqualTo (SslStatus.Success), "Read"); + while (result == SslStatus.WouldBlock) { + Assert.That (DateTime.UtcNow, Is.LessThan (deadline), "Read/timeout"); + result = ssl.Read (data, out processed); + } + Assert.That (result, Is.EqualTo (SslStatus.Success), "Read"); - string s = Encoding.UTF8.GetString (data, 0, (int) processed); - // The result apparently depends on where you are: I get a 302, the bots get a 200. - // Also sometimes it fails with 502 Bad Gateway on the bots - Assert.That (s, Does.StartWith ("HTTP/1.0 302 Found").Or.StartWith ("HTTP/1.0 200 OK").Or.StartWith ("HTTP/1.0 502 Bad Gateway"), "response"); + string s = Encoding.UTF8.GetString (data, 0, (int) processed); + // The result apparently depends on where you are: I get a 302, the bots get a 200. + // Also sometimes it fails with 502 Bad Gateway on the bots + Assert.That (s, Does.StartWith ("HTTP/1.0 302 Found").Or.StartWith ("HTTP/1.0 200 OK").Or.StartWith ("HTTP/1.0 502 Bad Gateway"), "response"); + } + } catch (Exception ex) { + TestRuntime.IgnoreInCIIfBadNetwork (ex); + throw; } } } diff --git a/tests/monotouch-test/System.Net.Http/NetworkResources.cs b/tests/monotouch-test/System.Net.Http/NetworkResources.cs index 99fe7fc5c24f..6fa21fe58507 100644 --- a/tests/monotouch-test/System.Net.Http/NetworkResources.cs +++ b/tests/monotouch-test/System.Net.Http/NetworkResources.cs @@ -6,6 +6,7 @@ namespace MonoTests.System.Net.Http { [Preserve (AllMembers = true)] public static class NetworkResources { + public const string AppleHost = "apple.com"; public static string MicrosoftUrl => AssertNetworkConnection ("https://www.microsoft.com"); public static Uri MicrosoftUri => new Uri (MicrosoftUrl); public static string MicrosoftHttpUrl => AssertNetworkConnection ("http://www.microsoft.com"); diff --git a/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs b/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs index e4da98fe4040..6da03dae47e2 100644 --- a/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs +++ b/tests/monotouch-test/SystemConfiguration/NetworkReachabilityTest.cs @@ -14,6 +14,8 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using System.Net.Sockets; +using MonoTests.System.Net.Http; namespace MonoTouchFixtures.SystemConfiguration { @@ -78,7 +80,23 @@ public void CtorIPAddress () [Test] public void CtorIPAddressPair () { - var address = Dns.GetHostAddresses ("apple.com") [0]; + IPAddress address; + try { + var addresses = Dns.GetHostAddresses (NetworkResources.AppleHost); + address = null; + foreach (var candidate in addresses) { + if (candidate.AddressFamily == AddressFamily.InterNetwork) { + address = candidate; + break; + } + } + if (address is null) + throw new InvalidOperationException ("No IPv4 address found."); + } catch (Exception e) { + TestRuntime.IgnoreInCIIfBadNetwork (e); + throw; + } + using (var nr = new NetworkReachability (IPAddress.Loopback, address)) { NetworkReachabilityFlags flags; @@ -90,8 +108,9 @@ public void CtorIPAddressPair () NetworkReachabilityFlags flags; Assert.IsTrue (nr.TryGetFlags (out flags), "#2"); - flags &= ~NetworkReachabilityFlags.TransientConnection; // Remove the TransientConnection flag if it's set - Assert.That (flags, Is.EqualTo (NetworkReachabilityFlags.Reachable), "#2 Reachable"); + // Different OS versions report different flags, so just + // check that Reachable is set and no unexpected flags appear. + CheckRemoteFlags (flags, "2"); } using (var nr = new NetworkReachability (IPAddress.Loopback, null)) { @@ -114,6 +133,17 @@ void CheckLoopbackFlags (NetworkReachabilityFlags flags, string number, bool has Assert.AreEqual (noFlags, otherFlags, $"#{number} No other flags: {flags.ToString ()}"); } + void CheckRemoteFlags (NetworkReachabilityFlags flags, string number) + { + var noFlags = (NetworkReachabilityFlags) 0; + var otherFlags = (flags & ~(NetworkReachabilityFlags.Reachable | NetworkReachabilityFlags.TransientConnection | NetworkReachabilityFlags.ConnectionRequired)); + + // Different versions of OSes report different flags, so just + // verify Reachable is set and no unexpected flags appear. + Assert.That (flags & NetworkReachabilityFlags.Reachable, Is.Not.EqualTo (noFlags), $"#{number} Reachable: {flags.ToString ()}"); + Assert.AreEqual (noFlags, otherFlags, $"#{number} No other flags: {flags.ToString ()}"); + } + [Test] public void Ctor_Invalid () { diff --git a/tests/monotouch-test/dotnet/shared.csproj b/tests/monotouch-test/dotnet/shared.csproj index 282d2a42e265..71e4ad497bca 100644 --- a/tests/monotouch-test/dotnet/shared.csproj +++ b/tests/monotouch-test/dotnet/shared.csproj @@ -46,16 +46,17 @@ - - + + - - - + + + + @@ -238,11 +239,11 @@ - Contents/Resources/ + Contents/Resources/ - + <_SmeltingSdk Condition="'$(_PlatformName)' == 'iOS'">iphoneos <_SmeltingSdk Condition="'$(_PlatformName)' == 'tvOS'">appletvos @@ -267,7 +268,7 @@ - $(DefineConstants);AOT + $(DefineConstants);AOT $(DefineConstants);AOT $(DefineConstants);AOT diff --git a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CompileEntitlementsTaskTests.cs b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CompileEntitlementsTaskTests.cs index 02133ee3be01..df80c4f9bfc6 100644 --- a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CompileEntitlementsTaskTests.cs +++ b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/CompileEntitlementsTaskTests.cs @@ -574,6 +574,38 @@ public void ValidateStringArrayEntitlement (string entitlement, EntitlementsMode ValidateEntitlementsImpl (platform, "error", [], mode, entitlement, "String", "InvalidValue", mobileProvision: "Apple_Signin_Test_Profile.mobileprovision"); } + // Test case inspired by https://github.com/dotnet/macios/issues/25306 + // A wallet extension requests com.apple.developer.payment-pass-provisioning, + // but the provisioning profile doesn't grant it. This should produce a + // warning/error so the developer knows why installation fails on device. + [Test] + [TestCase (EntitlementsMode.InCustomEntitlements)] + [TestCase (EntitlementsMode.InFile)] + public void ValidateEntitlements_PaymentPassProvisioningNotInProfile (EntitlementsMode mode) + { + ValidateEntitlementsImpl (ApplePlatform.iOS, "error", [ + "MT7140:The app requests the entitlement 'com.apple.developer.payment-pass-provisioning', but the provisioning profile 'iOS Team Provisioning Profile: *' doesn't contain this entitlement." + ], mode, "com.apple.developer.payment-pass-provisioning", "Boolean", "true"); + } + + [Test] + [TestCase (EntitlementsMode.InCustomEntitlements)] + [TestCase (EntitlementsMode.InFile)] + public void ValidateEntitlements_PaymentPassProvisioningNotInProfile_Warning (EntitlementsMode mode) + { + ValidateEntitlementsImpl (ApplePlatform.iOS, "warn", [ + "MT7140:The app requests the entitlement 'com.apple.developer.payment-pass-provisioning', but the provisioning profile 'iOS Team Provisioning Profile: *' doesn't contain this entitlement." + ], mode, "com.apple.developer.payment-pass-provisioning", "Boolean", "true"); + } + + [Test] + [TestCase (EntitlementsMode.InCustomEntitlements)] + [TestCase (EntitlementsMode.InFile)] + public void ValidateEntitlements_PaymentPassProvisioningNotInProfile_Disable (EntitlementsMode mode) + { + ValidateEntitlementsImpl (ApplePlatform.iOS, "disable", [], mode, "com.apple.developer.payment-pass-provisioning", "Boolean", "true"); + } + public enum EntitlementsMode { None, InFile, diff --git a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GetAvailableDevicesTest.cs b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GetAvailableDevicesTest.cs index beb8be0f356d..b8e71570aeb0 100644 --- a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GetAvailableDevicesTest.cs +++ b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GetAvailableDevicesTest.cs @@ -139,7 +139,7 @@ public void SimCtl1 () Assert.That (task.DiscardedDevices [1].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 2 mismatch."); Assert.That (task.DiscardedDevices [1].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 2 Name mismatch."); - Assert.That (task.DiscardedDevices [1].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 2 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [1].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 2 OSVersion mismatch."); Assert.That (task.DiscardedDevices [1].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 2 UDID mismatch."); Assert.That (task.DiscardedDevices [1].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 2 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [1].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 2 reason mismatch."); @@ -216,7 +216,7 @@ public void Ctl1 () Assert.That (task.DiscardedDevices [2].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 3 UDID mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 3 Name mismatch."); - Assert.That (task.DiscardedDevices [2].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 3 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [2].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 3 OSVersion mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 3 UDID mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 3 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 3 reason mismatch."); @@ -306,7 +306,7 @@ public void Ctl1_iPhone () Assert.That (task.DiscardedDevices [2].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 3 UDID mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 3 Name mismatch."); - Assert.That (task.DiscardedDevices [2].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 3 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [2].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 3 OSVersion mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 3 UDID mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 3 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 3 reason mismatch."); @@ -393,7 +393,7 @@ public void Ctl1_iPad () Assert.That (task.DiscardedDevices [4].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 5 ItemSpec mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 5 Description mismatch."); - Assert.That (task.DiscardedDevices [4].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 5 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [4].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 5 OSVersion mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 5 UDID mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 5 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 5 reason mismatch."); @@ -487,7 +487,7 @@ public void Ctl1_OSVersion () Assert.That (task.DiscardedDevices [3].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 4 UDID mismatch."); Assert.That (task.DiscardedDevices [3].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 4 Name mismatch."); - Assert.That (task.DiscardedDevices [3].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 4 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [3].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 4 OSVersion mismatch."); Assert.That (task.DiscardedDevices [3].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 4 UDID mismatch."); Assert.That (task.DiscardedDevices [3].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 4 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [3].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 4 reason mismatch."); @@ -573,7 +573,7 @@ public void Ctl1_RuntimeIdentifier () Assert.That (task.DiscardedDevices [2].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 3 UDID mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 3 Name mismatch."); - Assert.That (task.DiscardedDevices [2].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 3 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [2].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 3 OSVersion mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 3 UDID mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 3 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [2].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 3 reason mismatch."); @@ -651,7 +651,7 @@ public void Ctl1_AppleTV () Assert.That (task.DiscardedDevices [4].ItemSpec, Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 5 ItemSpec mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("Description"), Is.EqualTo ("iPhone 17 Pro"), "Discarded Device 5 Description mismatch."); - Assert.That (task.DiscardedDevices [4].GetMetadata ("OSVersion"), Is.EqualTo (""), "Discarded Device 5 OSVersion mismatch."); + Assert.That (task.DiscardedDevices [4].GetMetadata ("OSVersion"), Is.EqualTo ("26.0"), "Discarded Device 5 OSVersion mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("UDID"), Is.EqualTo ("D4D95709-144A-4CAA-8469-89566EC1C935"), "Discarded Device 5 UDID mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("RuntimeIdentifier"), Is.EqualTo (""), "Discarded Device 5 RuntimeIdentifier mismatch."); Assert.That (task.DiscardedDevices [4].GetMetadata ("DiscardedReason"), Is.EqualTo ("Device is not available: runtime profile not found using \"System\" match policy"), "Discarded Device 5 reason mismatch."); diff --git a/tests/mtouch/MTouch.cs b/tests/mtouch/MTouch.cs index 577b7e2b9ef4..fa74e96c3a1f 100644 --- a/tests/mtouch/MTouch.cs +++ b/tests/mtouch/MTouch.cs @@ -1986,7 +1986,7 @@ static void LoadWithoutNetworkAccess (XmlDocument doc, string filename) using (var fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) { var settings = new XmlReaderSettings () { XmlResolver = null, - DtdProcessing = DtdProcessing.Parse, + DtdProcessing = DtdProcessing.Ignore, }; using (var reader = XmlReader.Create (fs, settings)) { doc.Load (reader); diff --git a/tests/xharness/Jenkins/TestVariationsFactory.cs b/tests/xharness/Jenkins/TestVariationsFactory.cs index 53f58932a818..c47e46be53b5 100644 --- a/tests/xharness/Jenkins/TestVariationsFactory.cs +++ b/tests/xharness/Jenkins/TestVariationsFactory.cs @@ -129,6 +129,10 @@ IEnumerable GetTestData (RunTestTask test) yield return new TestData { Variation = "Debug (interpreter)", TestVariation = "interpreter", Ignored = ignore }; yield return new TestData { Variation = "Release (interpreter)", TestVariation = "release|interpreter", Ignored = ignore }; } + yield return new TestData { Variation = $"Release (compat inline dlfcn)", TestVariation = "inline-dlfcn-methods-compat|release", Ignored = ignore }; + yield return new TestData { Variation = $"Release (strict inline dlfcn, link sdk)", TestVariation = "inline-dlfcn-methods-strict|linksdk|release", Ignored = ignore }; + if (mac_supports_arm64) + yield return new TestData { Variation = $"Release (NativeAOT, .NET 11 defaults)", TestVariation = "inline-dlfcn-methods-strict|nativeaot|release", Ignored = ignore, RuntimeIdentifier = arm64_sim_runtime_identifier }; // it's necessary to specify RID, because NativeAOT defaults to building for device break; case "introspection": if (mac_supports_arm64) diff --git a/tools/common/CompilerFlags.cs b/tools/common/CompilerFlags.cs index 1138c4ca917f..1181f05a6943 100644 --- a/tools/common/CompilerFlags.cs +++ b/tools/common/CompilerFlags.cs @@ -55,7 +55,7 @@ public void ReferenceSymbols (IEnumerable symbols, Abi abi) foreach (var symbol in symbols) { if (symbol.ValidAbis.HasValue && (symbol.ValidAbis.Value & abi) == 0) continue; - UnresolvedSymbols.Add (symbol.Prefix + symbol.Name); + UnresolvedSymbols.Add (Symbol.Prefix + symbol.Name); } } diff --git a/tools/common/Frameworks.cs b/tools/common/Frameworks.cs index cc617412239b..1a831735145d 100644 --- a/tools/common/Frameworks.cs +++ b/tools/common/Frameworks.cs @@ -7,6 +7,7 @@ using Mono.Tuner; using Xamarin.Bundler; +using Xamarin.Linker; using Registrar; #endif @@ -453,7 +454,7 @@ public static Frameworks CreateiOSFrameworks (bool is_simulator_build) { "CoreLocationUI", "CoreLocationUI", 15,0 }, { "DataDetection", "DataDetection", 15, 0 }, - { "Phase", "PHASE", new Version (15,0), NotAvailableInSimulator /* no headers in beta 2 */ }, + { "Phase", "PHASE", new Version (15, 0), new Version (26, 0) /* not certain about the exact version when this framework was added to the simulator, but this should be a safe default */ }, { "OSLog", "OSLog", 15,0 }, { "ShazamKit", "ShazamKit", new Version (15,0), new Version (16, 0)}, { "ThreadNetwork", "ThreadNetwork", new Version (15,0), NotAvailableInSimulator}, @@ -702,11 +703,12 @@ public static Frameworks GetMacCatalystFrameworks () } } -#if LEGACY_TOOLS || BUNDLER - public static IEnumerable GetFrameworks (TypeDefinition td) +#if BUNDLER + public static bool TryGetFramework (Application app, TypeDefinition td, [NotNullWhen (true)] out string? framework) { + framework = null; + if (td.HasCustomAttributes) { - var any = false; foreach (var attrib in td.CustomAttributes) { if (!attrib.AttributeType.Is ("ObjCRuntime", "ObjectiveCFrameworkAttribute")) continue; @@ -715,25 +717,56 @@ public static IEnumerable GetFrameworks (TypeDefinition td) var arg = attrib.ConstructorArguments [0]; if (arg.Value is not string stringArgument) continue; - yield return stringArgument; - any = true; + framework = stringArgument; + return framework is not null; } - if (any) - yield break; } - yield return td.Namespace; + if (!app.Profile.IsProductAssembly (td.Module.Assembly)) + return false; + + framework = td.Namespace; + return framework is not null; + } + + public static bool TryGetFramework (Application app, TypeDefinition td, [NotNullWhen (true)] out Framework? framework) + { + framework = null; + + if (!TryGetFramework (app, td, out string? frameworkName)) + return false; + + var all_frameworks = GetFrameworks (app.Platform, app.IsSimulatorBuild); + if (all_frameworks is null) + return false; + return all_frameworks.TryGetValue (frameworkName, out framework); } - static void Gather (Application app, AssemblyDefinition product_assembly, HashSet frameworks, HashSet weak_frameworks, Func include_framework) + static void Gather (Application app, IEnumerable assemblies, HashSet frameworks, HashSet weak_frameworks, Func include_framework) { var namespaces = new HashSet (); - // Collect all the namespaces. - foreach (var md in product_assembly.Modules) { - foreach (var td in md.Types) { - foreach (var fw in GetFrameworks (td)) - namespaces.Add (fw); + // Process our product assembly + any assembly with the [ObjectiveCFramework] attribute, and collect all the namespaces that are used in those assemblies. + // For non-product assemblies, we only look at types with the [ObjectiveCFramework] attribute. + foreach (var assembly in assemblies) { + var hasObjectiveCFrameworkAttribute = false; + if (!app.Profile.IsProductAssembly (assembly)) { + hasObjectiveCFrameworkAttribute = assembly.MainModule.HasTypeReference ("ObjCRuntime.ObjectiveCFrameworkAttribute"); + if (!hasObjectiveCFrameworkAttribute) + continue; + } + + // Collect all the namespaces. + foreach (var md in assembly.Modules) { + foreach (var td in md.Types) { + if (hasObjectiveCFrameworkAttribute && !td.HasCustomAttribute ("ObjCRuntime", "ObjectiveCFrameworkAttribute")) + continue; + + if (TryGetFramework (app, td, out string? framework)) { + namespaces.Add (framework); + continue; + } + } } } @@ -798,9 +831,9 @@ static bool FilterFrameworks (Application app, Framework framework) return true; } - public static void Gather (Application app, AssemblyDefinition product_assembly, HashSet frameworks, HashSet weak_frameworks) + public static void Gather (Application app, IEnumerable assemblies, HashSet frameworks, HashSet weak_frameworks) { - Gather (app, product_assembly, frameworks, weak_frameworks, (framework) => FilterFrameworks (app, framework)); + Gather (app, assemblies, frameworks, weak_frameworks, (framework) => FilterFrameworks (app, framework)); } -#endif // LEGACY_TOOLS || BUNDLER +#endif // BUNDLER } diff --git a/tools/common/MachO.cs b/tools/common/MachO.cs index 197c99736be1..f54f4e222d95 100644 --- a/tools/common/MachO.cs +++ b/tools/common/MachO.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; using System.Text; using Xamarin.Bundler; @@ -90,6 +91,7 @@ public enum LoadCommands : uint { // /* Constants for the cmd field of all load commands, the type */ //#define LC_SEGMENT 0x1 /* segment of this file to be mapped */ //#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */ + Symtab = 0x2, //#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */ //#define LC_THREAD 0x4 /* thread */ //#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */ @@ -606,8 +608,8 @@ internal void Read (string filename, BinaryReader reader, long size) file.Read (reader); object_files.Add (file); } - // byte position is always even after each file. - if (nextPosition % 1 == 1) + // The ar format requires each entry to start at an even byte offset. + if (nextPosition % 2 == 1) nextPosition++; reader.BaseStream.Position = nextPosition; } @@ -641,6 +643,33 @@ public static bool IsStaticLibrary (string filename, bool throw_if_error = false } } } + + /// + /// Reads a static library or a Mach-O object file and returns the set of unresolved (undefined external) symbols. + /// + public static HashSet GetUnresolvedSymbols (string filename) + { + var symbols = new HashSet (); + using (var fs = File.OpenRead (filename)) + using (var reader = new BinaryReader (fs)) { + if (IsStaticLibrary (reader)) { + var lib = new StaticLibrary (); + lib.Read (filename, reader, fs.Length); + foreach (var obj in lib.ObjectFiles) { + foreach (var sym in obj.GetUnresolvedSymbols (reader)) + symbols.Add (sym); + } + } else if (MachOFile.IsMachOLibrary (null, reader)) { + var obj = new MachOFile (filename); + obj.Read (reader); + foreach (var sym in obj.GetUnresolvedSymbols (reader)) + symbols.Add (sym); + } else { + throw ErrorHelper.CreateError (1601, Errors.MT1601, System.Text.Encoding.ASCII.GetString (reader.ReadBytes (7), 0, 7)); + } + } + return symbols; + } } public class MachOFile { @@ -657,6 +686,7 @@ public class MachOFile { uint _reserved; bool is64bitheader; + long streamBasePosition; // position in the stream where this Mach-O header starts public int cputype { get { return is_big_endian ? MachO.ToBigEndian (_cputype) : _cputype; } } public int cpusubtype { get { return is_big_endian ? MachO.ToBigEndian (_cpusubtype) : _cpusubtype; } } @@ -728,6 +758,8 @@ internal static bool IsMachOLibrary (FatEntry? fat_entry, BinaryReader reader, b internal void Read (BinaryReader reader) { + streamBasePosition = reader.BaseStream.Position; + /* definitions from: /usr/include/mach-o/loader.h */ /* * The 32-bit mach header appears at the very beginning of the object file for @@ -868,6 +900,16 @@ internal void Read (BinaryReader reader) } lc = buildVer; break; + case MachO.LoadCommands.Symtab: + var symtabCmd = new SymtabLoadCommand (); + symtabCmd.cmd = reader.ReadUInt32 (); + symtabCmd.cmdsize = reader.ReadUInt32 (); + symtabCmd.symoff = reader.ReadUInt32 (); + symtabCmd.nsyms = reader.ReadUInt32 (); + symtabCmd.stroff = reader.ReadUInt32 (); + symtabCmd.strsize = reader.ReadUInt32 (); + lc = symtabCmd; + break; default: lc = new LoadCommand (); lc.cmd = reader.ReadUInt32 (); @@ -893,6 +935,58 @@ public bool IsDynamicLibrary { public bool IsObjectFile { get => filetype == MachO.MH_OBJECT; } + + const byte N_EXT = 0x01; // external symbol + const byte N_TYPE = 0x0e; // mask for type bits + const byte N_UNDF = 0x0; // undefined symbol + + /// + /// Reads unresolved (undefined external) symbols from this Mach-O file. + /// The reader must be the same stream used to read this file. + /// + public HashSet GetUnresolvedSymbols (BinaryReader reader) + { + var symbols = new HashSet (); + var symtab = load_commands.OfType ().FirstOrDefault (); + if (symtab is null || symtab.nsyms == 0) + return symbols; + + // Read the string table + reader.BaseStream.Position = streamBasePosition + symtab.stroff; + var stringTable = reader.ReadBytes ((int) symtab.strsize); + + // Read symbol table entries + reader.BaseStream.Position = streamBasePosition + symtab.symoff; + var nlistSize = is64bitheader ? 16 : 12; + for (uint i = 0; i < symtab.nsyms; i++) { + var n_strx = reader.ReadUInt32 (); + var n_type = reader.ReadByte (); + var n_sect = reader.ReadByte (); + var n_desc = reader.ReadInt16 (); + if (is64bitheader) + reader.ReadUInt64 (); // n_value (8 bytes) + else + reader.ReadUInt32 (); // n_value (4 bytes) + + // Filter for undefined external symbols (equivalent of nm -u) + if ((n_type & N_EXT) == 0) + continue; + if ((n_type & N_TYPE) != N_UNDF) + continue; + + // Read symbol name from string table + if (n_strx >= symtab.strsize) + continue; + var end = (int) n_strx; + while (end < stringTable.Length && stringTable [end] != 0) + end++; + var name = Encoding.UTF8.GetString (stringTable, (int) n_strx, end - (int) n_strx); + if (name.Length > 0) + symbols.Add (name); + } + + return symbols; + } } public class FatFile { @@ -1148,4 +1242,11 @@ public MachO.Platform Platform { get { return (MachO.Platform) platform; } } } + + public class SymtabLoadCommand : LoadCommand { + public uint symoff; // offset to symbol table entries + public uint nsyms; // number of symbol table entries + public uint stroff; // offset to string table + public uint strsize; // size of string table in bytes + } } diff --git a/tools/common/PListExtensions.cs b/tools/common/PListExtensions.cs index 26ac6c7e745e..892e142eb61d 100644 --- a/tools/common/PListExtensions.cs +++ b/tools/common/PListExtensions.cs @@ -11,7 +11,7 @@ public static void LoadWithoutNetworkAccess (this XmlDocument doc, string filena using (var fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) { var settings = new XmlReaderSettings () { XmlResolver = null, - DtdProcessing = DtdProcessing.Parse, + DtdProcessing = DtdProcessing.Ignore, }; using (var reader = XmlReader.Create (fs, settings)) { doc.Load (reader); @@ -24,7 +24,7 @@ public static void LoadXmlWithoutNetworkAccess (this XmlDocument doc, string xml using (var fs = new StringReader (xml)) { var settings = new XmlReaderSettings () { XmlResolver = null, - DtdProcessing = DtdProcessing.Parse, + DtdProcessing = DtdProcessing.Ignore, }; using (var reader = XmlReader.Create (fs, settings)) { doc.Load (reader); diff --git a/tools/common/Symbols.cs b/tools/common/Symbols.cs index 7306afd5fa2f..6b1b13077fe5 100644 --- a/tools/common/Symbols.cs +++ b/tools/common/Symbols.cs @@ -27,7 +27,7 @@ public class Symbol { public bool Ignore; public Abi? ValidAbis; - static string ObjectiveCPrefix { + public static string ObjectiveCPrefix { get { return "OBJC_CLASS_$_"; } @@ -52,11 +52,7 @@ public string Name { } public string? ObjectiveCName; - public string Prefix { - get { - return "_"; - } - } + public const string Prefix = "_"; List members = new List (); public IEnumerable Members { get { return members; } } @@ -158,6 +154,7 @@ public Symbol this [string name] { } } +#if !MSBUILD_TASKS public void Load (string filename, Application app) { using (var reader = new StreamReader (filename)) { @@ -183,6 +180,7 @@ public void Load (string filename, Application app) } } } +#endif // !MSBUILD_TASKS public void Save (string filename) { diff --git a/tools/devops/automation/scripts/TestResults.Tests.ps1 b/tools/devops/automation/scripts/TestResults.Tests.ps1 index 1a27744780c7..0d29999bc54f 100644 --- a/tools/devops/automation/scripts/TestResults.Tests.ps1 +++ b/tools/devops/automation/scripts/TestResults.Tests.ps1 @@ -1352,4 +1352,76 @@ Test results reported success, but the tests job failed. $sonomaIdx | Should -BeLessThan $sequoiaIdx } } + + Context "VSDrops publish failed" { + It "shows publish failed text instead of VSDrops link" { + $VerbosePreference = "Continue" + $DebugPreference = "Continue" + + $vsdropsMatrix = @" +{ + "cecil": { + "LABEL": "cecil", + "TESTS_LABELS": "--label=skip-all-tests,run-cecil-tests", + "TEST_STAGE": "simulator_tests", + "LABEL_WITH_PLATFORM": "cecil", + "STATUS_CONTEXT": "VSTS: simulator tests - cecil", + "TEST_PREFIX": "simulator_testscecil", + "TEST_PLATFORM": "" + } +} +"@ + $vsdropsFailedStageDeps = @" +{ + "configure_build": { + "configure": { + "outputs": { + "test_matrix.TEST_MATRIX": "$($vsdropsMatrix.Replace("`n", "\n").Replace("`"", "\`""))" + } + } + }, + "simulator_tests": { + "tests": { + "outputs": { + "cecil.PowerShell15.TESTS_ATTEMPT": "1", + "cecil.PowerShell15.TESTS_BOT": "XAMMINI-013.Ventura", + "cecil.PowerShell15.TESTS_LABEL": "cecil", + "cecil.PowerShell15.TESTS_PLATFORM": "", + "cecil.PowerShell15.TESTS_TITLE": "cecil", + "cecil.runTests.TESTS_JOBSTATUS": "Succeeded", + "cecil.setVSDropsPublishResult.VSDROPS_PUBLISHED": "Failed" + }, + "identifier": null, + "name": "tests", + "attempt": 1, + "startTime": null, + "finishTime": null, + "state": "NotStarted", + "result": "Succeeded" + } + } +} +"@ + $testDirectory = Join-Path "." "subdir" + New-Item -Path "$testDirectory" -ItemType "directory" -Force + New-Item -Path "$testDirectory/TestSummary-simulator_testscecil-1" -Name "TestSummary.md" -Value "# :tada: All 1 tests passed :tada:" -Force + + $parallelResults = New-ParallelTestsResults -Path "$testDirectory" -StageDependencies "$vsdropsFailedStageDeps" -Context "context" -VSDropsIndex "vsdropsIndex" + + $parallelResults.IsSuccess() | Should -Be $true + + $sb = [System.Text.StringBuilder]::new() + $parallelResults.WriteComment($sb) + + Remove-Item -Path $testDirectory -Recurse + + $content = $sb.ToString() + + Write-Host $content + + $content | Should -Not -BeLike "*[Html Report (VSDrops)]*" + $content | Should -BeLike "*(:warning: Html Report Publish failed :warning:)*" + $content | Should -BeLike "*[Download]*" + } + } } diff --git a/tools/devops/automation/scripts/TestResults.psm1 b/tools/devops/automation/scripts/TestResults.psm1 index ef5b0eb06457..da6b71d7107e 100644 --- a/tools/devops/automation/scripts/TestResults.psm1 +++ b/tools/devops/automation/scripts/TestResults.psm1 @@ -61,6 +61,7 @@ class TestResult { [string] $TestStage [string] $DisplayName [bool] $IsMacTest + [bool] $VSDropsPublishFailed hidden [int] $Passed hidden [int] $Failed hidden [string[]] $NotTestSummaryLabels = @() @@ -339,9 +340,13 @@ class ParallelTestsResults { } [string] GetDownloadLinks($testResult) { - $dropsIndex = "$($this.VSDropsIndex)/$($testResult.TestStage)$($testResult.Title)-$($testResult.Attempt)/;/tests/vsdrops_index.html" $artifactUrl = "$Env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI$Env:SYSTEM_TEAMPROJECT/_apis/build/builds/$Env:BUILD_BUILDID/artifacts?artifactName=HtmlReport-$($testResult.TestStage)$($testResult.Title)-$($testResult.Attempt)&api-version=6.0&`$format=zip" - $downloadInfo = "[Html Report (VSDrops)]($dropsIndex) [Download]($artifactUrl)" + if ($testResult.VSDropsPublishFailed) { + $downloadInfo = "(:warning: Html Report Publish failed :warning:) [Download]($artifactUrl)" + } else { + $dropsIndex = "$($this.VSDropsIndex)/$($testResult.TestStage)$($testResult.Title)-$($testResult.Attempt)/;/tests/vsdrops_index.html" + $downloadInfo = "[Html Report (VSDrops)]($dropsIndex) [Download]($artifactUrl)" + } return $downloadInfo } @@ -589,6 +594,7 @@ class ParallelTestsResults { $platformKey = $outputs.Keys | Where-Object { $_.EndsWith(".TESTS_PLATFORM") } $attemptKey = $outputs.Keys | Where-Object { $_.EndsWith(".TESTS_ATTEMPT") } $titleKey = $outputs.Keys | Where-Object { $_.EndsWith(".TESTS_TITLE") } + $vsdropsPublishedKey = $outputs.Keys | Where-Object { $_.EndsWith(".VSDROPS_PUBLISHED") } | Sort-Object | Select-Object -Last 1 } else { # matrix job $jobName = $name.Substring(0, $name.IndexOf('.')) @@ -597,6 +603,7 @@ class ParallelTestsResults { $platformKey = $outputs.Keys | Where-Object { $_.StartsWith($jobName + ".") -and $_.EndsWith(".TESTS_PLATFORM") } $attemptKey = $outputs.Keys | Where-Object { $_.StartsWith($jobName + ".") -and $_.EndsWith(".TESTS_ATTEMPT") } $titleKey = $outputs.Keys | Where-Object { $_.StartsWith($jobName + ".") -and $_.EndsWith(".TESTS_TITLE") } + $vsdropsPublishedKey = $outputs.Keys | Where-Object { $_.StartsWith($jobName + ".") -and $_.EndsWith(".VSDROPS_PUBLISHED") } | Sort-Object | Select-Object -Last 1 } Write-Host "Keys for Label='$label' and JobName='$jobName' (dotCount=$dotCount): TitleKey='$titleKey' StatusKey=$statusKey BotKey=$botKey PlatformKey=$platformKey AttemptKey=$attemptKey" @@ -611,6 +618,7 @@ class ParallelTestsResults { $platform = if ($platformKey -eq $null) { "NotFound" } else { $outputs[$platformKey] } $attempt = if ($attemptKey -eq $null) { -2 } else { [int]$outputs[$attemptKey] } $title = if ($titleKey -eq $null) { "NotFound" } else { $outputs[$titleKey] } + $vsdropsPublished = if ($vsdropsPublishedKey -eq $null) { $null } else { $outputs[$vsdropsPublishedKey] } $testResult = [PSCustomObject]@{ Label = $label Title = $title @@ -619,6 +627,7 @@ class ParallelTestsResults { Platform = $platform Attempt = $attempt TestStage = $testStage + VSDropsPublished = $vsdropsPublished } if ($tests.Contains($label)) { $testInfo = $tests[$label] @@ -675,6 +684,7 @@ class ParallelTestsResults { } $result = [TestResult]::new($testSummaryPath, $status, $testConfig, $testAttempt) + $result.VSDropsPublishFailed = ($testResult.VSDropsPublished -eq "Failed") } $testResults += $result diff --git a/tools/devops/automation/templates/mac/build.yml b/tools/devops/automation/templates/mac/build.yml index b564d24af9ac..770a2358fb29 100644 --- a/tools/devops/automation/templates/mac/build.yml +++ b/tools/devops/automation/templates/mac/build.yml @@ -210,8 +210,15 @@ steps: condition: succeededOrFailed() # Upload to VSDrops so that the Html Report link in the GitHub comment works. +- bash: | + echo "##vso[task.setvariable variable=JOB_STATUS_BEFORE_VSDROPS]$AGENT_JOBSTATUS" + displayName: 'Capture job status before VSDrops publish' + condition: succeededOrFailed() + continueOnError: true + - task: artifactDropTask@1 displayName: 'Publish to Artifact Services Drop' + name: publishVSDrops inputs: dropServiceURI: 'https://devdiv.artifacts.visualstudio.com/DefaultCollection' dropMetadataContainerName: '${{ parameters.uploadPrefix }}DropMetadata-${{ parameters.stageName }}${{ parameters.label }}-$(System.JobAttempt)' @@ -223,6 +230,19 @@ steps: continueOnError: true condition: succeededOrFailed() +# Azure DevOps doesn't support checking individual step results in step conditions +# (failed('stepName') only works for jobs/stages). Comparing AGENT_JOBSTATUS before +# and after the publish step is the best available approach to detect publish failures. +- bash: | + if [ "$JOB_STATUS_BEFORE_VSDROPS" != "$AGENT_JOBSTATUS" ]; then + echo "VSDrops publish changed job status from '$JOB_STATUS_BEFORE_VSDROPS' to '$AGENT_JOBSTATUS'" + echo "##vso[task.setvariable variable=VSDROPS_PUBLISHED;isOutput=true]Failed" + fi + name: setVSDropsPublishResult + displayName: 'Set VSDrops publish result' + continueOnError: true + condition: succeededOrFailed() + - template: ../common/archive-html-report.yml parameters: rootFolder: '$(BUILD_REPOSITORY_TITLE)/jenkins-results' diff --git a/tools/devops/automation/templates/tests/run-tests.yml b/tools/devops/automation/templates/tests/run-tests.yml index 0ff0d43d39cb..188474aa28ea 100644 --- a/tools/devops/automation/templates/tests/run-tests.yml +++ b/tools/devops/automation/templates/tests/run-tests.yml @@ -182,8 +182,15 @@ steps: continueOnError: true condition: succeededOrFailed() +- bash: | + echo "##vso[task.setvariable variable=JOB_STATUS_BEFORE_VSDROPS]$AGENT_JOBSTATUS" + displayName: 'Capture job status before VSDrops publish' + condition: succeededOrFailed() + continueOnError: true + - task: artifactDropTask@1 displayName: 'Publish to Artifact Services Drop' + name: publishVSDrops inputs: dropServiceURI: 'https://devdiv.artifacts.visualstudio.com/DefaultCollection' dropMetadataContainerName: '${{ parameters.uploadPrefix }}DropMetadata-${{ parameters.testPrefix }}${{ parameters.labelWithPlatform }}-$(System.JobAttempt)' @@ -195,6 +202,19 @@ steps: continueOnError: true condition: succeededOrFailed() +# Azure DevOps doesn't support checking individual step results in step conditions +# (failed('stepName') only works for jobs/stages). Comparing AGENT_JOBSTATUS before +# and after the publish step is the best available approach to detect publish failures. +- bash: | + if [ "$JOB_STATUS_BEFORE_VSDROPS" != "$AGENT_JOBSTATUS" ]; then + echo "VSDrops publish changed job status from '$JOB_STATUS_BEFORE_VSDROPS' to '$AGENT_JOBSTATUS'" + echo "##vso[task.setvariable variable=VSDROPS_PUBLISHED;isOutput=true]Failed" + fi + name: setVSDropsPublishResult + displayName: 'Set VSDrops publish result' + continueOnError: true + condition: succeededOrFailed() + - bash: | set -ex find . -name 'vsts-*.xml' || true diff --git a/tools/dotnet-linker/AppBundleRewriter.cs b/tools/dotnet-linker/AppBundleRewriter.cs index f49c71d518bd..5013997108d1 100644 --- a/tools/dotnet-linker/AppBundleRewriter.cs +++ b/tools/dotnet-linker/AppBundleRewriter.cs @@ -422,6 +422,12 @@ public TypeReference ObjCRuntime_Class { } } + public TypeReference ObjCRuntime_Dlfcn { + get { + return GetTypeReference (PlatformAssembly, "ObjCRuntime.Dlfcn", out var _); + } + } + public TypeReference ObjCRuntime_IManagedRegistrar { get { return GetTypeReference (PlatformAssembly, "ObjCRuntime.IManagedRegistrar", out var _); @@ -464,6 +470,12 @@ public TypeReference ObjCRuntime_NSObjectProxyAttribute { } } + public TypeReference ObjCRuntime_ObjectiveCFrameworkAttribute { + get { + return GetTypeReference (PlatformAssembly, "ObjCRuntime.ObjectiveCFrameworkAttribute", out var _); + } + } + public TypeReference ObjCRuntime_ProtocolProxyAttribute { get { return GetTypeReference (PlatformAssembly, "ObjCRuntime.ProtocolProxyAttribute", out var _); @@ -726,6 +738,17 @@ public MethodReference Class_GetHandle__System_String { } } + public MethodReference ObjectiveCFrameworkAttribute_ctor_String { + get { + return GetMethodReference (PlatformAssembly, ObjCRuntime_ObjectiveCFrameworkAttribute, ".ctor", (v) => + v.IsConstructor + && v.HasParameters + && v.Parameters.Count == 1 + && v.Parameters [0].ParameterType.Is ("System", "String") + && !v.HasGenericParameters); + } + } + public MethodReference ObjCRuntime_INativeObjectProxyAttribute__ctor { get { return GetMethodReference (PlatformAssembly, ObjCRuntime_INativeObjectProxyAttribute, ".ctor", (v) => v.IsDefaultConstructor ()); diff --git a/tools/dotnet-linker/LinkerConfiguration.cs b/tools/dotnet-linker/LinkerConfiguration.cs index bb7a257231c7..0d89756da5f6 100644 --- a/tools/dotnet-linker/LinkerConfiguration.cs +++ b/tools/dotnet-linker/LinkerConfiguration.cs @@ -30,6 +30,13 @@ public class LinkerConfiguration { public string IntermediateLinkDir { get; private set; } = string.Empty; public bool InvariantGlobalization { get; private set; } public bool HybridGlobalization { get; private set; } + public InlineDlfcnMethodsMode InlineDlfcnMethods { get; set; } + public bool InlineDlfcnMethodsEnabled => InlineDlfcnMethods != InlineDlfcnMethodsMode.Disabled; + // Per-assembly field symbols collected by InlineDlfcnMethodsStep, keyed by assembly name. + public Dictionary> InlinedDlfcnFields { get; } = new Dictionary> (); + // All [Field] symbol names collected by ProcessExportedFields, used in compatibility mode. + public HashSet FieldSymbols { get; } = new HashSet (); + public string IntermediateOutputPath { get; private set; } = string.Empty; public string ItemsDirectory { get; private set; } = string.Empty; public bool IsSimulatorBuild { get; private set; } public string PartialStaticRegistrarLibrary { get; set; } = string.Empty; @@ -46,6 +53,7 @@ public class LinkerConfiguration { public Application Application { get; private set; } public IList RegistrationMethods { get; set; } = new List (); + public List NativeCodeToCompileAndLink { get; private set; } = new List (); public CompilerFlags CompilerFlags; LinkContext? context; @@ -205,9 +213,22 @@ public static LinkerConfiguration GetInstance (LinkContext context) case "FrameworkAssembly": FrameworkAssemblies.Add (value); break; + case "InlineDlfcnMethods": + if (Enum.TryParse (value, true, out var inlineDlfcnMode)) + InlineDlfcnMethods = inlineDlfcnMode; + else if (string.Equals (value, "compatibility", StringComparison.OrdinalIgnoreCase)) + InlineDlfcnMethods = InlineDlfcnMethodsMode.Compat; + else if (string.IsNullOrEmpty (value)) + InlineDlfcnMethods = InlineDlfcnMethodsMode.Disabled; + else + throw new InvalidOperationException ($"Unknown InlineDlfcnMethods value: {value}"); + break; case "IntermediateLinkDir": IntermediateLinkDir = value; break; + case "IntermediateOutputPath": + IntermediateOutputPath = value; + break; case "Interpreter": if (!string.IsNullOrEmpty (value)) Application.ParseInterpreter (value); @@ -536,7 +557,9 @@ public void Write () foreach (var lib in Application.DylibsToConvertToFrameworks.OrderBy (v => v)) Console.WriteLine ($" {lib}"); Console.WriteLine ($" EnableSGenConc {Application.EnableSGenConc}"); + Console.WriteLine ($" InlineDlfcnMethods: {InlineDlfcnMethods}"); Console.WriteLine ($" IntermediateLinkDir: {IntermediateLinkDir}"); + Console.WriteLine ($" IntermediateOutputPath: {IntermediateOutputPath}"); Console.WriteLine ($" InterpretedAssemblies: {string.Join (", ", Application.InterpretedAssemblies)}"); Console.WriteLine ($" ItemsDirectory: {ItemsDirectory}"); Console.WriteLine ($" {FrameworkAssemblies.Count} framework assemblies:"); @@ -653,3 +676,9 @@ public MSBuildItem (string include, Dictionary metadata) Metadata = metadata; } } + +public enum InlineDlfcnMethodsMode { + Disabled, + Strict, + Compat, +} diff --git a/tools/dotnet-linker/Steps/AssemblyModifierStep.cs b/tools/dotnet-linker/Steps/AssemblyModifierStep.cs index 2e3e971d4d87..8e2899fb0660 100644 --- a/tools/dotnet-linker/Steps/AssemblyModifierStep.cs +++ b/tools/dotnet-linker/Steps/AssemblyModifierStep.cs @@ -31,7 +31,8 @@ protected sealed override void TryProcessAssembly (AssemblyDefinition assembly) protected virtual bool ModifyAssembly (AssemblyDefinition assembly) { var modified = false; - foreach (var type in assembly.MainModule.Types) + // ToArray () is needed because subclasses (e.g. InlineDlfcnMethodsStep) may add new types during iteration. + foreach (var type in assembly.MainModule.Types.ToArray ()) modified |= ProcessTypeImpl (type); return modified; } @@ -50,7 +51,8 @@ bool ProcessTypeImpl (TypeDefinition type) { var modified = ProcessType (type); if (type.HasNestedTypes) { - foreach (var nested in type.NestedTypes) + // ToArray () is needed because subclasses may add new types during iteration. + foreach (var nested in type.NestedTypes.ToArray ()) modified |= ProcessTypeImpl (nested); } return modified; diff --git a/tools/dotnet-linker/Steps/GatherFrameworksStep.cs b/tools/dotnet-linker/Steps/GatherFrameworksStep.cs index 4d5eb1fbfca7..5fb658b02f89 100644 --- a/tools/dotnet-linker/Steps/GatherFrameworksStep.cs +++ b/tools/dotnet-linker/Steps/GatherFrameworksStep.cs @@ -20,10 +20,7 @@ protected override void TryProcessAssembly (AssemblyDefinition assembly) { base.TryProcessAssembly (assembly); - if (Configuration.PlatformAssembly != assembly.Name.Name) - return; - - global::Frameworks.Gather (Configuration.Application, assembly, Frameworks, WeakFrameworks); + global::Frameworks.Gather (Configuration.Application, [assembly], Frameworks, WeakFrameworks); } protected override void TryEndProcess () diff --git a/tools/dotnet-linker/Steps/GenerateReferencesStep.cs b/tools/dotnet-linker/Steps/GenerateReferencesStep.cs index 7d1f08537fb3..4a3959aa0f80 100644 --- a/tools/dotnet-linker/Steps/GenerateReferencesStep.cs +++ b/tools/dotnet-linker/Steps/GenerateReferencesStep.cs @@ -38,7 +38,7 @@ protected override void TryEndProcess () break; case SymbolMode.Linker: foreach (var symbol in required_symbols) { - var item = new MSBuildItem (symbol.Prefix + symbol.Name); + var item = new MSBuildItem (Symbol.Prefix + symbol.Name); item.Metadata ["SymbolType"] = symbol.Type.ToString (); items.Add (item); } diff --git a/tools/dotnet-linker/Steps/InlineDlfcnMethodsStep.cs b/tools/dotnet-linker/Steps/InlineDlfcnMethodsStep.cs new file mode 100644 index 000000000000..0012ca7a456f --- /dev/null +++ b/tools/dotnet-linker/Steps/InlineDlfcnMethodsStep.cs @@ -0,0 +1,1015 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using Mono.Cecil; +using Mono.Cecil.Cil; +using Mono.Cecil.Rocks; +using Mono.Linker; +using Mono.Linker.Steps; +using Mono.Tuner; +using MonoTouch.Tuner; + +using Xamarin.Bundler; + +#nullable enable + +namespace Xamarin.Linker.Steps; + +// See docs/code/native-symbols.md for an overview of native symbol handling. +public class InlineDlfcnMethodsStep : AssemblyModifierStep { + + protected override string Name { get; } = "Inline Dlfcn Methods"; + protected override int ErrorCode { get; } = 2250; + + bool strictMode; + + protected override void TryProcess () + { + strictMode = Configuration.InlineDlfcnMethods == InlineDlfcnMethodsMode.Strict; + base.TryProcess (); + } + + string? current_framework; + protected override bool ProcessType (TypeDefinition type) + { + var modified = false; + if (type.HasMethods) { + if (Frameworks.TryGetFramework (App, type, out Framework? framework) && App.IsSimulatorBuild && !framework.IsFrameworkAvailableInSimulator (App)) { + Driver.Log (3, $"Type {type.FullName} appears to be part of the '{framework.Name}' framework, which is not available in the simulator. Skipping inlining Dlfcn calls for this type."); + return modified; + } + + current_framework = framework?.Namespace; + + foreach (var method in type.Methods) + modified |= ProcessMethod (method); + + current_framework = null; + } + return modified; + } + + TypeDefinition GetDlfcnType (MethodDefinition callingMethod) + { + // Check if there's a [Field] attribute with a second string argument (the library/namespace). + // The [Field] attribute can be on the method itself, or on the property the method is a getter/setter for. + var libraryName = callingMethod.HasCustomAttributes ? GetFieldAttributeLibraryName (callingMethod.CustomAttributes) : null; + if (libraryName is null && callingMethod.DeclaringType.HasProperties) { + foreach (var property in callingMethod.DeclaringType.Properties) { + if (property.GetMethod == callingMethod || property.SetMethod == callingMethod) { + libraryName = GetFieldAttributeLibraryName (property.CustomAttributes); + break; + } + } + } + + if (libraryName is not null) + return GetDlfcnType (callingMethod.Module, callingMethod.DeclaringType.Namespace, libraryName); + + return GetDlfcnType (callingMethod.Module, callingMethod.DeclaringType.Namespace); + } + + static string? GetFieldAttributeLibraryName (IList? attributes) + { + if (attributes is null || attributes.Count == 0) + return null; + + foreach (var attrib in attributes) { + if (attrib.AttributeType.Name != "FieldAttribute") + continue; + if (attrib.ConstructorArguments.Count == 2 && + attrib.ConstructorArguments [1].Type.Name == "String" && + attrib.ConstructorArguments [1].Value is string libraryName && + !string.IsNullOrEmpty (libraryName)) { + return libraryName; + } + } + + return null; + } + + // It's important to use a type in the same namespace as the calling code, so that + // we correctly compute which frameworks to link with. + TypeDefinition GetDlfcnType (ModuleDefinition module, string @namespace, string? fieldLibraryName = null) + { + var frameworkOverride = !string.IsNullOrEmpty (fieldLibraryName) ? fieldLibraryName : current_framework; + var ns = string.IsNullOrEmpty (frameworkOverride) ? @namespace : frameworkOverride; + var dlfcn = module.Types.FirstOrDefault (t => t.Namespace == ns && t.Name == "Dlfcn"); + if (dlfcn is null) { + dlfcn = new TypeDefinition (ns, "Dlfcn", TypeAttributes.NotPublic | TypeAttributes.Sealed, module.TypeSystem.Object); + module.Types.Add (dlfcn); + + if (!string.IsNullOrEmpty (frameworkOverride)) { + var attrib = new CustomAttribute (abr.ObjectiveCFrameworkAttribute_ctor_String); + attrib.ConstructorArguments.Add (new CustomAttributeArgument (abr.System_String, frameworkOverride)); + dlfcn.CustomAttributes.Add (attrib); + } + } + return dlfcn; + } + + void AddField (string assemblyName, string symbolName) + { + if (!Configuration.InlinedDlfcnFields.TryGetValue (assemblyName, out var set)) { + set = new HashSet (); + Configuration.InlinedDlfcnFields [assemblyName] = set; + } + set.Add (symbolName); + } + + MethodDefinition GetOrCreatePInvokeMethod (MethodDefinition callingMethod, string symbolName) + { + var dlfcn = GetDlfcnType (callingMethod); + var methodName = $"xamarin_Dlfcn_{symbolName}_Native"; + var nativeMethod = methodName; + var rv = dlfcn.Methods.FirstOrDefault (m => m.Name == methodName); + if (rv is not null) + return rv; // already exists, no need to create it again + + // [DllImport ("__Internal")] + // static extern IntPtr xamarin_Dlfcn_{symbolName}_Native (); + + rv = new MethodDefinition (methodName, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PInvokeImpl, abr.System_IntPtr); + rv.IsPreserveSig = true; + + var mod = callingMethod.Module.ModuleReferences.FirstOrDefault (mr => mr.Name == "__Internal"); + if (mod is null) { + mod = new ModuleReference ("__Internal"); + callingMethod.Module.ModuleReferences.Add (mod); + } + rv.PInvokeInfo = new PInvokeInfo (PInvokeAttributes.CharSetNotSpec | PInvokeAttributes.CallConvCdecl, nativeMethod, mod); + + dlfcn.Methods.Add (rv); + + AddField (callingMethod.Module.Assembly.Name.Name, symbolName); + + return rv; + } + + MethodDefinition GetOrCreateGetSymbolMethod (MethodDefinition callingMethod, string symbolName) + { + var dlfcn = GetDlfcnType (callingMethod); + var methodName = $"Get__{symbolName}"; + var symbolMethod = dlfcn.Methods.FirstOrDefault (m => m.Name == methodName); + if (symbolMethod is not null) + return symbolMethod; // already exists, no need to create it again + + // static bool Get__{symbolName}_Initialized; + // static IntPtr Get__{symbolName}_Cached; + // static IntPtr Get__{symbolName} () + // { + // if (!Get__{symbolName}_Initialized) { + // Get__{symbolName}_Cached = xamarin_Dlfcn_{symbolName}_Native (); + // Get__{symbolName}_Initialized = true; + // } + // return Get__{symbolName}_Cached; + // } + + var initializedField = new FieldDefinition ($"Get__{symbolName}_Initialized", FieldAttributes.Private | FieldAttributes.Static, callingMethod.Module.TypeSystem.Boolean); + dlfcn.Fields.Add (initializedField); + + var cachedField = new FieldDefinition ($"Get__{symbolName}_Cached", FieldAttributes.Private | FieldAttributes.Static, abr.System_IntPtr); + dlfcn.Fields.Add (cachedField); + + var intptr = abr.System_IntPtr; + symbolMethod = new MethodDefinition (methodName, MethodAttributes.Public | MethodAttributes.Static, intptr); + dlfcn.Methods.Add (symbolMethod); + + var body = symbolMethod.Body; + var il = body.GetILProcessor (); + + var loadCachedFieldInstruction = il.Create (OpCodes.Ldsfld, cachedField); + + // if (!Get__{symbolName}_Initialized) { + // The initialized field must use volatile semantics to prevent ARM64 store + // reordering: without it, another thread could see Initialized=true before + // the Cached value is written, and return a stale IntPtr.Zero. + // Note that we don't care if we call the P/Invoke more than once, that's + // a safe operation, we just don't want to call it every time. + il.Append (il.Create (OpCodes.Volatile)); + il.Append (il.Create (OpCodes.Ldsfld, initializedField)); + il.Append (il.Create (OpCodes.Brtrue, loadCachedFieldInstruction)); + + // Get__{symbolName}_Cached = xamarin_Dlfcn_{symbolName}_Native (); + il.Append (il.Create (OpCodes.Call, GetOrCreatePInvokeMethod (callingMethod, symbolName))); + il.Append (il.Create (OpCodes.Stsfld, cachedField)); + + // Get__{symbolName}_Initialized = true; + il.Append (il.Create (OpCodes.Ldc_I4_1)); + il.Append (il.Create (OpCodes.Volatile)); + il.Append (il.Create (OpCodes.Stsfld, initializedField)); + + // return Get__{symbolName}_Cached; + il.Append (loadCachedFieldInstruction); + il.Append (il.Create (OpCodes.Ret)); + + return symbolMethod; + } + + MethodDefinition GetOrCreateGetNativeFieldMethod (MethodDefinition callingMethod, TypeReference fieldType, string symbolName) + { + var dlfcn = GetDlfcnType (callingMethod); + var methodName = $"Get__{symbolName}_{fieldType.Name}"; + var rv = dlfcn.Methods.FirstOrDefault (m => m.Name == methodName); + if (rv is not null) + return rv; // already exists, no need to create it again + + // static FieldType Get__{symbolName}_{fieldType} () + // { + // var ptr = Get__{symbolName} (); + // if (ptr == IntPtr.Zero) + // return default; + // + // /* if value type */ + // return *(FieldType*)ptr; + // + // /* if not value type */ + // return Runtime.GetNSObject (*ptr); + // } + + var importedFieldType = callingMethod.Module.ImportReference (fieldType); + rv = new MethodDefinition (methodName, MethodAttributes.Public | MethodAttributes.Static, importedFieldType); + dlfcn.Methods.Add (rv); + + var body = rv.Body; + var il = body.GetILProcessor (); + + var ptrVariable = new VariableDefinition (abr.System_IntPtr); + body.Variables.Add (ptrVariable); + + var loadPointerInstructionStart = il.Create (OpCodes.Ldloc, ptrVariable); + + // var ptr = Get__{symbolName} (); + il.Append (il.Create (OpCodes.Call, GetOrCreateGetSymbolMethod (callingMethod, symbolName))); + il.Append (il.Create (OpCodes.Stloc, ptrVariable)); + + // if (ptr == IntPtr.Zero) + il.Append (il.Create (OpCodes.Ldloc, ptrVariable)); + il.Append (il.Create (OpCodes.Ldsfld, abr.System_IntPtr_Zero)); + il.Append (il.Create (OpCodes.Bne_Un, loadPointerInstructionStart)); + + // return default; + var fullFieldTypeName = fieldType.FullName; + switch (fullFieldTypeName) { + case "System.Byte": + case "System.SByte": + case "System.Int16": + case "System.UInt16": + case "System.Int32": + case "System.UInt32": + il.Append (il.Create (OpCodes.Ldc_I4_0)); + break; + case "System.Int64": + il.Append (il.Create (OpCodes.Ldc_I4_0)); + il.Append (il.Create (OpCodes.Conv_I8)); + break; + case "System.UInt64": + il.Append (il.Create (OpCodes.Ldc_I4_0)); + il.Append (il.Create (OpCodes.Conv_U8)); + break; + case "System.Single": + il.Append (il.Create (OpCodes.Ldc_R4, 0f)); + break; + case "System.Double": + il.Append (il.Create (OpCodes.Ldc_R8, 0.0)); + break; + case "System.IntPtr": + case "System.UIntPtr": + il.Append (il.Create (OpCodes.Ldc_I4_0)); + il.Append (il.Create (OpCodes.Conv_I)); + break; + default: + if (fieldType.IsValueType) { + if (fieldType.IsPrimitive) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2254 /* Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new. */, callingMethod, Errors.MX2254, fieldType.FullName, symbolName, FormatMethod (callingMethod))); + } + var defaultTemporary = new VariableDefinition (importedFieldType); + body.Variables.Add (defaultTemporary); + il.Append (il.Create (OpCodes.Ldloca, defaultTemporary)); + il.Append (il.Create (OpCodes.Initobj, importedFieldType)); + il.Append (il.Create (OpCodes.Ldloc, defaultTemporary)); + } else { + il.Append (il.Create (OpCodes.Ldnull)); + } + break; + } + il.Append (il.Create (OpCodes.Ret)); + + // /* if value type */ + // return *(FieldType*)ptr; + // /* if not value type */ + // return Runtime.GetNSObject (*(IntPtr*)ptr); + il.Append (loadPointerInstructionStart); // il.Create (OpCodes.Ldloc, ptrVariable); + if (fieldType.IsValueType) { + switch (fieldType.FullName) { + case "System.Byte": + il.Append (il.Create (OpCodes.Ldind_U1)); + break; + case "System.SByte": + il.Append (il.Create (OpCodes.Ldind_I1)); + break; + case "System.Int16": + il.Append (il.Create (OpCodes.Ldind_I2)); + break; + case "System.UInt16": + il.Append (il.Create (OpCodes.Ldind_U2)); + break; + case "System.Int32": + il.Append (il.Create (OpCodes.Ldind_I4)); + break; + case "System.UInt32": + il.Append (il.Create (OpCodes.Ldind_U4)); + break; + case "System.Int64": + case "System.UInt64": + il.Append (il.Create (OpCodes.Ldind_I8)); + break; + case "System.Single": + il.Append (il.Create (OpCodes.Ldind_R4)); + break; + case "System.Double": + il.Append (il.Create (OpCodes.Ldind_R8)); + break; + case "System.IntPtr": + case "System.UIntPtr": + il.Append (il.Create (OpCodes.Ldind_I)); + break; + default: + if (fieldType.IsPrimitive) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2254 /* Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new. */, callingMethod, Errors.MX2254, fieldType.FullName, symbolName, FormatMethod (callingMethod))); + } + il.Append (il.Create (OpCodes.Ldobj, importedFieldType)); + break; + } + } else if (IsNSObjectSubclass (fieldType)) { + il.Append (il.Create (OpCodes.Ldind_I)); + var getnsobject = abr.Runtime_GetNSObject_T___System_IntPtr.CreateGenericInstanceMethod (importedFieldType); + il.Append (il.Create (OpCodes.Call, getnsobject)); + } else { + Report (ErrorHelper.CreateError (Configuration.Application, 2256 /* The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new */, callingMethod, Errors.MX2256, fieldType.FullName, symbolName, FormatMethod (callingMethod))); + } + il.Append (il.Create (OpCodes.Ret)); + + return rv; + } + + MethodDefinition GetOrCreateSetNativeFieldMethod (MethodDefinition callingMethod, TypeReference fieldType, string symbolName) + { + var dlfcn = GetDlfcnType (callingMethod); + var methodName = $"Set__{symbolName}_{fieldType.Name}"; + var rv = dlfcn.Methods.FirstOrDefault (m => m.Name == methodName); + if (rv is not null) + return rv; // already exists, no need to create it again + + // static void Set__{symbolName}_{fieldType} ({FieldType} value) + // { + // var ptr = Get__{symbolName} (); + // if (ptr == IntPtr.Zero) + // return; + // + // /* if value type */ + // *(FieldType*)ptr = value; + // + // /* if not value type */ + // *(IntPtr*)ptr = (IntPtr) Runtime.RetainNSObject (value) + // } + // + // Notes: + // * Just like the Dlfcn method(s), this generated code does not release an existing value of a field. + + var importedFieldType = callingMethod.Module.ImportReference (fieldType); + rv = new MethodDefinition (methodName, MethodAttributes.Public | MethodAttributes.Static, abr.System_Void); + rv.Parameters.Add (new ParameterDefinition ("value", ParameterAttributes.None, importedFieldType)); + dlfcn.Methods.Add (rv); + + var body = rv.Body; + var il = body.GetILProcessor (); + + var ptrVariable = new VariableDefinition (abr.System_IntPtr); + body.Variables.Add (ptrVariable); + + var loadPointerInstructionStart = il.Create (OpCodes.Ldloc, ptrVariable); + + // var ptr = Get__{symbolName} (); + il.Append (il.Create (OpCodes.Call, GetOrCreateGetSymbolMethod (callingMethod, symbolName))); + il.Append (il.Create (OpCodes.Stloc, ptrVariable)); + + // if (ptr == IntPtr.Zero) + il.Append (il.Create (OpCodes.Ldloc, ptrVariable)); + il.Append (il.Create (OpCodes.Ldsfld, abr.System_IntPtr_Zero)); + il.Append (il.Create (OpCodes.Bne_Un, loadPointerInstructionStart)); + // return; + il.Append (il.Create (OpCodes.Ret)); + + // /* if value type */ + // *(FieldType*)ptr = value; + // /* if not value type */ + // *(IntPtr*)ptr = (IntPtr) Runtime.RetainNSObject (value) + il.Append (loadPointerInstructionStart); // il.Create (OpCodes.Ldloc, ptrVariable); + il.Append (il.Create (OpCodes.Ldarg_0)); + if (fieldType.IsValueType) { + switch (fieldType.FullName) { + case "System.Byte": + case "System.SByte": + il.Append (il.Create (OpCodes.Stind_I1)); + break; + case "System.Int16": + case "System.UInt16": + il.Append (il.Create (OpCodes.Stind_I2)); + break; + case "System.Int32": + case "System.UInt32": + il.Append (il.Create (OpCodes.Stind_I4)); + break; + case "System.Int64": + case "System.UInt64": + il.Append (il.Create (OpCodes.Stind_I8)); + break; + case "System.Single": + il.Append (il.Create (OpCodes.Stind_R4)); + break; + case "System.Double": + il.Append (il.Create (OpCodes.Stind_R8)); + break; + case "System.IntPtr": + case "System.UIntPtr": + il.Append (il.Create (OpCodes.Stind_I)); + break; + default: + if (fieldType.IsPrimitive) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2254 /* Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new. */, callingMethod, Errors.MX2254, fieldType.FullName, symbolName, FormatMethod (callingMethod))); + } + il.Append (il.Create (OpCodes.Stobj, importedFieldType)); + break; + } + } else if (IsNSObjectSubclass (fieldType)) { + il.Append (il.Create (OpCodes.Call, abr.Runtime_RetainNSObject)); + il.Append (il.Create (OpCodes.Call, abr.NativeObject_op_Implicit_IntPtr)); + il.Append (il.Create (OpCodes.Stind_I)); + } else { + Report (ErrorHelper.CreateError (Configuration.Application, 2256 /* The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new */, callingMethod, Errors.MX2256, fieldType.FullName, symbolName, FormatMethod (callingMethod))); + } + il.Append (il.Create (OpCodes.Ret)); + + return rv; + } + + MethodDefinition GetOrCreateSetNativeStringMethod (MethodDefinition callingMethod, string symbolName) + { + var dlfcn = GetDlfcnType (callingMethod); + var methodName = $"Set__{symbolName}_String"; + var rv = dlfcn.Methods.FirstOrDefault (m => m.Name == methodName); + if (rv is not null) + return rv; // already exists, no need to create it again + + // static FieldType Set__{symbolName}_String (string? value) + // { + // var ptr = Get__{symbolName} (); + // if (ptr == IntPtr.Zero) + // return; + // + // *(IntPtr*)ptr = (IntPtr) CFString.CreateNative (value); + // } + // + // Notes: + // * Just like the Dlfcn method(s), this generated code does not release an existing value of a field. + + rv = new MethodDefinition (methodName, MethodAttributes.Public | MethodAttributes.Static, abr.System_Void); + rv.Parameters.Add (new ParameterDefinition ("value", ParameterAttributes.None, abr.System_String)); + dlfcn.Methods.Add (rv); + + var body = rv.Body; + var il = body.GetILProcessor (); + + var ptrVariable = new VariableDefinition (abr.System_IntPtr); + body.Variables.Add (ptrVariable); + + var loadPointerInstructionStart = il.Create (OpCodes.Ldloc, ptrVariable); + + // var ptr = Get__{symbolName} (); + il.Append (il.Create (OpCodes.Call, GetOrCreateGetSymbolMethod (callingMethod, symbolName))); + il.Append (il.Create (OpCodes.Stloc, ptrVariable)); + + // if (ptr == IntPtr.Zero) + il.Append (il.Create (OpCodes.Ldloc, ptrVariable)); + il.Append (il.Create (OpCodes.Ldsfld, abr.System_IntPtr_Zero)); + il.Append (il.Create (OpCodes.Bne_Un, loadPointerInstructionStart)); + // return; + il.Append (il.Create (OpCodes.Ret)); + + // *(IntPtr*)ptr = (IntPtr) CFString.CreateNative (value); + il.Append (loadPointerInstructionStart); // il.Create (OpCodes.Ldloc, ptrVariable); + il.Append (il.Create (OpCodes.Ldarg_0)); + il.Append (il.Create (OpCodes.Call, abr.CFString_CreateNative)); + il.Append (il.Create (OpCodes.Call, abr.NativeObject_op_Implicit_IntPtr)); + il.Append (il.Create (OpCodes.Stind_I)); + il.Append (il.Create (OpCodes.Ret)); + + return rv; + } + + bool InlineSymbol (string symbolName) + { + // In compatibility mode, only inline symbols from [Field] attributes. + if (!strictMode && !Configuration.FieldSymbols.Contains (symbolName)) + return false; + + // These symbols already come from [Objective-]C code, so they should already be valid identifiers, + // which means we don't have to validate them. + + var requiredSymbol = DerivedLinkContext.RequiredSymbols.Find (symbolName); + if (requiredSymbol?.Mode == SymbolMode.Ignore) + return false; // don't inline if the symbol is to be ignored + + return true; + } + + protected override bool ProcessMethod (MethodDefinition method) + { + var modified = false; + + if (!method.HasBody) + return modified; + + if (method.DeclaringType.Name == "Dlfcn" && method.DeclaringType.Namespace == "ObjCRuntime") + return modified; // don't process the Dlfcn methods themselves + + foreach (var instr in method.Body.Instructions) { + if (instr.Operand is not MethodReference mr) + continue; + if (mr.DeclaringType.Name != "Dlfcn" || mr.DeclaringType.Namespace != "ObjCRuntime") + continue; + + // Handle Dlfcn functions of the form (libraryHandle, symbolName) + if (mr.Parameters.Count == 2 && mr.Parameters [0].ParameterType.FullName == "System.IntPtr" && mr.Parameters [1].ParameterType.FullName == "System.String") { + if (instr.Previous.OpCode != OpCodes.Ldstr) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + + // In compatibility mode, only inline symbols from [Field] attributes. + var ldstr = instr.Previous; + if (ldstr.Operand is not string symbolName) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + if (!InlineSymbol (symbolName)) + continue; + + switch (mr.Name) { + // primitive types + case "GetDouble": + case "GetFloat": + case "GetNFloat": + case "GetIntPtr": + case "GetUIntPtr": + case "GetNInt": + case "GetNUInt": + case "GetInt16": + case "GetUInt16": + case "GetInt32": + case "GetUInt32": + case "GetInt64": + case "GetUInt64": + // non-primitive value types + case "GetCGSize": + case "GetCGRect": + // classes + case "GetNSNumber": + case "GetStringConstant": + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateGetNativeFieldMethod (method, mr.ReturnType, symbolName); + + modified = true; + continue; + case "GetStruct": + if (mr is not GenericInstanceMethod gim || gim.GenericArguments.Count != 1) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + var returnType = gim.GenericArguments [0]; + if (returnType.IsGenericInstance) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateGetNativeFieldMethod (method, returnType, symbolName); + + modified = true; + continue; + case "GetIndirect": + case "dlsym": + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateGetSymbolMethod (method, symbolName); + + modified = true; + continue; + } + } + + // Handle Dlfcn functions of the form (RTLD, symbolName) + if (mr.Parameters.Count == 2 && mr.Parameters [0].ParameterType.FullName == "ObjCRuntime.Dlfcn/RTLD" && mr.Parameters [1].ParameterType.FullName == "System.String") { + if (instr.Previous.OpCode != OpCodes.Ldstr) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + var ldstr = instr.Previous; + if (ldstr.Operand is not string symbolName) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + + if (!InlineSymbol (symbolName)) + continue; + + + switch (mr.Name) { + case "dlsym": + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateGetSymbolMethod (method, symbolName); + + modified = true; + continue; + } + } + + // Handle Dlfcn functions of the form (libraryName, symbolName) + if (mr.Parameters.Count == 2 && mr.Parameters [0].ParameterType.FullName == "System.String" && mr.Parameters [1].ParameterType.FullName == "System.String") { + if (instr.Previous.OpCode != OpCodes.Ldstr) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + var ldstr = instr.Previous; + if (ldstr.Operand is not string symbolName) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + + if (!InlineSymbol (symbolName)) + continue; + + switch (mr.Name) { + // primitive types + case "SlowGetDouble": + case "SlowGetIntPtr": + case "SlowGetInt32": + case "SlowGetInt64": + // classes + case "SlowGetStringConstant": + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateGetNativeFieldMethod (method, mr.ReturnType, symbolName); + + modified = true; + continue; + } + } + + // Handle Dlfcn functions of the form void (libraryHandle|libraryName, symbolName, value) + if (mr.Parameters.Count == 3 && + (mr.Parameters [0].ParameterType.FullName == "System.String" || mr.Parameters [0].ParameterType.FullName == "System.IntPtr") && + mr.Parameters [1].ParameterType.FullName == "System.String") { + + var ins = instr; + Instruction? ldstr = null; + + // skip any call instructions that take a single argument and return a value, as those are likely to be calls to op_Implicit or op_Explicit functions. + while (ins.Previous.OpCode == OpCodes.Call && ins.Previous.Operand is MethodReference prevMr && !prevMr.ReturnType.Is ("System", "Void") && prevMr.HasParameters && prevMr.Parameters.Count == 1) { + ins = ins.Previous; + } + + switch (ins.Previous.OpCode.StackBehaviourPop) { + case StackBehaviour.Pop0: + switch (ins.Previous.OpCode.StackBehaviourPush) { + case StackBehaviour.Push1: + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + case StackBehaviour.Pushref: + ldstr = ins.Previous.Previous; + break; + } + break; + case StackBehaviour.Pop1: + case StackBehaviour.Popref: + switch (ins.Previous.OpCode.StackBehaviourPush) { + case StackBehaviour.Push1: + case StackBehaviour.Pushi: + case StackBehaviour.Pushi8: + case StackBehaviour.Pushr4: + case StackBehaviour.Pushr8: + case StackBehaviour.Pushref: + ldstr = ins.Previous.Previous.Previous; + break; + } + break; + } + if (ldstr is null) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255, method, "Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. Unknown instruction sequence: {2} ({3}/{4}). The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new.", FormatMethod (mr), FormatMethod (method), instr.Previous, instr.Previous.OpCode.StackBehaviourPop, instr.Previous.OpCode.StackBehaviourPush)); + continue; + } + + if (ldstr.OpCode != OpCodes.Ldstr) { + // Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255, method, "Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. Expected 'ldstr' opcode, got '{2}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new.", FormatMethod (mr), FormatMethod (method), ldstr)); + continue; + } + if (ldstr.Operand is not string symbolName) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + + if (!InlineSymbol (symbolName)) + continue; + + switch (mr.Name) { + // primitive types + case "SetSByte": + case "SetByte": + case "SetInt16": + case "SetUInt16": + case "SetInt32": + case "SetUInt32": + case "SetInt64": + case "SetUInt64": + case "SetArray": + case "SetObject": + case "SetNInt": + case "SetNUInt": + case "SetNFloat": + case "SetUIntPtr": + case "SetIntPtr": + case "SetCGSize": + case "SetDouble": + case "SetFloat": + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateSetNativeFieldMethod (method, mr.Parameters [2].ParameterType, symbolName); + + modified = true; + continue; + // classes + case "SetString": + if (mr.Parameters [2].ParameterType.FullName == "System.String") { + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateSetNativeStringMethod (method, symbolName); + modified = true; + continue; + } else if (mr.Parameters [2].ParameterType.FullName == "Foundation.NSString") { + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + instr.OpCode = OpCodes.Call; + instr.Operand = GetOrCreateSetNativeFieldMethod (method, mr.Parameters [2].ParameterType, symbolName); + modified = true; + continue; + } + + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + case "CachePointer": + if (!(mr.Parameters [2].ParameterType is PointerType pt && pt.ElementType.FullName == "System.IntPtr")) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + + // + // we're going to replace the entire method body with something like: + // + // var ptr = Get__{symbolName} (); + // if (ptr == IntPtr.Zero) + // return IntPtr.Zero; + // return *(IntPtr *) ptr; + // + + if (!IsGeneratedCachePointerMethod (method, out var cachePointerSymbolName, out var failureMessage)) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2257 /* Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2257, failureMessage, FormatMethod (method))); + continue; + } + + if (cachePointerSymbolName != symbolName) { + Report (ErrorHelper.CreateWarning (Configuration.Application, 2257 /* Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2257, $"Could not determine symbol name", FormatMethod (method))); + continue; + } + + ldstr.OpCode = OpCodes.Pop; // just pop the library handle/name, we don't need it + ldstr.Operand = null; + + method.Body.Instructions.Clear (); + var il = method.Body.GetILProcessor (); + var ptrVariable = new VariableDefinition (abr.System_IntPtr); + method.Body.Variables.Add (ptrVariable); + var loadPointerInstructionStart = il.Create (OpCodes.Ldloc, ptrVariable); + // var ptr = Get__{symbolName} () + il.Append (il.Create (OpCodes.Call, GetOrCreateGetSymbolMethod (method, symbolName))); + il.Append (il.Create (OpCodes.Stloc, ptrVariable)); + // if (ptr == IntPtr.Zero) + il.Append (il.Create (OpCodes.Ldloc, ptrVariable)); + il.Append (il.Create (OpCodes.Brtrue_S, loadPointerInstructionStart)); + // return IntPtr.Zero; + il.Append (il.Create (OpCodes.Ldc_I4_0)); + il.Append (il.Create (OpCodes.Conv_I)); + il.Append (il.Create (OpCodes.Ret)); + // return *(IntPtr *) ptr; + il.Append (loadPointerInstructionStart); // il.Create (OpCodes.Ldloc, ptrVariable) + il.Append (il.Create (OpCodes.Ldind_I)); + il.Append (il.Create (OpCodes.Ret)); + + modified = true; + return modified; // we replace the whole method body, so no need to continue processing the method + } + } + + switch (mr.Name) { + case "_dlopen": // nothing to inline here + case "dlopen": // nothing to inline here + case "dlerror": // nothing to inline here + continue; + case "dlclose": + // It might be possible to just remove these calls, because + // (PENDING CONFIRMATION) I believe dlclose is a no-op on at least some Apple platforms. + continue; + default: + Report (ErrorHelper.CreateWarning (Configuration.Application, 2255 /* Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. */, method, Errors.MX2255, FormatMethod (mr), FormatMethod (method))); + continue; + } + } + + return modified; + } + + static bool IsGeneratedCachePointerMethod (MethodDefinition method, [NotNullWhen (true)] out string? fieldName, [NotNullWhen (false)] out string? failureMessage) + { + fieldName = null; + failureMessage = null; + + // The following code: + // + // get { + // fixed (IntPtr *storage = &values [8]) + // return Dlfcn.CachePointer (Libraries.XYZ.Handle, "...", storage); + // } + // + // has the following IL sequence: + // + // IL_0000: ldsfld System.IntPtr[] ::values + // IL_0005: ldc.i4.0 + // IL_0006: ldelema System.IntPtr + // IL_000b: stloc.1 + // IL_000c: ldloc.1 + // IL_000d: conv.u + // IL_000e: stloc.0 + // IL_000f: ldsfld System.IntPtr ObjCRuntime.Libraries/::Handle + // IL_0014: ldstr "FIELDNAME" + // IL_0019: ldloc.0 + // IL_001a: call System.IntPtr ObjCRuntime.Dlfcn::CachePointer(System.IntPtr,System.String,System.IntPtr*) + // IL_0020: stloc.2 + // IL_0021: br.s IL_0023 + // IL_0023: ldloc.2 + // IL_001f: ret + // + // (the indented code can happen for debug builds) + // + if (!method.HasBody) { + failureMessage = "Method has no body"; + return false; + } + var body = method.Body; + if (body.Instructions.Count == 0) { + failureMessage = "Method has no instructions"; + return false; + } + + var instr = body.Instructions.First (); + var isLast = false; + + bool AssertOpCode ([NotNullWhen (false)] out string? failureMessage, params OpCode [] expected) + { + failureMessage = null; + + while (instr.OpCode == OpCodes.Nop && instr.Next is not null) + instr = instr.Next; + + if (!expected.Any (v => v == instr.OpCode)) { + failureMessage = $"Expected any of '{string.Join (", ", expected.Select (v => v.ToString ()))}' as instruction at offset IL{instr.Offset:X4}, got: {instr}"; + return false; + } + + if (instr.Next is null) { + if (isLast) + return true; + failureMessage = $"Expected more instructions after {instr}."; + return false; + } + + if (isLast) { + failureMessage = $"Got more instructions than expected after {instr}."; + return false; + } + + instr = instr.Next; + + return true; + } + + if (!AssertOpCode (out failureMessage, OpCodes.Ldsfld)) + return false; + + var ldcOpcodes = new OpCode [] { OpCodes.Ldc_I4_0, OpCodes.Ldc_I4_1, OpCodes.Ldc_I4_2, OpCodes.Ldc_I4_3, OpCodes.Ldc_I4_4, OpCodes.Ldc_I4_5, OpCodes.Ldc_I4_6, OpCodes.Ldc_I4_7, OpCodes.Ldc_I4_8, OpCodes.Ldc_I4, OpCodes.Ldc_I4_S }; + if (!AssertOpCode (out failureMessage, ldcOpcodes)) + return false; + + if (!AssertOpCode (out failureMessage, OpCodes.Ldelema)) + return false; + + var stlocOpcodes = new OpCode [] { OpCodes.Stloc_0, OpCodes.Stloc_1, OpCodes.Stloc_2, OpCodes.Stloc_3, OpCodes.Stloc, OpCodes.Stloc_S }; + if (!AssertOpCode (out failureMessage, stlocOpcodes)) + return false; + + var ldlocOpcodes = new OpCode [] { OpCodes.Ldloc_0, OpCodes.Ldloc_1, OpCodes.Ldloc_2, OpCodes.Ldloc_3, OpCodes.Ldloc, OpCodes.Ldloc_S }; + if (!AssertOpCode (out failureMessage, ldlocOpcodes)) + return false; + + if (!AssertOpCode (out failureMessage, OpCodes.Conv_U)) + return false; + + if (!AssertOpCode (out failureMessage, stlocOpcodes)) + return false; + + if (!AssertOpCode (out failureMessage, OpCodes.Ldsfld)) + return false; + + if (!AssertOpCode (out failureMessage, OpCodes.Ldstr)) + return false; + fieldName = (string) instr.Previous.Operand; + + if (!AssertOpCode (out failureMessage, ldlocOpcodes)) + return false; + + if (!AssertOpCode (out failureMessage, OpCodes.Call)) + return false; + + if (stlocOpcodes.Any (v => v == instr.OpCode)) { + if (!AssertOpCode (out failureMessage, stlocOpcodes)) + return false; + + var branchOpcodes = new OpCode [] { OpCodes.Br, OpCodes.Br_S }; + if (!AssertOpCode (out failureMessage, branchOpcodes)) + return false; + + if (!AssertOpCode (out failureMessage, ldlocOpcodes)) + return false; + } + + isLast = true; + return AssertOpCode (out failureMessage, OpCodes.Ret); + } + + static string FormatMethod (MethodReference method) + { + var rv = method.FullName; + var idx = rv.IndexOf (' '); + if (idx > 0) + rv = rv.Substring (idx + 1); + return rv; + } + + static bool IsNSObjectSubclass (TypeReference type) + { + var resolved = type.Resolve (); + while (resolved is not null) { + if (resolved.FullName == "Foundation.NSObject") + return true; + if (resolved.BaseType is null) + break; + resolved = resolved.BaseType.Resolve (); + } + return false; + } +} diff --git a/tools/linker/MonoTouch.Tuner/ListExportedSymbols.cs b/tools/linker/MonoTouch.Tuner/ListExportedSymbols.cs index e014c12bc41c..eda79a994f73 100644 --- a/tools/linker/MonoTouch.Tuner/ListExportedSymbols.cs +++ b/tools/linker/MonoTouch.Tuner/ListExportedSymbols.cs @@ -191,6 +191,13 @@ bool ProcessMethod (MethodDefinition method) switch (pinfo.Module.Name) { case "__Internal": + // For NativeAOT builds, don't add inlined dlfcn P/Invoke wrappers as + // required symbols: only the surviving ones will have native code generated, + // so force-referencing all of them causes linker errors for symbols that + // NativeAOT trimmed away. For non-NativeAOT builds, the wrappers are resolved + // via dlsym and need the -u flags to be exported from the binary. + if (Configuration.InlineDlfcnMethodsEnabled && Configuration.Application.XamarinRuntime == XamarinRuntime.NativeAOT && pinfo.EntryPoint.StartsWith ("xamarin_Dlfcn_", StringComparison.Ordinal)) + break; Driver.Log (4, "Adding native reference to {0} in {1} because it's referenced by {2} in {3}.", pinfo.EntryPoint, pinfo.Module.Name, method.FullName, method.Module.Name); DerivedLinkContext.RequiredSymbols.AddFunction (pinfo.EntryPoint).AddMember (method); break; @@ -211,7 +218,7 @@ bool ProcessMethod (MethodDefinition method) } } - if (method.IsPropertyMethod ()) { + if (method.IsPropertyMethod () && !Configuration.InlineDlfcnMethodsEnabled) { var property = method.GetProperty (); // The Field attribute may have been linked away, but we've stored it in an annotation. if (property is not null && Annotations.GetCustomAnnotations ("ExportedFields").TryGetValue (property, out var symbol) && symbol is string symbolStr) { diff --git a/tools/linker/MonoTouch.Tuner/ProcessExportedFields.cs b/tools/linker/MonoTouch.Tuner/ProcessExportedFields.cs index 8e4a61ed2578..53787784589f 100644 --- a/tools/linker/MonoTouch.Tuner/ProcessExportedFields.cs +++ b/tools/linker/MonoTouch.Tuner/ProcessExportedFields.cs @@ -23,6 +23,8 @@ namespace MonoTouch.Tuner { // Then at the end of the linker process (ListExportedSymbols step) // we lookup that annotation. // + // See docs/code/native-symbols.md for an overview of native symbol handling. + // public class ProcessExportedFields : BaseStep { protected override void ProcessAssembly (AssemblyDefinition assembly) @@ -55,6 +57,15 @@ void ProcessProperty (PropertyDefinition property) if (!property.HasCustomAttributes) return; + var config = LinkerConfiguration.GetInstance (Context); + + // Collect all [Field] symbol names for InlineDlfcnMethodsStep's compatibility mode. + if (config.InlineDlfcnMethodsEnabled) { + var allSymbol = GetFieldSymbolName (property); + if (allSymbol is not null) + config.FieldSymbols.Add (allSymbol); + } + var symbol = GetFieldSymbol (property); if (symbol is null) return; @@ -62,6 +73,28 @@ void ProcessProperty (PropertyDefinition property) Annotations.GetCustomAnnotations ("ExportedFields").Add (property, symbol); } + // Returns the symbol name from a [Field] attribute, regardless of library. + internal static string? GetFieldSymbolName (PropertyDefinition property) + { + if (!property.HasCustomAttributes) + return null; + + foreach (var attrib in property.CustomAttributes) { + var declaringType = attrib.Constructor.DeclaringType.Resolve (); + + if (!declaringType.Is (Namespaces.Foundation, "FieldAttribute")) + continue; + + if (attrib.ConstructorArguments.Count < 1) + continue; + + return (string) attrib.ConstructorArguments [0].Value; + } + + return null; + } + + // Returns the symbol name only for __Internal fields. internal static string? GetFieldSymbol (PropertyDefinition property) { if (!property.HasCustomAttributes) diff --git a/tools/mtouch/Errors.designer.cs b/tools/mtouch/Errors.designer.cs index e2f24503e42d..85e5fd3a6293 100644 --- a/tools/mtouch/Errors.designer.cs +++ b/tools/mtouch/Errors.designer.cs @@ -3524,6 +3524,42 @@ public static string MX2112_B { } } + /// + /// Looks up a localized string similar to Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new. + /// + public static string MX2254 { + get { + return ResourceManager.GetString("MX2254", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. + /// + public static string MX2255 { + get { + return ResourceManager.GetString("MX2255", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new. + /// + public static string MX2256 { + get { + return ResourceManager.GetString("MX2256", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new. + /// + public static string MX2257 { + get { + return ResourceManager.GetString("MX2257", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not {0} the assembly '{1}'. /// diff --git a/tools/mtouch/Errors.resx b/tools/mtouch/Errors.resx index 83c238026906..f719755a4d48 100644 --- a/tools/mtouch/Errors.resx +++ b/tools/mtouch/Errors.resx @@ -1097,6 +1097,24 @@ + + + + Unsupported primitive field type '{0}' for symbol '{1}' in method '{2}'. Sub-optimal but functional code will be generated. Please file an issue at https://github.com/dotnet/macios/issues/new + + + + Unknown or unsupported Dlfcn pattern: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + + + + The field type '{0}' for symbol '{1}' in method '{2}' is not an NSObject subclass. Please file an issue at https://github.com/dotnet/macios/issues/new + + + + Unknown IL sequence for method with call to Dlfcn.CachePointer: '{0}' in method '{1}'. The call will not be inlined. Please file an issue at https://github.com/dotnet/macios/issues/new + +