mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-20 02:55:38 +08:00
@@ -1,4 +1,4 @@
|
||||
name: Deploy Docs
|
||||
name: deploy-docs
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_and_deploy:
|
||||
deploy-to-azure:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build and Deploy Job
|
||||
steps:
|
||||
69
.github/workflows/dev-build.yml
vendored
Normal file
69
.github/workflows/dev-build.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# <auto-generated>
|
||||
#
|
||||
# This code was generated.
|
||||
#
|
||||
# - To turn off auto-generation set:
|
||||
#
|
||||
# [GitHubActions (AutoGenerate = false)]
|
||||
#
|
||||
# - To trigger manual generation invoke:
|
||||
#
|
||||
# nuke --generate-configuration GitHubActions_dev-build --host GitHubActions
|
||||
#
|
||||
# </auto-generated>
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
name: dev-build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
paths:
|
||||
- 'src/MeoAssistant/**'
|
||||
- 'src/MeoAssistantBuilder/**'
|
||||
- 'src/MeoAsstGui/**'
|
||||
- '3rdparty/**'
|
||||
- 'include/**'
|
||||
- 'resource/**'
|
||||
- MeoAssistantArknights.sln
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- 'src/MeoAssistant/**'
|
||||
- 'src/MeoAssistantBuilder/**'
|
||||
- 'src/MeoAsstGui/**'
|
||||
- '3rdparty/**'
|
||||
- 'include/**'
|
||||
- 'resource/**'
|
||||
- MeoAssistantArknights.sln
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
Reason:
|
||||
description: "Reason"
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
windows-latest:
|
||||
name: windows-latest
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Cache .nuke/temp, ~/.nuget/packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.nuke/temp
|
||||
~/.nuget/packages
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }}
|
||||
- name: Run './build.cmd DevBuild'
|
||||
run: ./build.cmd DevBuild
|
||||
env:
|
||||
Reason: ${{ github.event.inputs.Reason }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: artifacts
|
||||
path: artifacts
|
||||
61
.github/workflows/maa-dev-build.yaml
vendored
61
.github/workflows/maa-dev-build.yaml
vendored
@@ -1,61 +0,0 @@
|
||||
name: "Maa Dev Build"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- src/MeoAssistant/**
|
||||
- src/MeoAssistantBuilder/**
|
||||
- src/MeoAsstGui/**
|
||||
- 3rdparty/**
|
||||
- include/**
|
||||
- MeoAssistantArknights.sln
|
||||
pull_request:
|
||||
paths:
|
||||
- src/MeoAssistant/**
|
||||
- src/MeoAssistantBuilder/**
|
||||
- src/MeoAsstGui/**
|
||||
- 3rdparty/**
|
||||
- include/**
|
||||
- MeoAssistantArknights.sln
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Run dev build task
|
||||
run: pwsh .\build.ps1 DevBuild
|
||||
|
||||
- name: Read file name
|
||||
id: read_path
|
||||
run: pwsh .\read_path.ps1 ./artifacts MaaBundle*
|
||||
|
||||
- name: Upload Artifacts 0
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.read_path.outputs.name_0 }}
|
||||
path: ${{ steps.read_path.outputs.path_0 }}
|
||||
|
||||
- name: Upload Artifacts 1
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.read_path.outputs.name_1 }}
|
||||
path: ${{ steps.read_path.outputs.path_1 }}
|
||||
|
||||
- name: Upload Artifacts 2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.read_path.outputs.name_2 }}
|
||||
path: ${{ steps.read_path.outputs.path_2 }}
|
||||
45
.github/workflows/maa-release-bundle.yaml
vendored
45
.github/workflows/maa-release-bundle.yaml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Release MaaBundle
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
|
||||
release-bundle:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
|
||||
- name: Setup .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Run release core task
|
||||
run: pwsh .\build.ps1 ReleaseBundle
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: MaaBundle-${{ steps.tag.outputs.tag }}
|
||||
path: ./artifacts/MaaBundle*
|
||||
|
||||
- name: Upload release assets
|
||||
uses: xresloader/upload-to-github-release@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
file: ./artifacts/MaaBundle*
|
||||
tags: true
|
||||
draft: false
|
||||
verbose: true
|
||||
45
.github/workflows/maa-release-core.yaml
vendored
45
.github/workflows/maa-release-core.yaml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Release MaaCore
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
|
||||
release-core:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get tag
|
||||
id: tag
|
||||
uses: dawidd6/action-get-tag@v1
|
||||
|
||||
- name: Setup .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Run release core task
|
||||
run: pwsh .\build.ps1 ReleaseCore
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: MaaCore-${{ steps.tag.outputs.tag }}
|
||||
path: ./artifacts/MaaCore*
|
||||
|
||||
- name: Upload release assets
|
||||
uses: xresloader/upload-to-github-release@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
file: ./artifacts/MaaCore*
|
||||
tags: true
|
||||
draft: false
|
||||
verbose: true
|
||||
39
.github/workflows/maa-release-resource.yaml
vendored
39
.github/workflows/maa-release-resource.yaml
vendored
@@ -1,39 +0,0 @@
|
||||
name: Release MaaResource
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- resource/**
|
||||
- 3rdparty/resource/**
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
release-resource:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Run release resource task
|
||||
run: pwsh .\build.ps1 ReleaseResource
|
||||
|
||||
- name: Read file name
|
||||
id: read_path
|
||||
run: pwsh .\read_path.ps1 ./artifacts MaaResource*
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.read_path.outputs.name_0 }}
|
||||
path: ${{ steps.read_path.outputs.path_0 }}
|
||||
38
.github/workflows/maa-release-wpf.yaml
vendored
38
.github/workflows/maa-release-wpf.yaml
vendored
@@ -1,38 +0,0 @@
|
||||
name: Release MaaWpf
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- src/MeoAsstGui/**
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
release-wpf:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET 6.0.x
|
||||
uses: actions/setup-dotnet@v2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
- name: Run release wpf task
|
||||
run: pwsh .\build.ps1 ReleaseWpf
|
||||
|
||||
- name: Read file name
|
||||
id: read_path
|
||||
run: pwsh .\read_path.ps1 ./artifacts MaaWpf*
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.read_path.outputs.name_0 }}
|
||||
path: ${{ steps.read_path.outputs.path_0 }}
|
||||
48
.github/workflows/release-maa-resource.yml
vendored
Normal file
48
.github/workflows/release-maa-resource.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# <auto-generated>
|
||||
#
|
||||
# This code was generated.
|
||||
#
|
||||
# - To turn off auto-generation set:
|
||||
#
|
||||
# [GitHubActions (AutoGenerate = false)]
|
||||
#
|
||||
# - To trigger manual generation invoke:
|
||||
#
|
||||
# nuke --generate-configuration GitHubActions_release-maa-resource --host GitHubActions
|
||||
#
|
||||
# </auto-generated>
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
name: release-maa-resource
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'resource/**'
|
||||
- '3rdparty/resource/**'
|
||||
|
||||
jobs:
|
||||
windows-latest:
|
||||
name: windows-latest
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Cache .nuke/temp, ~/.nuget/packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.nuke/temp
|
||||
~/.nuget/packages
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }}
|
||||
- name: Run './build.cmd ReleaseMaaResource'
|
||||
run: ./build.cmd ReleaseMaaResource
|
||||
env:
|
||||
PUBLISH_GH_PAT: ${{ secrets.PUBLISH_GH_PAT }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: artifacts
|
||||
path: artifacts
|
||||
45
.github/workflows/release-maa.yml
vendored
Normal file
45
.github/workflows/release-maa.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# <auto-generated>
|
||||
#
|
||||
# This code was generated.
|
||||
#
|
||||
# - To turn off auto-generation set:
|
||||
#
|
||||
# [GitHubActions (AutoGenerate = false)]
|
||||
#
|
||||
# - To trigger manual generation invoke:
|
||||
#
|
||||
# nuke --generate-configuration GitHubActions_release-maa --host GitHubActions
|
||||
#
|
||||
# </auto-generated>
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
name: release-maa
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
windows-latest:
|
||||
name: windows-latest
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Cache .nuke/temp, ~/.nuget/packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
.nuke/temp
|
||||
~/.nuget/packages
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }}
|
||||
- name: Run './build.cmd ReleaseMaa'
|
||||
run: ./build.cmd ReleaseMaa
|
||||
env:
|
||||
PUBLISH_GH_PAT: ${{ secrets.PUBLISH_GH_PAT }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: artifacts
|
||||
path: artifacts
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -437,3 +437,6 @@ tools/**/*.png
|
||||
resource/infrast
|
||||
.vscode
|
||||
!3rdparty/tools/*
|
||||
|
||||
# Nuke
|
||||
.nuke/temp/*
|
||||
|
||||
145
.nuke/build.schema.json
Normal file
145
.nuke/build.schema.json
Normal file
@@ -0,0 +1,145 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Build Schema",
|
||||
"$ref": "#/definitions/build",
|
||||
"definitions": {
|
||||
"build": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Continue": {
|
||||
"type": "boolean",
|
||||
"description": "Indicates to continue a previously failed build attempt"
|
||||
},
|
||||
"Help": {
|
||||
"type": "boolean",
|
||||
"description": "Shows the help text for this build assembly"
|
||||
},
|
||||
"Host": {
|
||||
"type": "string",
|
||||
"description": "Host for execution. Default is 'automatic'",
|
||||
"enum": [
|
||||
"AppVeyor",
|
||||
"AzurePipelines",
|
||||
"Bamboo",
|
||||
"Bitrise",
|
||||
"GitHubActions",
|
||||
"GitLab",
|
||||
"Jenkins",
|
||||
"Rider",
|
||||
"SpaceAutomation",
|
||||
"TeamCity",
|
||||
"Terminal",
|
||||
"TravisCI",
|
||||
"VisualStudio",
|
||||
"VSCode"
|
||||
]
|
||||
},
|
||||
"NoLogo": {
|
||||
"type": "boolean",
|
||||
"description": "Disables displaying the NUKE logo"
|
||||
},
|
||||
"Partition": {
|
||||
"type": "string",
|
||||
"description": "Partition to use on CI"
|
||||
},
|
||||
"Plan": {
|
||||
"type": "boolean",
|
||||
"description": "Shows the execution plan (HTML)"
|
||||
},
|
||||
"Profile": {
|
||||
"type": "array",
|
||||
"description": "Defines the profiles to load",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"Root": {
|
||||
"type": "string",
|
||||
"description": "Root directory during build execution"
|
||||
},
|
||||
"Skip": {
|
||||
"type": "array",
|
||||
"description": "List of targets to be skipped. Empty list skips all dependencies",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Clean",
|
||||
"Default",
|
||||
"DevBuild",
|
||||
"ReleaseMaa",
|
||||
"ReleaseMaaCore",
|
||||
"ReleaseMaaResource",
|
||||
"SetMaaChangeLog",
|
||||
"SetPackageBundled",
|
||||
"SetVersion",
|
||||
"UseCommitVersion",
|
||||
"UseMaaChangeLog",
|
||||
"UseMaaCore",
|
||||
"UseMaaDevBundle",
|
||||
"UseMaaLegacyBundle",
|
||||
"UseMaaResource",
|
||||
"UseMaaResourceChangeLog",
|
||||
"UsePublishArtifact",
|
||||
"UsePublishRelease",
|
||||
"UseTagVersion",
|
||||
"WithCompileCoreCICD",
|
||||
"WithCompileCoreDebug",
|
||||
"WithCompileCoreRelease",
|
||||
"WithCompileResourceRelease",
|
||||
"WithCompileWpfDebug",
|
||||
"WithCompileWpfRelease"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Solution": {
|
||||
"type": "string",
|
||||
"description": "Path to a solution file that is automatically loaded"
|
||||
},
|
||||
"Target": {
|
||||
"type": "array",
|
||||
"description": "List of targets to be invoked. Default is '{default_target}'",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Clean",
|
||||
"Default",
|
||||
"DevBuild",
|
||||
"ReleaseMaa",
|
||||
"ReleaseMaaCore",
|
||||
"ReleaseMaaResource",
|
||||
"SetMaaChangeLog",
|
||||
"SetPackageBundled",
|
||||
"SetVersion",
|
||||
"UseCommitVersion",
|
||||
"UseMaaChangeLog",
|
||||
"UseMaaCore",
|
||||
"UseMaaDevBundle",
|
||||
"UseMaaLegacyBundle",
|
||||
"UseMaaResource",
|
||||
"UseMaaResourceChangeLog",
|
||||
"UsePublishArtifact",
|
||||
"UsePublishRelease",
|
||||
"UseTagVersion",
|
||||
"WithCompileCoreCICD",
|
||||
"WithCompileCoreDebug",
|
||||
"WithCompileCoreRelease",
|
||||
"WithCompileResourceRelease",
|
||||
"WithCompileWpfDebug",
|
||||
"WithCompileWpfRelease"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Verbosity": {
|
||||
"type": "string",
|
||||
"description": "Logging verbosity during build execution. Default is 'Normal'",
|
||||
"enum": [
|
||||
"Minimal",
|
||||
"Normal",
|
||||
"Quiet",
|
||||
"Verbose"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4
.nuke/parameters.json
Normal file
4
.nuke/parameters.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "./build.schema.json",
|
||||
"Solution": "MeoAssistantArknights.sln"
|
||||
}
|
||||
2
CHANGELOG_MAA.md
Normal file
2
CHANGELOG_MAA.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- 这是 MaaCore 的更新日志
|
||||
- 这是用来测试的
|
||||
2
CHANGELOG_RES.md
Normal file
2
CHANGELOG_RES.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- MaaResource 的更新日志
|
||||
- 这是用来测试的
|
||||
@@ -29,49 +29,38 @@ EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
CICD|x64 = CICD|x64
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
RelWithDebInfo|x64 = RelWithDebInfo|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.CICD|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.CICD|x64.Build.0 = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Debug|x64.ActiveCfg = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Debug|x64.Build.0 = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.ActiveCfg = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.Build.0 = Release|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.CICD|x64.ActiveCfg = CICD|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.CICD|x64.Build.0 = CICD|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.Build.0 = RelWithDebInfo|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.CICD|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.CICD|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Debug|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Debug|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x64.ActiveCfg = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.Release|x64.Build.0 = Release|x64
|
||||
{093A3174-A27E-4D23-B64E-16F9448AD5AC}.RelWithDebInfo|x64.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.CICD|x64.ActiveCfg = CICD|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.CICD|x64.Build.0 = CICD|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.Build.0 = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.CICD|x64.ActiveCfg = Release|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.CICD|x64.Build.0 = Release|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.Debug|x64.Build.0 = Debug|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.Release|x64.ActiveCfg = Release|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.Release|x64.Build.0 = Release|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.RelWithDebInfo|x64.ActiveCfg = Release|x64
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.CICD|x64.ActiveCfg = Release|Any CPU
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.CICD|x64.Build.0 = Release|Any CPU
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8D9036DD-75F1-4BD0-89E2-DFB37B925DA3}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
7
build.cmd
Normal file
7
build.cmd
Normal file
@@ -0,0 +1,7 @@
|
||||
:; set -eo pipefail
|
||||
:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
|
||||
:; ${SCRIPT_DIR}/build.sh "$@"
|
||||
:; exit $?
|
||||
|
||||
@ECHO OFF
|
||||
powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
|
||||
73
build.ps1
73
build.ps1
@@ -1,16 +1,69 @@
|
||||
if ($args.Length -ne 1) {
|
||||
throw "One argument required"
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||
[string[]]$BuildArguments
|
||||
)
|
||||
|
||||
Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
|
||||
|
||||
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
|
||||
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
|
||||
###########################################################################
|
||||
# CONFIGURATION
|
||||
###########################################################################
|
||||
|
||||
$BuildProjectFile = "$PSScriptRoot\src\MeoAssistantBuilder\MeoAssistantBuilder.csproj"
|
||||
$TempDirectory = "$PSScriptRoot\\.nuke\temp"
|
||||
|
||||
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
|
||||
$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
|
||||
$DotNetChannel = "Current"
|
||||
|
||||
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
|
||||
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
|
||||
$env:DOTNET_MULTILEVEL_LOOKUP = 0
|
||||
|
||||
###########################################################################
|
||||
# EXECUTION
|
||||
###########################################################################
|
||||
|
||||
function ExecSafe([scriptblock] $cmd) {
|
||||
& $cmd
|
||||
if ($LASTEXITCODE) { exit $LASTEXITCODE }
|
||||
}
|
||||
|
||||
$target = $args[0]
|
||||
$valid_targets = @("ReleaseCore", "ReleaseWpf", "ReleaseResource", "ReleaseBundle", "DevBuild")
|
||||
# If dotnet CLI is installed globally and it matches requested version, use for execution
|
||||
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
|
||||
$(dotnet --version) -and $LASTEXITCODE -eq 0) {
|
||||
$env:DOTNET_EXE = (Get-Command "dotnet").Path
|
||||
}
|
||||
else {
|
||||
# Download install script
|
||||
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
|
||||
New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
|
||||
|
||||
if (!$valid_targets.Contains($target)) {
|
||||
throw "$target is not a valid target"
|
||||
# If global.json exists, load expected version
|
||||
if (Test-Path $DotNetGlobalFile) {
|
||||
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
|
||||
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
|
||||
$DotNetVersion = $DotNetGlobal.sdk.version
|
||||
}
|
||||
}
|
||||
|
||||
# Install by channel or version
|
||||
$DotNetDirectory = "$TempDirectory\dotnet-win"
|
||||
if (!(Test-Path variable:DotNetVersion)) {
|
||||
ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
|
||||
} else {
|
||||
ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
|
||||
}
|
||||
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
|
||||
}
|
||||
|
||||
Set-Location -Path .\src\MeoAssistantBuilder
|
||||
Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"
|
||||
|
||||
dotnet run -- --target $target
|
||||
|
||||
Set-Location -Path ..\..\
|
||||
ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
|
||||
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
|
||||
|
||||
62
build.sh
Normal file
62
build.sh
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
bash --version 2>&1 | head -n 1
|
||||
|
||||
set -eo pipefail
|
||||
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
|
||||
|
||||
###########################################################################
|
||||
# CONFIGURATION
|
||||
###########################################################################
|
||||
|
||||
BUILD_PROJECT_FILE="$SCRIPT_DIR/src/MeoAssistantBuilder/MeoAssistantBuilder.csproj"
|
||||
TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
|
||||
|
||||
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
|
||||
DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
|
||||
DOTNET_CHANNEL="Current"
|
||||
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
|
||||
export DOTNET_MULTILEVEL_LOOKUP=0
|
||||
|
||||
###########################################################################
|
||||
# EXECUTION
|
||||
###########################################################################
|
||||
|
||||
function FirstJsonValue {
|
||||
perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
|
||||
}
|
||||
|
||||
# If dotnet CLI is installed globally and it matches requested version, use for execution
|
||||
if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
|
||||
export DOTNET_EXE="$(command -v dotnet)"
|
||||
else
|
||||
# Download install script
|
||||
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
|
||||
mkdir -p "$TEMP_DIRECTORY"
|
||||
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
|
||||
chmod +x "$DOTNET_INSTALL_FILE"
|
||||
|
||||
# If global.json exists, load expected version
|
||||
if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
|
||||
DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
|
||||
if [[ "$DOTNET_VERSION" == "" ]]; then
|
||||
unset DOTNET_VERSION
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install by channel or version
|
||||
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
|
||||
if [[ -z ${DOTNET_VERSION+x} ]]; then
|
||||
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
|
||||
else
|
||||
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
|
||||
fi
|
||||
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
|
||||
fi
|
||||
|
||||
echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
|
||||
|
||||
"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
|
||||
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
|
||||
@@ -1,212 +1,212 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "maa task config",
|
||||
"patternProperties": {
|
||||
"^(?!\\$)": {
|
||||
"type": "object",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/JustReturnTask"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MatchTemplateTask"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/OcrDetectTask"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/HashTask"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Rectangle": {
|
||||
"type": "array",
|
||||
"maxItems": 4,
|
||||
"minItems": 4,
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"TaskNameList": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "要执行的任务"
|
||||
}
|
||||
},
|
||||
"BaseTask": {
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "算法类型"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "ClickSelf|ClickRand|DoNothing|Stop|ClickRect|SwipeToTheLeft|SwipeToTheRight",
|
||||
"default": "DoNothing",
|
||||
"description": "可选项,表示识别到后的动作\n不填写时默认为 DoNothing"
|
||||
},
|
||||
"next": {
|
||||
"$ref": "#/definitions/TaskNameList",
|
||||
"description": "可选项,表示执行完当前任务后,下一个要执行的任务\n会从前往后依次去识别,去执行第一个匹配上的\n不填写默认执行完当前任务直接停止"
|
||||
},
|
||||
"maxTimes": {
|
||||
"type": "number",
|
||||
"description": "可选项,表示该任务最大执行次数\n不填写时默认无穷大\n达到最大次数后,若存在 exceededNext 字段,则执行 exceededNext;否则直接任务停止"
|
||||
},
|
||||
"exceededNext": {
|
||||
"$ref": "#/definitions/TaskNameList",
|
||||
"description": "可选项,表示达到了最大执行次数后要执行的任务\n不填写时,达到了最大执行次数则停止;填写后就执行这里的,而不是 next 里的"
|
||||
},
|
||||
"preDelay": {
|
||||
"type": "number",
|
||||
"description": "可选项,表示识别到后延迟多久才执行 action,单位毫秒;不填写时默认 0"
|
||||
},
|
||||
"rearDelay": {
|
||||
"type": "number",
|
||||
"description": "可选项,表示 action 执行完后延迟多久才去识别 next, 单位毫秒;不填写时默认 0"
|
||||
},
|
||||
"roi": {
|
||||
"$ref": "#/definitions/Rectangle",
|
||||
"description": "可选项,表示识别的范围,格式为 [ x, y, width, height ]\n以 1280 * 720 为基准自动缩放;不填写时默认 [ 0, 0, 1280, 720 ]\n尽量填写,减小识别范围可以减少性能消耗,加快识别速度"
|
||||
},
|
||||
"cache": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "可选项,表示该任务是否使用缓存,默认为 true;\n第一次识别到后,以后永远只在第一次识别到的位置进行识别,开启可大幅节省性能\n但仅适用于待识别目标位置完全不会变的任务,若待识别目标位置会变请设为 false"
|
||||
},
|
||||
"rectMove": {
|
||||
"$ref": "#/definitions/Rectangle",
|
||||
"description": "可选项,识别后的目标移动,不建议使用该选项。以 1280 * 720 为基准自动缩放\n例如识别到了 A 图标,但实际要点击的是 A 图标旁边的某个位置,则进行移动后再点击。可以的话尽量直接识别要点击的位置,不建议使用该选项"
|
||||
},
|
||||
"reduceOtherTimes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "要执行的任务"
|
||||
},
|
||||
"description": "可选项,执行后减少其他任务的执行计数。\n可选项,执行后减少其他任务的执行计数。"
|
||||
},
|
||||
"specificRect": {
|
||||
"$ref": "#/definitions/Rectangle",
|
||||
"description": "仅当 action 为 ClickRect 时有效且必选,表示指定的点击位置(范围内随机一点)。以 1280 * 720 为基准自动缩放"
|
||||
}
|
||||
}
|
||||
},
|
||||
"JustReturnTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "JustReturn"
|
||||
}
|
||||
},
|
||||
"description": "不进行识别,直接执行 action",
|
||||
"required": [
|
||||
"algorithm"
|
||||
]
|
||||
},
|
||||
"MatchTemplateTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "MatchTemplate"
|
||||
},
|
||||
"template": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "可选项,要匹配的图片文件名\n不填时写默认 \"任务名.png\""
|
||||
},
|
||||
"templThreshold": {
|
||||
"type": "number",
|
||||
"default": 0.8,
|
||||
"description": "可选项,图片模板匹配得分的阈值,超过阈值才认为识别到了。\n默认 0.8, 可根据日志查看实际得分是多少"
|
||||
},
|
||||
"maskRange": {
|
||||
"type": "array",
|
||||
"maxItems": 2,
|
||||
"minimum": 2,
|
||||
"items": {
|
||||
"type": "number"
|
||||
},
|
||||
"default": [
|
||||
1,
|
||||
255
|
||||
],
|
||||
"description": "可选项,灰度掩码范围。例如将图片不需要识别的部分涂成黑色(灰度值为 0),然后设置 [ 1, 255 ], 匹配的时候即刻忽略涂黑的部分"
|
||||
}
|
||||
},
|
||||
"description": "匹配图片"
|
||||
},
|
||||
"OcrDetectTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "OcrDetect"
|
||||
},
|
||||
"text": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "必选项,要识别的文字内容,只要任一匹配上了即认为识别到了"
|
||||
},
|
||||
"fullMatch": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "可选项,文字识别是否需要全字匹配(不能多字),默认为 false\nfalse 时只要是子串即可:例如 text: [ \"开始\" ],实际识别到了 \"开始行动\",也算识别成功;\ntrue 时则必须识别到了 \"开始\",多一个字都不行"
|
||||
},
|
||||
"ocrReplace": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "可选项,针对常见识别错的文字进行替换(支持正则)"
|
||||
}
|
||||
},
|
||||
"description": "文字识别",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"HashTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "Hash"
|
||||
}
|
||||
},
|
||||
"description": "哈希计算",
|
||||
"required": [
|
||||
"algorithm"
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "maa task config",
|
||||
"patternProperties": {
|
||||
"^(?!\\$)": {
|
||||
"type": "object",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/JustReturnTask"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/MatchTemplateTask"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/OcrDetectTask"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/HashTask"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Rectangle": {
|
||||
"type": "array",
|
||||
"maxItems": 4,
|
||||
"minItems": 4,
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"TaskNameList": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "要执行的任务"
|
||||
}
|
||||
},
|
||||
"BaseTask": {
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"description": "算法类型"
|
||||
},
|
||||
"action": {
|
||||
"type": "string",
|
||||
"pattern": "ClickSelf|ClickRand|DoNothing|Stop|ClickRect|SwipeToTheLeft|SwipeToTheRight",
|
||||
"default": "DoNothing",
|
||||
"description": "可选项,表示识别到后的动作\n不填写时默认为 DoNothing"
|
||||
},
|
||||
"next": {
|
||||
"$ref": "#/definitions/TaskNameList",
|
||||
"description": "可选项,表示执行完当前任务后,下一个要执行的任务\n会从前往后依次去识别,去执行第一个匹配上的\n不填写默认执行完当前任务直接停止"
|
||||
},
|
||||
"maxTimes": {
|
||||
"type": "number",
|
||||
"description": "可选项,表示该任务最大执行次数\n不填写时默认无穷大\n达到最大次数后,若存在 exceededNext 字段,则执行 exceededNext;否则直接任务停止"
|
||||
},
|
||||
"exceededNext": {
|
||||
"$ref": "#/definitions/TaskNameList",
|
||||
"description": "可选项,表示达到了最大执行次数后要执行的任务\n不填写时,达到了最大执行次数则停止;填写后就执行这里的,而不是 next 里的"
|
||||
},
|
||||
"preDelay": {
|
||||
"type": "number",
|
||||
"description": "可选项,表示识别到后延迟多久才执行 action,单位毫秒;不填写时默认 0"
|
||||
},
|
||||
"rearDelay": {
|
||||
"type": "number",
|
||||
"description": "可选项,表示 action 执行完后延迟多久才去识别 next, 单位毫秒;不填写时默认 0"
|
||||
},
|
||||
"roi": {
|
||||
"$ref": "#/definitions/Rectangle",
|
||||
"description": "可选项,表示识别的范围,格式为 [ x, y, width, height ]\n以 1280 * 720 为基准自动缩放;不填写时默认 [ 0, 0, 1280, 720 ]\n尽量填写,减小识别范围可以减少性能消耗,加快识别速度"
|
||||
},
|
||||
"cache": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "可选项,表示该任务是否使用缓存,默认为 true;\n第一次识别到后,以后永远只在第一次识别到的位置进行识别,开启可大幅节省性能\n但仅适用于待识别目标位置完全不会变的任务,若待识别目标位置会变请设为 false"
|
||||
},
|
||||
"rectMove": {
|
||||
"$ref": "#/definitions/Rectangle",
|
||||
"description": "可选项,识别后的目标移动,不建议使用该选项。以 1280 * 720 为基准自动缩放\n例如识别到了 A 图标,但实际要点击的是 A 图标旁边的某个位置,则进行移动后再点击。可以的话尽量直接识别要点击的位置,不建议使用该选项"
|
||||
},
|
||||
"reduceOtherTimes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "要执行的任务"
|
||||
},
|
||||
"description": "可选项,执行后减少其他任务的执行计数。\n可选项,执行后减少其他任务的执行计数。"
|
||||
},
|
||||
"specificRect": {
|
||||
"$ref": "#/definitions/Rectangle",
|
||||
"description": "仅当 action 为 ClickRect 时有效且必选,表示指定的点击位置(范围内随机一点)。以 1280 * 720 为基准自动缩放"
|
||||
}
|
||||
}
|
||||
},
|
||||
"JustReturnTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "JustReturn"
|
||||
}
|
||||
},
|
||||
"description": "不进行识别,直接执行 action",
|
||||
"required": [
|
||||
"algorithm"
|
||||
]
|
||||
},
|
||||
"MatchTemplateTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "MatchTemplate"
|
||||
},
|
||||
"template": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "可选项,要匹配的图片文件名\n不填时写默认 \"任务名.png\""
|
||||
},
|
||||
"templThreshold": {
|
||||
"type": "number",
|
||||
"default": 0.8,
|
||||
"description": "可选项,图片模板匹配得分的阈值,超过阈值才认为识别到了。\n默认 0.8, 可根据日志查看实际得分是多少"
|
||||
},
|
||||
"maskRange": {
|
||||
"type": "array",
|
||||
"maxItems": 2,
|
||||
"minimum": 2,
|
||||
"items": {
|
||||
"type": "number"
|
||||
},
|
||||
"default": [
|
||||
1,
|
||||
255
|
||||
],
|
||||
"description": "可选项,灰度掩码范围。例如将图片不需要识别的部分涂成黑色(灰度值为 0),然后设置 [ 1, 255 ], 匹配的时候即刻忽略涂黑的部分"
|
||||
}
|
||||
},
|
||||
"description": "匹配图片"
|
||||
},
|
||||
"OcrDetectTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "OcrDetect"
|
||||
},
|
||||
"text": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "必选项,要识别的文字内容,只要任一匹配上了即认为识别到了"
|
||||
},
|
||||
"fullMatch": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "可选项,文字识别是否需要全字匹配(不能多字),默认为 false\nfalse 时只要是子串即可:例如 text: [ \"开始\" ],实际识别到了 \"开始行动\",也算识别成功;\ntrue 时则必须识别到了 \"开始\",多一个字都不行"
|
||||
},
|
||||
"ocrReplace": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "可选项,针对常见识别错的文字进行替换(支持正则)"
|
||||
}
|
||||
},
|
||||
"description": "文字识别",
|
||||
"required": [
|
||||
"algorithm",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"HashTask": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BaseTask"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"pattern": "Hash"
|
||||
}
|
||||
},
|
||||
"description": "哈希计算",
|
||||
"required": [
|
||||
"algorithm"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
if ($args.Length -ne 2) {
|
||||
throw "Need two arguments"
|
||||
}
|
||||
|
||||
$fs = Get-ChildItem -Path $args[0] -Filter $args[1]
|
||||
|
||||
$index = 0
|
||||
foreach($f in $fs) {
|
||||
|
||||
$name = $f.Name
|
||||
$path = $f.FullName
|
||||
Write-Output "::set-output name=name_$index::$name"
|
||||
Write-Output "::set-output name=path_$index::$path"
|
||||
|
||||
$index = $index + 1
|
||||
}
|
||||
@@ -297,7 +297,7 @@
|
||||
<LanguageStandard_C>stdc11</LanguageStandard_C>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<AdditionalOptions>/utf-8 /MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -328,7 +328,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<AdditionalOptions>/utf-8 /MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -373,4 +373,4 @@
|
||||
<UserProperties _1_1_4_1_1_4resource_4config_1json__JsonSchema="" _1_1_4_1_1_4resource_4tasks_1json__JsonSchema="../docs/maa_tasks_schema.json" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
11
src/MeoAssistantBuilder/.editorconfig
Normal file
11
src/MeoAssistantBuilder/.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
[*.cs]
|
||||
dotnet_style_qualification_for_field = false:warning
|
||||
dotnet_style_qualification_for_property = false:warning
|
||||
dotnet_style_qualification_for_method = false:warning
|
||||
dotnet_style_qualification_for_event = false:warning
|
||||
dotnet_style_require_accessibility_modifiers = never:warning
|
||||
|
||||
csharp_style_expression_bodied_methods = true:silent
|
||||
csharp_style_expression_bodied_properties = true:warning
|
||||
csharp_style_expression_bodied_indexers = true:warning
|
||||
csharp_style_expression_bodied_accessors = true:warning
|
||||
117
src/MeoAssistantBuilder/ActionConfiguration.cs
Normal file
117
src/MeoAssistantBuilder/ActionConfiguration.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Nuke.Common.Tooling;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[TypeConverter(typeof(TypeConverter<ActionConfiguration>))]
|
||||
public class ActionConfiguration : Enumeration
|
||||
{
|
||||
/// <summary>
|
||||
/// 开发构建测试
|
||||
/// <para>触发条件</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>Push 或 PR 至 `dev` 分支</item>
|
||||
/// <item>Maa 相关代码有更改</item>
|
||||
/// <item>可手动触发</item>
|
||||
/// </list>
|
||||
/// <para>运行内容 (在 MaaElectronUI 发布后将会进行修改)</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>将会发布 Artifact</item>
|
||||
/// <item>将会打包 MaaBundle</item>
|
||||
/// <item>生成的包文件名为 `MaaBundle-Dev-{VERSION}.zip`</item>
|
||||
/// <item>版本号为 `{yyyy-MM-dd-HH-mm-ss}-{commitHash[..7]}`</item>
|
||||
/// <item>MaaCore 使用 `RelWithDebInfo` 配置</item>
|
||||
/// <item>MaaWpf 使用 `RelWithDebInfo` 配置</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public static readonly ActionConfiguration DevBuild = new() { Value = "dev-build" };
|
||||
|
||||
/// <summary>
|
||||
/// 发布 MeoAssistantArknights (在 MaaElectronUI 发布后,此 Action 将被移除,由 <see cref="ReleaseMaaCore"/> 代替)
|
||||
/// <para>触发条件</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>创建了 Tag</item>
|
||||
/// <item>Tag 匹配 `v*` 规则</item>
|
||||
/// </list>
|
||||
/// <para>运行内容</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>将会发布 Artifact</item>
|
||||
/// <item>将会打包 MeoAssistantArknights 和 MaaCore</item>
|
||||
/// <item>生成的包文件名为 `MeoAssistantArknights_{VERSION}.zip` 和 `MaaCore-{VERSION}.zip`</item>
|
||||
/// <item>GitHub Actions 中运行时,将会发布 Release 至 `MaaAssistantArknights/MaaAssistantArknights`</item>
|
||||
/// <item>GitHub Actions 中运行时,`ref` 不匹配 `ref/tags/v*` 时将会抛错</item>
|
||||
/// <item>GitHub Actions 中运行时,版本号为 `{Tag}`</item>
|
||||
/// <item>
|
||||
/// 其他环境中运行时,版本号为
|
||||
/// <list type="number">
|
||||
/// <item>当前 HEAD 存在一个 Tag,则为 `{Tag}-Local`</item>
|
||||
/// <item>当前 HEAD 不存在 Tag,则为 `v.{CommitHash[..7]}-Local`</item>
|
||||
/// </list>
|
||||
/// </item>
|
||||
/// <item>MaaCore 使用 `Release` 配置,单独的包中使用 `CICD` 配置</item>
|
||||
/// <item>MaaWpf 使用 `Release` 配置</item>
|
||||
/// <item>将会移除 Debug 用文件</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public static readonly ActionConfiguration ReleaseMaa = new() { Value = "release-maa" };
|
||||
|
||||
/// <summary>
|
||||
/// 发布 MaaCore (在 MaaElectronUI 发布前,此 Action 不执行)
|
||||
/// <para>触发条件</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>创建了 Tag</item>
|
||||
/// <item>Tag 匹配 `v*` 规则</item>
|
||||
/// </list>
|
||||
/// <para>运行内容</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>将会发布 Artifact</item>
|
||||
/// <item>将会打包 MaaCore</item>
|
||||
/// <item>生成的包文件名为 `MaaCore-{VERSION}.zip`</item>
|
||||
/// <item>GitHub Actions 中运行时,将会发布 Release 至 `MaaAssistantArknights/MaaAssistantArknights`</item>
|
||||
/// <item>GitHub Actions 中运行时,`ref` 不匹配 `ref/tags/v*` 时将会抛错</item>
|
||||
/// <item>GitHub Actions 中运行时,版本号为 `{Tag}`</item>
|
||||
/// <item>
|
||||
/// 其他环境中运行时,版本号为
|
||||
/// <list type="number">
|
||||
/// <item>当前 HEAD 存在一个 Tag,则为 `{Tag}-Local`</item>
|
||||
/// <item>当前 HEAD 不存在 Tag,则为 `v.{CommitHash[..7]}-Local`</item>
|
||||
/// </list>
|
||||
/// </item>
|
||||
/// <item>MaaCore 使用 `CICD` 配置</item>
|
||||
/// <item>将会移除 Debug 用文件</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public static readonly ActionConfiguration ReleaseMaaCore = new() { Value = "release-maa-core" };
|
||||
|
||||
/// <summary>
|
||||
/// 发布 MaaResource
|
||||
/// <para>触发条件</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>资源文件夹有更改</item>
|
||||
/// <item>`master` 分支</item>
|
||||
/// </list>
|
||||
/// <para>运行内容</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>将会发布 Artifact</item>
|
||||
/// <item>将会打包 MaaResource</item>
|
||||
/// <item>生成的包文件名为 `MaaResource-{VERSION}.zip`</item>
|
||||
/// <item>GitHub Actions 中运行时,将会发布 Release 至 `MaaAssistantArknights/MaaResourceRelease`</item>
|
||||
/// <item>版本号为 `{yyyy-MM-dd-HH-mm-ss}-{commitHash[..7]}`</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public static readonly ActionConfiguration ReleaseMaaResource = new() { Value = "release-maa-resource" };
|
||||
|
||||
public static implicit operator string(ActionConfiguration configuration)
|
||||
{
|
||||
return configuration.Value;
|
||||
}
|
||||
|
||||
public static explicit operator ActionConfiguration(string value) => value switch
|
||||
{
|
||||
"dev-build" => DevBuild,
|
||||
"release-maa" => ReleaseMaa,
|
||||
"release-maa-core" => ReleaseMaaCore,
|
||||
"release-maa-resource" => ReleaseMaaResource,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
35
src/MeoAssistantBuilder/Build.CI.GitHubActions.DevBuild.cs
Normal file
35
src/MeoAssistantBuilder/Build.CI.GitHubActions.DevBuild.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Nuke.Common.CI.GitHubActions;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[GitHubActions(
|
||||
name: "dev-build",
|
||||
image: GitHubActionsImage.WindowsLatest,
|
||||
OnPushBranchesIgnore = new[] { MasterBranch },
|
||||
OnPullRequestBranches = new[] { DevBranch },
|
||||
OnPushIncludePaths = new[]
|
||||
{
|
||||
"src/MeoAssistant/**",
|
||||
"src/MeoAssistantBuilder/**",
|
||||
"src/MeoAsstGui/**", // 新 UI 发布后,移除 MeoAsstGui
|
||||
"3rdparty/**", // 新 UI 发布后,移除 3rdparty/resource/**
|
||||
"include/**",
|
||||
"resource/**", // 新 UI 发布后,DevBuild 不再包含 WPF Gui 内容,不再打包 MaaBundle,因此移除资源文件夹的监控
|
||||
"MeoAssistantArknights.sln"
|
||||
},
|
||||
OnPullRequestIncludePaths = new[]
|
||||
{
|
||||
"src/MeoAssistant/**",
|
||||
"src/MeoAssistantBuilder/**",
|
||||
"src/MeoAsstGui/**", // 新 UI 发布后,移除 MeoAsstGui
|
||||
"3rdparty/**", // 新 UI 发布后,移除 3rdparty/resource/**
|
||||
"include/**",
|
||||
"resource/**", // 新 UI 发布后,DevBuild 不再包含 WPF Gui 内容,不再打包 MaaBundle,因此移除资源文件夹的监控
|
||||
"MeoAssistantArknights.sln"
|
||||
},
|
||||
OnWorkflowDispatchRequiredInputs = new string[] { "Reason" },
|
||||
InvokedTargets = new[] { nameof(DevBuild) },
|
||||
EnableGitHubToken = true,
|
||||
PublishArtifacts = true
|
||||
)]
|
||||
public partial class Build { }
|
||||
14
src/MeoAssistantBuilder/Build.CI.GitHubActions.ReleaseMaa.cs
Normal file
14
src/MeoAssistantBuilder/Build.CI.GitHubActions.ReleaseMaa.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Nuke.Common.CI.GitHubActions;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[GitHubActions(
|
||||
name: "release-maa",
|
||||
image: GitHubActionsImage.WindowsLatest,
|
||||
OnPushTags = new[] { "v*" },
|
||||
InvokedTargets = new[] { nameof(ReleaseMaa) },
|
||||
ImportSecrets = new[] { "PUBLISH_GH_PAT" },
|
||||
EnableGitHubToken = true,
|
||||
PublishArtifacts = true
|
||||
)]
|
||||
public partial class Build { }
|
||||
@@ -0,0 +1,17 @@
|
||||
/*using Nuke.Common.CI.GitHubActions;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[GitHubActions(
|
||||
name: "release-maa-core",
|
||||
image: GitHubActionsImage.WindowsLatest,
|
||||
OnPushTags = new[] { "v*" },
|
||||
InvokedTargets = new[] { nameof(ReleaseMaaCore) },
|
||||
ImportSecrets = new[] { "PUBLISH_GH_PAT" },
|
||||
EnableGitHubToken = true,
|
||||
PublishArtifacts = true
|
||||
)]
|
||||
public partial class Build { }
|
||||
*/
|
||||
|
||||
// 在 MaaElectronUI 发布前不启用
|
||||
@@ -0,0 +1,19 @@
|
||||
using Nuke.Common.CI.GitHubActions;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[GitHubActions(
|
||||
name: "release-maa-resource",
|
||||
image: GitHubActionsImage.WindowsLatest,
|
||||
OnPushBranches = new[] { MasterBranch },
|
||||
OnPushIncludePaths = new[]
|
||||
{
|
||||
"resource/**",
|
||||
"3rdparty/resource/**"
|
||||
},
|
||||
InvokedTargets = new[] { nameof(ReleaseMaaResource) },
|
||||
ImportSecrets = new[] { "PUBLISH_GH_PAT" },
|
||||
EnableGitHubToken = true,
|
||||
PublishArtifacts = true
|
||||
)]
|
||||
public partial class Build { }
|
||||
588
src/MeoAssistantBuilder/Build.cs
Normal file
588
src/MeoAssistantBuilder/Build.cs
Normal file
@@ -0,0 +1,588 @@
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Nuke.Common;
|
||||
using Nuke.Common.Execution;
|
||||
using Nuke.Common.Git;
|
||||
using Nuke.Common.IO;
|
||||
using Nuke.Common.Tooling;
|
||||
using Nuke.Common.Tools.GitHub;
|
||||
using Nuke.Common.Tools.MSBuild;
|
||||
using Octokit;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[CheckBuildProjectConfigurations]
|
||||
public partial class Build : NukeBuild
|
||||
{
|
||||
public static int Main()
|
||||
{
|
||||
var osValidation =
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
|
||||
RuntimeInformation.OSArchitecture == Architecture.X64;
|
||||
|
||||
if (osValidation is false)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Error.WriteLine("仅在 Windows x64 平台可用");
|
||||
|
||||
Console.Error.WriteLine($"当前系统:{RuntimeInformation.OSDescription}");
|
||||
Console.Error.WriteLine($"当前系统架构:{RuntimeInformation.OSArchitecture}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
return Execute<Build>(_ => _.Default);
|
||||
}
|
||||
|
||||
BuildParameters Parameters;
|
||||
|
||||
const string MasterBranch = "master";
|
||||
const string DevBranch = "dev";
|
||||
|
||||
const string MaaDevBundlePackageNameTemplate = "MaaBundle-Dev-{VERSION}";
|
||||
const string MaaLegacyBundlePackageNameTemplate = "MeoAssistantArknights_{VERSION}";
|
||||
const string MaaCorePackageNameTemplate = "MaaCore-{VERSION}";
|
||||
const string MaaResourcePackageNameTemplate = "MaaResource-{VERSION}";
|
||||
|
||||
private string _version = "";
|
||||
private string _changeLog = "";
|
||||
|
||||
private string MaaDevBundlePackageName => MaaDevBundlePackageNameTemplate.Replace("{VERSION}", _version);
|
||||
private string MaaLegacyBundlePackageName => MaaLegacyBundlePackageNameTemplate.Replace("{VERSION}", _version);
|
||||
private string MaaCorePackageName => MaaCorePackageNameTemplate.Replace("{VERSION}", _version);
|
||||
private string MaaResourcePackageName => MaaResourcePackageNameTemplate.Replace("{VERSION}", _version);
|
||||
|
||||
protected override void OnBuildInitialized()
|
||||
{
|
||||
Parameters = new BuildParameters(this);
|
||||
|
||||
Information("==========================");
|
||||
|
||||
Information("1. 工具链");
|
||||
Information($"Visual Studio 路径:{Parameters.VisualStudioPath ?? "Null"}");
|
||||
Information($"MSBuild 路径:{Parameters.MsBuildPath ?? "Null"}");
|
||||
|
||||
Information("2. 仓库");
|
||||
Information($"Fork:{Parameters.IsFork}");
|
||||
Information($"主仓库:{Parameters.MainRepo ?? "Null"}");
|
||||
Information($"MaaResource 发布仓库:{Parameters.MaaResourceReleaseRepo ?? "Null"}");
|
||||
Information($"主分支:{Parameters.MasterBranchRef ?? "Null"}");
|
||||
Information($"开发分支:{Parameters.DevBranchRef ?? "Null"}");
|
||||
Information($"发布 Tag 前缀:{Parameters.ReleaseTagRefPrefix ?? "Null"}");
|
||||
|
||||
Information("3. 路径");
|
||||
Information($"编译输出路径:{Parameters.BuildOutput ?? "Null"}");
|
||||
Information($"Artifact 输出路径:{Parameters.ArtifactOutput ?? "Null"}");
|
||||
|
||||
Information("4. 项目");
|
||||
Information($"MaaCore 项目:{Parameters.MaaCoreProject ?? "Null"}");
|
||||
Information($"MaaWpf 项目:{Parameters.MaaWpfProject ?? "Null"}");
|
||||
|
||||
Information("5. 配置");
|
||||
Information($"构建时间:{Parameters.BuildTime ?? "Null"}");
|
||||
Information($"Commit Hash:{Parameters.CommitHash ?? "Null"}");
|
||||
Information($"Commit Hash Full:{Parameters.CommitHashFull ?? "Null"}");
|
||||
|
||||
Information("6. CI");
|
||||
Information($"在 GitHub Actions 中运行:{Parameters.IsGitHubActions}");
|
||||
Information($"是 Pull Request:{Parameters.IsPullRequest}");
|
||||
Information($"是 Workflow Dispatch 触发:{Parameters.IsWorkflowDispatch}");
|
||||
Information($"Actions 名称:{Parameters.GhActionName ?? "Null"}");
|
||||
Information($"Actions 分支:{Parameters.GhBranch ?? "Null"}");
|
||||
Information($"Actions PR:{Parameters.GhPullRequestId ?? "Null"}");
|
||||
Information($"Actions Tag:{Parameters.GhTag ?? "Null"}");
|
||||
|
||||
Information("==========================");
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "<Pending>")]
|
||||
Target Default => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
Assert.Fail("请指定一个 Target");
|
||||
});
|
||||
|
||||
#region 清理
|
||||
|
||||
Target Clean => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
FileSystemTasks.EnsureCleanDirectory(Parameters.ArtifactOutput);
|
||||
|
||||
FileSystemTasks.EnsureCleanDirectory(Parameters.BuildOutput / BuildConfiguration.Release);
|
||||
FileSystemTasks.EnsureCleanDirectory(Parameters.BuildOutput / BuildConfiguration.RelWithDebInfo);
|
||||
FileSystemTasks.EnsureCleanDirectory(Parameters.BuildOutput / BuildConfiguration.CICD);
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region 设置版本
|
||||
|
||||
Target UseCommitVersion => _ => _
|
||||
.DependsOn(Clean)
|
||||
.Triggers(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
_version = $"{Parameters.BuildTime}-{Parameters.CommitHash}";
|
||||
});
|
||||
|
||||
Target UseTagVersion => _ => _
|
||||
.DependsOn(Clean)
|
||||
.Triggers(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
if (Parameters.IsGitHubActions is false)
|
||||
{
|
||||
Information("未在 GitHub Actions 中运行");
|
||||
|
||||
var repo = GitRepository.FromLocalDirectory(RootDirectory);
|
||||
Assert.True(repo is not null, "不在 Git Repo 中");
|
||||
|
||||
var tag = repo.Tags.FirstOrDefault();
|
||||
|
||||
if (tag is not null)
|
||||
{
|
||||
_version = $"{tag}-Local";
|
||||
}
|
||||
else
|
||||
{
|
||||
_version = $"v.{Parameters.CommitHash}-Local";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Information("在 GitHub Actions 中运行");
|
||||
|
||||
Assert.True(Parameters.GhTag is not null, "在 GitHub Actions 中运行,但是不存在 Tag");
|
||||
|
||||
_version = Parameters.GhTag;
|
||||
}
|
||||
});
|
||||
|
||||
Target SetVersion => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
Information($"当前版本号设置为:{_version}");
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region 编译
|
||||
|
||||
Target WithCompileCoreRelease => _ => _
|
||||
.After(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
var versionEnv = $"/DMAA_VERSION=\\\"{_version}\\\"";
|
||||
Information($"MaaCore 编译环境变量:ExternalCompilerOptions = {versionEnv}");
|
||||
MSBuild(c => c
|
||||
.SetProcessToolPath(Parameters.MsBuildPath)
|
||||
.SetProjectFile(Parameters.MaaCoreProject)
|
||||
.SetTargets("ReBuild")
|
||||
.SetConfiguration(BuildConfiguration.Release)
|
||||
.SetTargetPlatform(MSBuildTargetPlatform.x64)
|
||||
.SetProcessEnvironmentVariable("ExternalCompilerOptions", versionEnv)
|
||||
);
|
||||
});
|
||||
|
||||
Target WithCompileCoreDebug => _ => _
|
||||
.After(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
var versionEnv = $"/DMAA_VERSION=\\\"{_version}\\\"";
|
||||
Information($"MaaCore 编译环境变量:ExternalCompilerOptions = {versionEnv}");
|
||||
MSBuild(c => c
|
||||
.SetProcessToolPath(Parameters.MsBuildPath)
|
||||
.SetProjectFile(Parameters.MaaCoreProject)
|
||||
.SetTargets("ReBuild")
|
||||
.SetConfiguration(BuildConfiguration.RelWithDebInfo)
|
||||
.SetTargetPlatform(MSBuildTargetPlatform.x64)
|
||||
.SetProcessEnvironmentVariable("ExternalCompilerOptions", versionEnv)
|
||||
);
|
||||
});
|
||||
|
||||
Target WithCompileCoreCICD => _ => _
|
||||
.After(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
var versionEnv = $"/DMAA_VERSION=\\\"{_version}\\\"";
|
||||
Information($"MaaCore 编译环境变量:ExternalCompilerOptions = {versionEnv}");
|
||||
MSBuild(c => c
|
||||
.SetProcessToolPath(Parameters.MsBuildPath)
|
||||
.SetProjectFile(Parameters.MaaCoreProject)
|
||||
.SetTargets("ReBuild")
|
||||
.SetConfiguration(BuildConfiguration.CICD)
|
||||
.SetTargetPlatform(MSBuildTargetPlatform.x64)
|
||||
.SetProcessEnvironmentVariable("ExternalCompilerOptions", versionEnv)
|
||||
);
|
||||
|
||||
var output = Parameters.BuildOutput / BuildConfiguration.CICD;
|
||||
var dlls = RootDirectory / "3rdparty" / "bin";
|
||||
|
||||
Information($"复制目录:{dlls} -> {output}");
|
||||
FileSystemTasks.CopyDirectoryRecursively(dlls, output,
|
||||
DirectoryExistsPolicy.Merge, FileExistsPolicy.OverwriteIfNewer);
|
||||
});
|
||||
|
||||
// TODO 在 MaaElectronUI 发布后移除
|
||||
Target WithCompileWpfRelease => _ => _
|
||||
.After(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
MSBuild(c => c
|
||||
.SetProcessToolPath(Parameters.MsBuildPath)
|
||||
.SetProjectFile(Parameters.MaaWpfProject)
|
||||
.SetTargets("ReBuild")
|
||||
.SetConfiguration(BuildConfiguration.Release)
|
||||
.SetTargetPlatform(MSBuildTargetPlatform.x64)
|
||||
.EnableRestore()
|
||||
);
|
||||
});
|
||||
|
||||
// TODO 在 MaaElectronUI 发布后移除
|
||||
Target WithCompileWpfDebug => _ => _
|
||||
.After(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
MSBuild(c => c
|
||||
.SetProcessToolPath(Parameters.MsBuildPath)
|
||||
.SetProjectFile(Parameters.MaaWpfProject)
|
||||
.SetTargets("ReBuild")
|
||||
.SetConfiguration(BuildConfiguration.RelWithDebInfo)
|
||||
.SetTargetPlatform(MSBuildTargetPlatform.x64)
|
||||
.EnableRestore()
|
||||
);
|
||||
});
|
||||
|
||||
Target WithCompileResourceRelease => _ => _
|
||||
.After(SetVersion)
|
||||
.Executes(() =>
|
||||
{
|
||||
var output = Parameters.BuildOutput / BuildConfiguration.Release;
|
||||
var resourceFile = RootDirectory / "resource";
|
||||
var resourceFileThirdParty = RootDirectory / "3rdparty" / "resource";
|
||||
|
||||
Information($"复制目录:{resourceFile} -> {output}");
|
||||
FileSystemTasks.CopyDirectoryRecursively(resourceFile, output,
|
||||
DirectoryExistsPolicy.Merge, FileExistsPolicy.OverwriteIfNewer);
|
||||
Information($"复制目录:{resourceFileThirdParty} -> {output}");
|
||||
FileSystemTasks.CopyDirectoryRecursively(resourceFileThirdParty, output,
|
||||
DirectoryExistsPolicy.Merge, FileExistsPolicy.OverwriteIfNewer);
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region 打包
|
||||
|
||||
Target UseMaaDevBundle => _ => _
|
||||
.DependsOn(WithCompileCoreDebug, WithCompileWpfDebug)
|
||||
.Triggers(SetPackageBundled)
|
||||
.Executes(() =>
|
||||
{
|
||||
var buildOutput = Parameters.BuildOutput / BuildConfiguration.RelWithDebInfo;
|
||||
BundlePackage(buildOutput, MaaDevBundlePackageName);
|
||||
});
|
||||
|
||||
Target UseMaaLegacyBundle => _ => _
|
||||
.DependsOn(WithCompileCoreCICD, WithCompileCoreRelease, WithCompileWpfRelease)
|
||||
.Triggers(SetPackageBundled)
|
||||
.Executes(() =>
|
||||
{
|
||||
var releaseBuildOutput = Parameters.BuildOutput / BuildConfiguration.Release;
|
||||
RemoveDebugSymbols(releaseBuildOutput);
|
||||
|
||||
BundlePackage(releaseBuildOutput, MaaLegacyBundlePackageName);
|
||||
|
||||
var cicdBuildOutput = Parameters.BuildOutput / BuildConfiguration.CICD;
|
||||
RemoveDebugSymbols(cicdBuildOutput);
|
||||
|
||||
BundlePackage(cicdBuildOutput, MaaCorePackageName);
|
||||
});
|
||||
|
||||
Target UseMaaCore => _ => _
|
||||
.DependsOn(WithCompileCoreCICD)
|
||||
.Triggers(SetPackageBundled)
|
||||
.Executes(() =>
|
||||
{
|
||||
var buildOutput = Parameters.BuildOutput / BuildConfiguration.CICD;
|
||||
RemoveDebugSymbols(buildOutput);
|
||||
|
||||
BundlePackage(buildOutput, MaaCorePackageName);
|
||||
});
|
||||
|
||||
Target UseMaaResource => _ => _
|
||||
.DependsOn(WithCompileResourceRelease)
|
||||
.Triggers(SetPackageBundled)
|
||||
.Executes(() =>
|
||||
{
|
||||
var buildOutput = Parameters.BuildOutput / BuildConfiguration.Release;
|
||||
RemoveDebugSymbols(buildOutput);
|
||||
|
||||
BundlePackage(buildOutput, MaaResourcePackageName);
|
||||
});
|
||||
|
||||
Target SetPackageBundled => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
Information("已完成打包");
|
||||
foreach (var file in Parameters.ArtifactOutput.GlobFiles("*.zip"))
|
||||
{
|
||||
var size = (new FileInfo(file).Length / 1024.0 / 1024.0).ToString("F3");
|
||||
Information($"找到 Artifact:{file}");
|
||||
}
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region 更新日志
|
||||
|
||||
Target UseMaaChangeLog => _ => _
|
||||
.Triggers(SetMaaChangeLog)
|
||||
.Executes(() =>
|
||||
{
|
||||
_changeLog = $"对应 Commit:[{Parameters.MainRepo}@{Parameters.CommitHash}](https://github.com/{Parameters.MainRepo}/commit/{Parameters.CommitHashFull})\n\n";
|
||||
if (File.Exists(Parameters.MaaChangelogFile))
|
||||
{
|
||||
Information($"找到 {Parameters.MaaChangelogFile} 文件,读取内容作为更新日志");
|
||||
var text = File.ReadAllText(Parameters.MaaChangelogFile);
|
||||
_changeLog += text;
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning($"未发现 {Parameters.MaaChangelogFile} 文件,将使用默认值");
|
||||
}
|
||||
});
|
||||
|
||||
Target UseMaaResourceChangeLog => _ => _
|
||||
.Triggers(SetMaaChangeLog)
|
||||
.Executes(() =>
|
||||
{
|
||||
_changeLog = $"对应 Commit:[{Parameters.MainRepo}@{Parameters.CommitHash}](https://github.com/{Parameters.MainRepo}/commit/{Parameters.CommitHashFull})\n\n";
|
||||
if (File.Exists(Parameters.MaaResourceChangeLogFile))
|
||||
{
|
||||
Information($"找到 {Parameters.MaaResourceChangeLogFile} 文件,读取内容作为更新日志");
|
||||
var text = File.ReadAllText(Parameters.MaaResourceChangeLogFile);
|
||||
_changeLog += text;
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning($"未发现 {Parameters.MaaResourceChangeLogFile} 文件,将使用默认值");
|
||||
}
|
||||
});
|
||||
|
||||
Target SetMaaChangeLog => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
Information($"更新日志:\n================================\n{_changeLog}\n================================");
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region 发布
|
||||
|
||||
Target UsePublishArtifact => _ => _
|
||||
.After(SetPackageBundled, SetMaaChangeLog)
|
||||
.Produces(RootDirectory / "artifacts" / "*.zip")
|
||||
.OnlyWhenStatic(() => GitHubActions != null);
|
||||
|
||||
Target UsePublishRelease => _ => _
|
||||
.After(UsePublishArtifact)
|
||||
.OnlyWhenStatic(() => GitHubActions != null)
|
||||
.Executes(() =>
|
||||
{
|
||||
Information("在 GitHub Actions 中运行,执行发布 Release 任务");
|
||||
Information($"当前 Actions:{Parameters.GhActionName}");
|
||||
|
||||
if (Parameters.GhActionName == ActionConfiguration.DevBuild)
|
||||
{
|
||||
Information($"DevBuild 跳过发布 Release");
|
||||
return;
|
||||
}
|
||||
|
||||
GitHubTasks.GitHubClient = new GitHubClient(new ProductHeaderValue(nameof(NukeBuild)))
|
||||
{
|
||||
Credentials = new Credentials(Parameters.GitHubPersonalAccessToken)
|
||||
};
|
||||
|
||||
if (Parameters.GhActionName == ActionConfiguration.ReleaseMaa)
|
||||
{
|
||||
Information($"运行 ReleaseMaa 将在 {Parameters.MainRepo} 创建 Release {Parameters.GhTag}");
|
||||
|
||||
CreateGitHubRelease(Parameters.MainRepo, Parameters.CommitHashFull, _version);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Parameters.GhActionName == ActionConfiguration.ReleaseMaaCore)
|
||||
{
|
||||
Information($"运行 ReleaseMaaCore 将在 {Parameters.MainRepo} 创建 Release {Parameters.GhTag}");
|
||||
|
||||
CreateGitHubRelease(Parameters.MainRepo, Parameters.CommitHashFull, _version);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Parameters.GhActionName == ActionConfiguration.ReleaseMaaResource)
|
||||
{
|
||||
Information($"运行 ReleaseMaaResource 将在 {Parameters.MaaResourceReleaseRepo} 创建 Release {_version}");
|
||||
|
||||
CreateGitHubRelease(Parameters.MaaResourceReleaseRepo, "main", _version);
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region Work Flow
|
||||
|
||||
/// <summary>
|
||||
/// 见 <see cref="ActionConfiguration.DevBuild"/>
|
||||
/// </summary>
|
||||
Target DevBuild => _ => _
|
||||
.DependsOn(Clean)
|
||||
.DependsOn(UseCommitVersion)
|
||||
.DependsOn(UseMaaDevBundle)
|
||||
.DependsOn(UsePublishArtifact);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 见 <see cref="ActionConfiguration.ReleaseMaa"/>
|
||||
/// </summary>
|
||||
Target ReleaseMaa => _ => _
|
||||
.DependsOn(Clean)
|
||||
.DependsOn(UseTagVersion)
|
||||
.DependsOn(UseMaaLegacyBundle)
|
||||
.DependsOn(UseMaaChangeLog)
|
||||
.DependsOn(UsePublishArtifact)
|
||||
.DependsOn(UsePublishRelease);
|
||||
|
||||
/// <summary>
|
||||
/// 见 <see cref="ActionConfiguration.ReleaseMaaCore"/>
|
||||
/// </summary>
|
||||
Target ReleaseMaaCore => _ => _
|
||||
.DependsOn(Clean)
|
||||
.DependsOn(UseTagVersion)
|
||||
.DependsOn(UseMaaCore)
|
||||
.DependsOn(UseMaaChangeLog)
|
||||
.DependsOn(UsePublishArtifact)
|
||||
.DependsOn(UsePublishRelease);
|
||||
|
||||
/// <summary>
|
||||
/// 见 <see cref="ActionConfiguration.ReleaseMaaResource"/>
|
||||
/// </summary>
|
||||
Target ReleaseMaaResource => _ => _
|
||||
.DependsOn(Clean)
|
||||
.DependsOn(UseCommitVersion)
|
||||
.DependsOn(UseMaaResource)
|
||||
.DependsOn(UseMaaResourceChangeLog)
|
||||
.DependsOn(UsePublishArtifact)
|
||||
.DependsOn(UsePublishRelease);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Logger
|
||||
|
||||
private readonly Action<string> Information = (string msg) =>
|
||||
{
|
||||
Log.Information("{Message}", msg);
|
||||
};
|
||||
|
||||
private readonly Action<string> Warning = (string msg) =>
|
||||
{
|
||||
Log.Warning("{Message}", msg);
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utilities
|
||||
|
||||
private void BundlePackage(AbsolutePath input, string bundleName)
|
||||
{
|
||||
var packName = bundleName;
|
||||
if (packName.EndsWith(".zip") is false)
|
||||
{
|
||||
packName += ".zip";
|
||||
}
|
||||
var bundle = Parameters.ArtifactOutput / packName;
|
||||
|
||||
Information($"编译输出:{input}");
|
||||
Information($"打包输出:{bundle}");
|
||||
|
||||
Assert.True(Directory.Exists(input), $"输出目录 {input} 不存在");
|
||||
|
||||
Information($"创建压缩文件:{bundle}");
|
||||
ZipFile.CreateFromDirectory(input, bundle, CompressionLevel.SmallestSize, false);
|
||||
}
|
||||
|
||||
private void RemoveDebugSymbols(AbsolutePath outputDir)
|
||||
{
|
||||
var files = outputDir.GlobFiles("*.pdb", "*.lib", "*.exp", "*.exe.config");
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
FileSystemTasks.DeleteFile(file);
|
||||
Information($"删除文件:{file}");
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateGitHubRelease(string repo, string commitish, string releaseName)
|
||||
{
|
||||
var assets = Parameters.ArtifactOutput.GlobFiles("*.zip");
|
||||
|
||||
var release = new NewRelease(_version)
|
||||
{
|
||||
TargetCommitish = commitish,
|
||||
Name = releaseName,
|
||||
Body = _changeLog,
|
||||
Draft = true,
|
||||
Prerelease = false
|
||||
};
|
||||
var repoOwner = repo.Split('/')[0];
|
||||
var repoName = repo.Split('/')[1];
|
||||
|
||||
var createdRelease = GitHubTasks.GitHubClient.Repository.Release.Create(repoOwner, repoName, release).Result;
|
||||
Information($"创建 Release {Parameters.GhTag} 成功");
|
||||
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
UploadReleaseAssetToGitHub(createdRelease, asset);
|
||||
}
|
||||
|
||||
var _ = GitHubTasks.GitHubClient.Repository.Release.Edit(repoOwner, repoName, createdRelease.Id, new ReleaseUpdate { Draft = false }).Result;
|
||||
}
|
||||
|
||||
private void UploadReleaseAssetToGitHub(Release release, AbsolutePath asset)
|
||||
{
|
||||
if (new FileExtensionContentTypeProvider().TryGetContentType(asset, out var assetContentType) is false)
|
||||
{
|
||||
assetContentType = "application/x-binary";
|
||||
}
|
||||
|
||||
var releaseAssetUpload = new ReleaseAssetUpload
|
||||
{
|
||||
ContentType = assetContentType,
|
||||
FileName = Path.GetFileName(asset),
|
||||
RawData = File.OpenRead(path: asset)
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var _ = GitHubTasks.GitHubClient.Repository.Release.UploadAsset(release, releaseAssetUpload).Result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Assert.Fail($"上传文件 {asset} 到 GitHub 失败");
|
||||
}
|
||||
|
||||
Information($"上传文件 {asset} 到 GitHub 成功");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
31
src/MeoAssistantBuilder/BuildConfiguration.cs
Normal file
31
src/MeoAssistantBuilder/BuildConfiguration.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Nuke.Common.Tooling;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
[TypeConverter(typeof(TypeConverter<BuildConfiguration>))]
|
||||
public class BuildConfiguration : Enumeration
|
||||
{
|
||||
/// <summary>
|
||||
/// MaaCore 在此配置下会自动复制资源文件,在直接发布 MaaBundle 时使用;
|
||||
/// MaaWpf 在此配置下开启了优化,在直接发布 MaaBundle 时使用;
|
||||
/// </summary>
|
||||
public static readonly BuildConfiguration Release = new() { Value = nameof(Release) };
|
||||
|
||||
/// <summary>
|
||||
/// MaaCore 在此配置下会生成完整的 Debug 信息,在 DevBuild 中使用;
|
||||
/// MaaWpf 在此配置下关闭了优化,在 DevBuild 中使用;
|
||||
/// </summary>
|
||||
public static readonly BuildConfiguration RelWithDebInfo = new() { Value = nameof(RelWithDebInfo) };
|
||||
|
||||
/// <summary>
|
||||
/// MaaCore 在此配置下不会自动复制资源文件,其余配置和 <see cref="Release"/> 相同,在发布 MaaCore 时使用
|
||||
/// MaaWpf 在此配置下与 <see cref="Release"/> 相同,不建议使用
|
||||
/// </summary>
|
||||
public static readonly BuildConfiguration CICD = new() { Value = nameof(CICD) };
|
||||
|
||||
public static implicit operator string(BuildConfiguration configuration)
|
||||
{
|
||||
return configuration.Value;
|
||||
}
|
||||
}
|
||||
238
src/MeoAssistantBuilder/BuildParameters.cs
Normal file
238
src/MeoAssistantBuilder/BuildParameters.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Nuke.Common;
|
||||
using Nuke.Common.CI;
|
||||
using Nuke.Common.CI.GitHubActions;
|
||||
using Nuke.Common.IO;
|
||||
using Nuke.Common.ProjectModel;
|
||||
using Nuke.Common.Tools.Git;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
public partial class Build
|
||||
{
|
||||
#region Nuke 默认全局参数
|
||||
|
||||
[Solution] readonly Solution Solution;
|
||||
[CI] readonly GitHubActions GitHubActions;
|
||||
|
||||
#endregion
|
||||
|
||||
public class BuildParameters
|
||||
{
|
||||
#region 方法
|
||||
|
||||
private static readonly Lazy<string> GetVsPath = new(() =>
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) is false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var vsDirectory = VSWhere("-latest -nologo -property installationPath -format value -prerelease").FirstOrDefault().Text;
|
||||
|
||||
return string.IsNullOrWhiteSpace(vsDirectory) ? null : vsDirectory;
|
||||
});
|
||||
|
||||
private readonly Func<string, string> GetMsBuildPath = (string vsPath) =>
|
||||
{
|
||||
var msBuildExe = Path.Combine(vsPath, @"MSBuild\Current\Bin\MSBuild.exe");
|
||||
if (File.Exists(msBuildExe) is false)
|
||||
{
|
||||
msBuildExe = Path.Combine(vsPath, @"MSBuild\15.0\Bin\MSBuild.exe");
|
||||
}
|
||||
|
||||
return File.Exists(msBuildExe) ? msBuildExe : null;
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
// 工具链
|
||||
public AbsolutePath MsBuildPath { get; }
|
||||
public AbsolutePath VisualStudioPath { get; }
|
||||
|
||||
// 仓库
|
||||
public bool IsFork { get; }
|
||||
public string MainRepo { get; }
|
||||
public string MasterBranchRef { get; }
|
||||
public string DevBranchRef { get; }
|
||||
public string ReleaseTagRefPrefix { get; }
|
||||
public string MaaResourceReleaseRepo { get; }
|
||||
|
||||
// 路径
|
||||
public AbsolutePath BuildOutput { get; }
|
||||
public AbsolutePath ArtifactOutput { get; }
|
||||
public AbsolutePath MaaChangelogFile { get; }
|
||||
public AbsolutePath MaaResourceChangeLogFile { get; }
|
||||
|
||||
// 项目
|
||||
public Project MaaCoreProject { get; }
|
||||
public Project MaaWpfProject { get; }
|
||||
|
||||
// 配置
|
||||
public string BuildTime { get; }
|
||||
public string CommitHash { get; }
|
||||
public string CommitHashFull { get; }
|
||||
|
||||
// CI
|
||||
public bool IsGitHubActions { get; }
|
||||
public bool IsPullRequest { get; }
|
||||
public bool IsWorkflowDispatch { get; }
|
||||
public string GitHubPersonalAccessToken { get; } = null;
|
||||
public Dictionary<string, string> WorkflowDispatchArguments { get; }
|
||||
public ActionConfiguration GhActionName { get; } = null;
|
||||
public string GhBranch { get; } = null;
|
||||
public string GhPullRequestId { get; } = null;
|
||||
public string GhTag { get; } = null;
|
||||
|
||||
public BuildParameters(Build b)
|
||||
{
|
||||
// 工具链
|
||||
var vs = GetVsPath.Value;
|
||||
Assert.True(vs is not null, "找不到 Visual Studio");
|
||||
VisualStudioPath = (AbsolutePath)vs;
|
||||
var msbuild = GetMsBuildPath.Invoke(VisualStudioPath);
|
||||
Assert.True(msbuild is not null, "找不到 MSBuild");
|
||||
MsBuildPath = (AbsolutePath)msbuild;
|
||||
|
||||
// 仓库
|
||||
IsFork = false;
|
||||
MainRepo = "MaaAssistantArknights/MaaAssistantArknights";
|
||||
MaaResourceReleaseRepo = "MaaAssistantArknights/MaaResourceRelease";
|
||||
|
||||
MasterBranchRef = "refs/heads/master";
|
||||
DevBranchRef = "refs/heads/dev";
|
||||
ReleaseTagRefPrefix = "refs/tags/v";
|
||||
|
||||
|
||||
// 路径
|
||||
BuildOutput = RootDirectory / "x64";
|
||||
ArtifactOutput = RootDirectory / "artifacts";
|
||||
|
||||
MaaChangelogFile = RootDirectory / "CHANGELOG_MAA.md";
|
||||
MaaResourceChangeLogFile = RootDirectory / "CHANGELOG_RES.md";
|
||||
|
||||
// 项目
|
||||
MaaCoreProject = b.Solution.GetProject("MeoAssistant");
|
||||
MaaWpfProject = b.Solution.GetProject("MeoAsstGui");
|
||||
|
||||
// 配置
|
||||
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("zh-Hans-CN");
|
||||
BuildTime = DateTimeOffset.UtcNow.ToLocalTime().ToString("yyyy-MM-dd-HH-mm-ss");
|
||||
|
||||
CommitHash = GitTasks.GitCurrentCommit();
|
||||
Assert.True(CommitHash is not null, "Commit Hash 为 Null");
|
||||
CommitHashFull = CommitHash;
|
||||
CommitHash = CommitHash[..7];
|
||||
|
||||
// CI
|
||||
IsGitHubActions = b.GitHubActions is not null;
|
||||
if (IsGitHubActions)
|
||||
{
|
||||
GhActionName = (ActionConfiguration)b.GitHubActions.Workflow;
|
||||
Assert.True(GhActionName is not null, $"GitHub Actions Workflow 名 {b.GitHubActions.Workflow} 无法转换为 ActionConfiguration");
|
||||
|
||||
Assert.False(string.IsNullOrEmpty(b.GitHubActions.Ref), "Ref 为 Null");
|
||||
|
||||
GitHubPersonalAccessToken = Environment.GetEnvironmentVariable("PUBLISH_GH_PAT");
|
||||
|
||||
if (b.GitHubActions.Ref.StartsWith(ReleaseTagRefPrefix))
|
||||
{
|
||||
var tag = $"v{b.GitHubActions.Ref.Replace(ReleaseTagRefPrefix, "")}";
|
||||
var pattern = @"v((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)";
|
||||
var match = Regex.Match(tag, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
GhTag = tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Fail("Tag 与 SemVer 不匹配");
|
||||
}
|
||||
}
|
||||
else if (b.GitHubActions.Ref.StartsWith("refs/heads/"))
|
||||
{
|
||||
GhBranch = b.GitHubActions.Ref.Replace("refs/heads/", "");
|
||||
}
|
||||
else if (b.GitHubActions.IsPullRequest)
|
||||
{
|
||||
IsPullRequest = true;
|
||||
GhPullRequestId = b.GitHubActions.Ref;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning("未知的 Ref:{Ref}", b.GitHubActions.Ref ?? "Null");
|
||||
}
|
||||
|
||||
var ghEvent = b.GitHubActions.GitHubEvent;
|
||||
|
||||
if (ghEvent.ContainsKey("inputs"))
|
||||
{
|
||||
IsWorkflowDispatch = true;
|
||||
WorkflowDispatchArguments = new();
|
||||
|
||||
var inputs = (JObject)ghEvent["inputs"];
|
||||
foreach (var (k, v) in inputs)
|
||||
{
|
||||
WorkflowDispatchArguments.Add(k, v.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if (b.GitHubActions.BaseRef is not null)
|
||||
{
|
||||
// Fork
|
||||
MainRepo = b.GitHubActions.Repository;
|
||||
var repoOwner = MainRepo.Split("/")[0];
|
||||
MaaResourceReleaseRepo = $"{repoOwner}/MaaResourceRelease";
|
||||
IsFork = true;
|
||||
}
|
||||
|
||||
// 若是 DevBuild,Branch 必须不为 Master,或者是 PR 至 Dev,又或者是手动触发
|
||||
if (GhActionName == ActionConfiguration.DevBuild)
|
||||
{
|
||||
if (IsWorkflowDispatch)
|
||||
{
|
||||
Assert.True(GhBranch is not null, "DevBuild -> Workflow Dispatch,Branch 为 Null");
|
||||
}
|
||||
else if (IsPullRequest)
|
||||
{
|
||||
Assert.True(GhPullRequestId is not null, "DevBuild -> Pull Request,Pull Request Id 为 Null");
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(GhBranch != MasterBranch, "DevBuild -> Auto Triggered,Branch 为 master");
|
||||
}
|
||||
}
|
||||
|
||||
// 若是 ReleaseMaa,Tag 必须存在,PAT 必须存在
|
||||
if (GhActionName == ActionConfiguration.ReleaseMaa)
|
||||
{
|
||||
Assert.True(GhTag is not null, "ReleaseMaa -> Auto Triggered,Tag 为 Null");
|
||||
Assert.True(GitHubPersonalAccessToken is not null, "ReleaseMaa -> Auto Triggered,PAT 为 Null");
|
||||
}
|
||||
|
||||
// 若是 ReleaseMaaCore,Tag 必须存在,PAT 必须存在
|
||||
if (GhActionName == ActionConfiguration.ReleaseMaaCore)
|
||||
{
|
||||
Assert.True(GhTag is not null, "ReleaseMaaCore -> Auto Triggered,Tag 为 Null");
|
||||
Assert.True(GitHubPersonalAccessToken is not null, "ReleaseMaaCore -> Auto Triggered,PAT 为 Null");
|
||||
}
|
||||
|
||||
// 若是 ReleaseMaaResource,Branch 必须为 Master,PAT 必须存在
|
||||
if (GhActionName == ActionConfiguration.ReleaseMaaResource)
|
||||
{
|
||||
Assert.True(GhBranch == MasterBranch, "ReleaseMaaResource -> Auto Triggered,Branch 不为 master");
|
||||
Assert.True(GitHubPersonalAccessToken is not null, "ReleaseMaaResource -> Auto Triggered,PAT 为 Null");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
public const string MaaProjectRootDirectory = "../../";
|
||||
public const string MaaProjectThirdPartyDirectory = "../../3rdparty";
|
||||
public const string MaaProjectResourceDirectory = "../../resource";
|
||||
public const string MaaProjectArtifactDirectory = "../../artifacts";
|
||||
|
||||
public const string MaaCoreProjectDirectory = "../MeoAssistant";
|
||||
public const string MaaWpfProjectDirectory = "../MeoAsstGui";
|
||||
|
||||
public const string MaaCoreProjectFilePath = $"{MaaCoreProjectDirectory}/MeoAssistant.vcxproj";
|
||||
public const string MaaWpfProjectFilePath = $"{MaaWpfProjectDirectory}/MeoAsstGui.csproj";
|
||||
|
||||
public const string MaaBuildOutputDirectory = $"{MaaProjectRootDirectory}/x64";
|
||||
|
||||
public const string MaaCoreBuildIntermediatOutputDirectory = $"{MaaCoreProjectDirectory}/x64";
|
||||
|
||||
public static readonly string[] MaaCoreExtraFiles = new[] { "MeoAssistant.pdb", "MeoAssistant.lib", "MeoAssistant.exp" };
|
||||
|
||||
public static readonly string[] MaaWpfExtraFiles = new[] { "MeoAsstGui.pdb", "MeoAsstGui.exe.config" };
|
||||
}
|
||||
8
src/MeoAssistantBuilder/Directory.Build.props
Normal file
8
src/MeoAssistantBuilder/Directory.Build.props
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- This file prevents unintended imports of unrelated MSBuild files -->
|
||||
<!-- Uncomment to include parent Directory.Build.props file -->
|
||||
<!--<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />-->
|
||||
|
||||
</Project>
|
||||
8
src/MeoAssistantBuilder/Directory.Build.targets
Normal file
8
src/MeoAssistantBuilder/Directory.Build.targets
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- This file prevents unintended imports of unrelated MSBuild files -->
|
||||
<!-- Uncomment to include parent Directory.Build.targets file -->
|
||||
<!--<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />-->
|
||||
|
||||
</Project>
|
||||
@@ -1,17 +0,0 @@
|
||||
using Cake.Common.Tools.MSBuild;
|
||||
|
||||
namespace MeoAssistantBuilder.Helper;
|
||||
|
||||
public static class BuildCoreHelper
|
||||
{
|
||||
public static void BuildCore(this MaaBuildContext context, string configuration)
|
||||
{
|
||||
context.MSBuild(Constants.MaaCoreProjectFilePath, new MSBuildSettings
|
||||
{
|
||||
WorkingDirectory = Constants.MaaProjectRootDirectory,
|
||||
ToolPath = context.MsBuildExecutable,
|
||||
Configuration = configuration,
|
||||
PlatformTarget = PlatformTarget.x64
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Cake.Common.Tools.MSBuild;
|
||||
|
||||
namespace MeoAssistantBuilder.Helper;
|
||||
|
||||
public static class BuildWpfHelper
|
||||
{
|
||||
public static void BuildWpf(this MaaBuildContext context, string configuration)
|
||||
{
|
||||
context.MSBuild(Constants.MaaWpfProjectFilePath, new MSBuildSettings
|
||||
{
|
||||
WorkingDirectory = Constants.MaaProjectRootDirectory,
|
||||
Restore = true,
|
||||
ToolPath = context.MsBuildExecutable,
|
||||
Configuration = configuration,
|
||||
PlatformTarget = PlatformTarget.x64
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Common.IO;
|
||||
|
||||
namespace MeoAssistantBuilder.Helper;
|
||||
|
||||
public static class CleanDirectoryHelper
|
||||
{
|
||||
public static void CleanArtifacts(this MaaBuildContext context)
|
||||
{
|
||||
context.CleanDirectory(Constants.MaaProjectArtifactDirectory);
|
||||
if (Directory.Exists(Constants.MaaProjectArtifactDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(Constants.MaaProjectArtifactDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CleanCore(this MaaBuildContext context)
|
||||
{
|
||||
context.CleanDirectory(Constants.MaaBuildOutputDirectory);
|
||||
context.CleanDirectory(Constants.MaaCoreBuildIntermediatOutputDirectory);
|
||||
}
|
||||
|
||||
public static void CleanWpf(this MaaBuildContext context)
|
||||
{
|
||||
context.CleanDirectory(Constants.MaaBuildOutputDirectory);
|
||||
context.CleanDirectory(Path.Combine(Constants.MaaWpfProjectDirectory, "bin"));
|
||||
context.CleanDirectory(Path.Combine(Constants.MaaWpfProjectDirectory, "obj"));
|
||||
}
|
||||
|
||||
public static void CleanAll(this MaaBuildContext context)
|
||||
{
|
||||
CleanCore(context);
|
||||
CleanWpf(context);
|
||||
}
|
||||
|
||||
public static void RemoveExtraCore(this MaaBuildContext context, string buildOutput)
|
||||
{
|
||||
foreach (var extra in Constants.MaaCoreExtraFiles)
|
||||
{
|
||||
var file = Path.Combine(buildOutput, extra);
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.Delete(file);
|
||||
context.Information($"Delete file: {file}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveExtraWpf(this MaaBuildContext context, string buildOutput)
|
||||
{
|
||||
foreach (var extra in Constants.MaaWpfExtraFiles)
|
||||
{
|
||||
var file = Path.Combine(buildOutput, extra);
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.Delete(file);
|
||||
context.Information($"Delete file: {file}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Common.IO;
|
||||
|
||||
namespace MeoAssistantBuilder.Helper
|
||||
{
|
||||
public static class FileCopyHelper
|
||||
{
|
||||
public static void CopyThirdPartyDlls(this MaaBuildContext context, string outputDir)
|
||||
{
|
||||
var thirdPartyDlls = Directory.GetFiles(Path.Combine(Constants.MaaProjectThirdPartyDirectory, "bin"));
|
||||
foreach (var f in thirdPartyDlls)
|
||||
{
|
||||
var fileName = new FileInfo(f).Name;
|
||||
context.CopyFile(f, Path.Combine(outputDir, fileName));
|
||||
context.Information($"Copy file: FROM {f} to {Path.Combine(outputDir, fileName)}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyResources(this MaaBuildContext context, string outputDir)
|
||||
{
|
||||
var resourceTargetDir = Path.Combine(outputDir, "resource");
|
||||
var resourceThirdParty = Path.Combine(Constants.MaaProjectRootDirectory, "3rdparty\\resource");
|
||||
var resoutceMaa = Path.Combine(Constants.MaaProjectRootDirectory, "resource");
|
||||
|
||||
var files = new List<string>();
|
||||
var directories = new List<string>();
|
||||
|
||||
files.AddRange(Directory.GetFiles(resourceThirdParty));
|
||||
files.AddRange(Directory.GetFiles(resoutceMaa));
|
||||
directories.AddRange(Directory.GetDirectories(resourceThirdParty));
|
||||
directories.AddRange(Directory.GetDirectories(resoutceMaa));
|
||||
|
||||
if (Directory.Exists(resourceTargetDir) is false)
|
||||
{
|
||||
Directory.CreateDirectory(resourceTargetDir);
|
||||
}
|
||||
|
||||
foreach (var f in files)
|
||||
{
|
||||
var fileName = new FileInfo(f).Name;
|
||||
context.CopyFile(f, Path.Combine(resourceTargetDir, fileName));
|
||||
context.Information($"Copy file: FROM {f} TO {Path.Combine(resourceTargetDir, fileName)}");
|
||||
}
|
||||
|
||||
foreach (var d in directories)
|
||||
{
|
||||
var dirName = new DirectoryInfo(d).Name;
|
||||
context.CopyDirectory(d, Path.Combine(resourceTargetDir, dirName));
|
||||
context.Information($"Copy directory: FROM {d} TO {Path.Combine(resourceTargetDir, dirName)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Cake.Common.Build;
|
||||
using Cake.Common.Diagnostics;
|
||||
|
||||
namespace MeoAssistantBuilder.Helper;
|
||||
|
||||
public static class GetBuildInformationHelper
|
||||
{
|
||||
public static (string, string) GetBuildInformation(this MaaBuildContext context)
|
||||
{
|
||||
var ghAction = context.GitHubActions();
|
||||
|
||||
var buildTime = DateTime.UtcNow.AddHours(8);
|
||||
var bt = buildTime.ToString("yyyy-MM-dd-HH-mm-ss");
|
||||
string hash;
|
||||
|
||||
if (ghAction.IsRunningOnGitHubActions)
|
||||
{
|
||||
hash = ghAction.Environment.Workflow.Sha.ToLower()[..7];
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var realPath = new DirectoryInfo(Constants.MaaProjectRootDirectory).FullName;
|
||||
var repo = new LibGit2Sharp.Repository(realPath);
|
||||
var commit = repo.Commits.First();
|
||||
hash = commit.Sha.ToLower()[..7];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
context.Warning($"Failed to get git log: {e.Message}");
|
||||
hash = "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
return (bt, hash);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using Cake.Common;
|
||||
using Cake.Common.Tools.VSWhere;
|
||||
using Cake.Core;
|
||||
using Cake.Core.Diagnostics;
|
||||
using Cake.Frosting;
|
||||
|
||||
namespace MeoAssistantBuilder;
|
||||
|
||||
public class MaaBuildContext : FrostingContext
|
||||
{
|
||||
public string MsBuildExecutable { get; set; }
|
||||
|
||||
public MaaBuildContext(ICakeContext context) : base(context)
|
||||
{
|
||||
MsBuildExecutable = context.Argument<string>("tool", "");
|
||||
if (MsBuildExecutable == "")
|
||||
{
|
||||
var vsPath = context.VSWhereLatest();
|
||||
if (vsPath == null)
|
||||
{
|
||||
context.Log.Write(Verbosity.Normal, LogLevel.Fatal, "Can not find Visual Studio install path");
|
||||
System.Environment.Exit(-1);
|
||||
}
|
||||
MsBuildExecutable = Path.Combine(vsPath.FullPath, "Msbuild\\Current\\Bin\\MsBuild.exe");
|
||||
}
|
||||
context.Log.Information($"Use MsBuild at: {MsBuildExecutable}");
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,36 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<Platforms>x64</Platforms>
|
||||
<Configurations>Debug;Release;CICD</Configurations>
|
||||
<RootNamespace></RootNamespace>
|
||||
<NoWarn>CS0649;CS0169</NoWarn>
|
||||
<NukeRootDirectory>..\..</NukeRootDirectory>
|
||||
<NukeScriptDirectory>..\..</NukeScriptDirectory>
|
||||
<NukeTelemetryVersion>1</NukeTelemetryVersion>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cake.Frosting" Version="2.2.0" />
|
||||
<PackageReference Include="LibGit2Sharp" Version="0.27.0-preview-0102" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nuke.Common" Version="6.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageDownload Include="vswhere" Version="[3.0.2]" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="..\..\.github\workflows\release-maa-core.yml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="..\..\.github\workflows\release-maa-core.yml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="..\..\.github\workflows\release-maa-core.yml" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=HeapView_002EDelegateAllocation/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VariableHidesOuterVariable/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeMadeStatic_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Implicit</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_PRIVATE_MODIFIER/@EntryValue">Implicit</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">0</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ATTRIBUTE_LENGTH_FOR_SAME_LINE/@EntryValue">120</s:Int64>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -1,15 +0,0 @@
|
||||
using Cake.Frosting;
|
||||
using MeoAssistantBuilder;
|
||||
|
||||
var sArgs = new List<string>();
|
||||
foreach (var arg in args)
|
||||
{
|
||||
var sa = arg.Split(" ")
|
||||
.ToList();
|
||||
sa.RemoveAll(x => string.IsNullOrEmpty(x) || string.IsNullOrWhiteSpace(x));
|
||||
sArgs.AddRange(sa);
|
||||
}
|
||||
|
||||
return new CakeHost()
|
||||
.UseContext<MaaBuildContext>()
|
||||
.Run(sArgs);
|
||||
8
src/MeoAssistantBuilder/Properties/launchSettings.json
Normal file
8
src/MeoAssistantBuilder/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"MeoAssistantBuilder": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--target DevTest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,54 @@
|
||||
# MeoAssistantBuilder
|
||||
|
||||
MAA 构建项目
|
||||
Maa 的构建工具
|
||||
|
||||
## 构建 MAA
|
||||
## 使用方法
|
||||
|
||||
需要安装
|
||||
- `.NET SDK 6.0`
|
||||
- `.NET Framework SDK 4.8`
|
||||
- `MSVC v143 x64`
|
||||
- `MSBuild (VS2022)`
|
||||
> 请先安装 `.NET SDK 6.0.x`
|
||||
|
||||
在本项目根目录执行
|
||||
```
|
||||
dotnet run -- --target <TARGET>
|
||||
在解决方案根目录执行:
|
||||
|
||||
``` sh
|
||||
# PowerShell
|
||||
./build.ps1 --target <TARGET>
|
||||
# Command Prompt
|
||||
./build.cmd --target <TARGET>
|
||||
# Bash
|
||||
./build.sh --target <TARGET>
|
||||
```
|
||||
|
||||
TARGET 可选项
|
||||
`TARGET` 可选:
|
||||
|
||||
- `DevBuild`
|
||||
- `ReleaseCore`
|
||||
- `ReleaseWpf`
|
||||
- `ReleaseResource`
|
||||
- DevBuild
|
||||
- ReleaseMaa
|
||||
- ReleaseMaaCore
|
||||
- ReleaseMaaResource
|
||||
|
||||
关于各个 Target,请参考 [ActionConfiguration.cs](./ActionConfiguration.cs)
|
||||
|
||||
关于 Target 之间的流程联系,请在安装 `Nuke.GlobalTool` 后再 Repo 的任意位置执行
|
||||
|
||||
``` sh
|
||||
nuke --plan
|
||||
```
|
||||
|
||||
构建生成的文件将会在 `./artifacts` 中
|
||||
|
||||
[可选] 安装 `Nuke.GlobalTool`
|
||||
|
||||
``` sh
|
||||
dotnet tool install Nuke.GlobalTool --global
|
||||
```
|
||||
|
||||
> 使用 `ZSH` 时,请将 `export PATH=$HOME/.dotnet/tools:$PATH` 添加到 `.zshrc`
|
||||
|
||||
关于 Nuke,请参考 [官方文档](https://nuke.build/index.html)
|
||||
|
||||
## 注意事项
|
||||
|
||||
⚠ 每次执行时,会删除以下目录 ⚠
|
||||
|
||||
- ./artifacts
|
||||
- ./x64/Release
|
||||
- ./x64/RelWithDebInfo
|
||||
- ./x64/CICD
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Frosting;
|
||||
using MeoAssistantBuilder.Helper;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace MeoAssistantBuilder.Tasks;
|
||||
|
||||
[TaskName("DevBuild")]
|
||||
public sealed class DevBuildTask : FrostingTask<MaaBuildContext>
|
||||
{
|
||||
public override void Run(MaaBuildContext context)
|
||||
{
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("1. Get build information");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
context.CleanArtifacts();
|
||||
var (bt, hash) = context.GetBuildInformation();
|
||||
var artifact = $"MaaBundle-DevBuild-(CONF)-{hash}-{bt}.zip";
|
||||
context.Information($"Dev build of commit {hash} at {bt}");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("2. Build MaaBundle with configuration Release");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
context.CleanAll();
|
||||
|
||||
context.BuildCore("Release");
|
||||
context.BuildWpf("Release");
|
||||
var releaseOutput = Path.Combine(Constants.MaaBuildOutputDirectory, "Release");
|
||||
var releaseArtifact = Path.Combine(Constants.MaaProjectArtifactDirectory, artifact.Replace("(CONF)", "Release"));
|
||||
ZipFile.CreateFromDirectory(releaseOutput, releaseArtifact);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("3. Build MaaBundle with configuration RelWithDebInfo");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
context.CleanAll();
|
||||
|
||||
context.BuildCore("RelWithDebInfo");
|
||||
context.BuildWpf("RelWithDebInfo");
|
||||
var releaseDebugOutput = Path.Combine(Constants.MaaBuildOutputDirectory, "RelWithDebInfo");
|
||||
var releaseDebugArtifact = Path.Combine(Constants.MaaProjectArtifactDirectory, artifact.Replace("(CONF)", "RelWithDebInfo"));
|
||||
ZipFile.CreateFromDirectory(releaseDebugOutput, releaseDebugArtifact);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("4. Build MaaBundle with configuration CICD");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
context.CleanAll();
|
||||
|
||||
context.BuildCore("CICD");
|
||||
context.BuildWpf("CICD");
|
||||
var releaseCiOutput = Path.Combine(Constants.MaaBuildOutputDirectory, "CICD");
|
||||
var releaseCiArtifact = Path.Combine(Constants.MaaProjectArtifactDirectory, artifact.Replace("(CONF)", "CICD"));
|
||||
context.CopyThirdPartyDlls(releaseCiOutput);
|
||||
context.CopyResources(releaseCiOutput);
|
||||
ZipFile.CreateFromDirectory(releaseCiOutput, releaseCiArtifact);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using Cake.Common.Build;
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Frosting;
|
||||
using MeoAssistantBuilder.Helper;
|
||||
using System.IO.Compression;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MeoAssistantBuilder.Tasks;
|
||||
|
||||
[TaskName("ReleaseBundle")]
|
||||
public sealed class ReleaseBundleTask : FrostingTask<MaaBuildContext>
|
||||
{
|
||||
public override void Run(MaaBuildContext context)
|
||||
{
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("1. Read MaaCore version string");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var version = "UNKNOWN";
|
||||
var versionFile = Path.Combine(Constants.MaaCoreProjectDirectory, "Version.h");
|
||||
var versionFileContent = File.ReadAllText(versionFile);
|
||||
|
||||
var regex = @"v((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)";
|
||||
|
||||
var match = Regex.Match(versionFileContent, regex);
|
||||
if (match.Success is false)
|
||||
{
|
||||
context.Warning("Can not read version");
|
||||
Environment.Exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
version = match.Value;
|
||||
}
|
||||
|
||||
var ghActions = context.GitHubActions();
|
||||
if (ghActions.IsRunningOnGitHubActions is false)
|
||||
{
|
||||
version += "-Local";
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Information($"Running in GitHub Action with workflow name: {ghActions.Environment.Workflow.Workflow}, ref: {ghActions.Environment.Workflow.Ref}");
|
||||
if (ghActions.Environment.Workflow.Workflow != "Release MaaCore")
|
||||
{
|
||||
version += $"-{ghActions.Environment.Workflow.RunId}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var tag = ghActions.Environment.Workflow.Ref.Replace("refs/tags/", "");
|
||||
if (tag != version)
|
||||
{
|
||||
context.Error($"Version do not match. From File: {version}. From Ref: {tag}");
|
||||
Environment.Exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.Information($"MaaCore Version: {version}");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("2. Release MaaCore with third party dlls and resource");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var buildOutput = Path.Combine(Constants.MaaBuildOutputDirectory, "Release");
|
||||
context.CleanAll();
|
||||
context.CleanArtifacts();
|
||||
|
||||
context.BuildCore("Release");
|
||||
context.RemoveExtraCore(buildOutput);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("3. Release MaaWpf with third party executables");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
context.BuildWpf("Release");
|
||||
context.RemoveExtraWpf(buildOutput);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("4. Bundle MaaBundle package");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var bundle = Path.Combine(Constants.MaaProjectArtifactDirectory, $"MaaBundle-{version}.zip");
|
||||
ZipFile.CreateFromDirectory(buildOutput, bundle);
|
||||
|
||||
context.Information($"Bundled MaaBundle file: {bundle}");
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
using Cake.Common.Build;
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Frosting;
|
||||
using MeoAssistantBuilder.Helper;
|
||||
using System.IO.Compression;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MeoAssistantBuilder.Tasks;
|
||||
|
||||
[TaskName("ReleaseCore")]
|
||||
public sealed class ReleaseCoreTask : FrostingTask<MaaBuildContext>
|
||||
{
|
||||
public override void Run(MaaBuildContext context)
|
||||
{
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("1. Read MaaCore version string");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var version = "UNKNOWN";
|
||||
var versionFile = Path.Combine(Constants.MaaCoreProjectDirectory, "Version.h");
|
||||
var versionFileContent = File.ReadAllText(versionFile);
|
||||
|
||||
var regex = @"v((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)";
|
||||
|
||||
var match = Regex.Match(versionFileContent, regex);
|
||||
if (match.Success is false)
|
||||
{
|
||||
context.Warning("Can not read version");
|
||||
Environment.Exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
version = match.Value;
|
||||
}
|
||||
|
||||
var ghActions = context.GitHubActions();
|
||||
if (ghActions.IsRunningOnGitHubActions is false)
|
||||
{
|
||||
version += "-Local";
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Information($"Running in GitHub Action with workflow name: {ghActions.Environment.Workflow.Workflow}, ref: {ghActions.Environment.Workflow.Ref}");
|
||||
if (ghActions.Environment.Workflow.Workflow != "Release MaaCore")
|
||||
{
|
||||
version += $"-{ghActions.Environment.Workflow.RunId}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var tag = ghActions.Environment.Workflow.Ref.Replace("refs/tags/", "");
|
||||
if (tag != version)
|
||||
{
|
||||
context.Error($"Version do not match. From File: {version}. From Ref: {tag}");
|
||||
Environment.Exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.Information($"MaaCore Version: {version}");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("2. Build MaaCore with CICD configuration");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
context.CleanCore();
|
||||
context.CleanArtifacts();
|
||||
context.BuildCore("CICD");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("3. Remove extra files from build output");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var buildOutput = Path.Combine(Constants.MaaBuildOutputDirectory, "CICD");
|
||||
context.RemoveExtraCore(buildOutput);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("4. Copy 3rd party library DLLs to output directory");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var thirdPartyDlls = Directory.GetFiles(Path.Combine(Constants.MaaProjectThirdPartyDirectory, "bin"));
|
||||
foreach (var f in thirdPartyDlls)
|
||||
{
|
||||
var fileName = new FileInfo(f).Name;
|
||||
File.Copy(f, Path.Combine(buildOutput, fileName));
|
||||
context.Information($"Copy file: FROM {f} to {Path.Combine(buildOutput, fileName)}");
|
||||
}
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("5. Bundle MaaCore DLLs");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var bundle = Path.Combine(Constants.MaaProjectArtifactDirectory, $"MaaCore-{version}.zip");
|
||||
ZipFile.CreateFromDirectory(buildOutput, bundle);
|
||||
|
||||
context.Information($"Bundled MAACore DLLs file: {bundle}");
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Frosting;
|
||||
using MeoAssistantBuilder.Helper;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace MeoAssistantBuilder.Tasks;
|
||||
|
||||
[TaskName("ReleaseResource")]
|
||||
public sealed class ReleaseResourceTask : FrostingTask<MaaBuildContext>
|
||||
{
|
||||
public override void Run(MaaBuildContext context)
|
||||
{
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("1. Get bundle information");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var (hash, bt) = context.GetBuildInformation();
|
||||
context.CleanArtifacts();
|
||||
var version = $"{hash}-{bt}";
|
||||
context.Information($"MaaResource Version: {version}");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("2. Copy MaaResource");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var resDir = Path.Combine(Constants.MaaBuildOutputDirectory, "resource");
|
||||
if (Directory.Exists(resDir) is false)
|
||||
{
|
||||
Directory.CreateDirectory(resDir);
|
||||
}
|
||||
context.CopyResources(resDir);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("3. Bundle MaaResource");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var bundle = Path.Combine(Constants.MaaProjectArtifactDirectory, $"MaaResource-{version}.zip");
|
||||
ZipFile.CreateFromDirectory(resDir, bundle);
|
||||
|
||||
context.Information($"Bundled MaaResource file: {bundle}");
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Cake.Common.Diagnostics;
|
||||
using Cake.Frosting;
|
||||
using MeoAssistantBuilder.Helper;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace MeoAssistantBuilder.Tasks;
|
||||
|
||||
[TaskName("ReleaseWpf")]
|
||||
public sealed class ReleaseWpfTask : FrostingTask<MaaBuildContext>
|
||||
{
|
||||
public override void Run(MaaBuildContext context)
|
||||
{
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("1. Build MaaWpf with ReleaseCore configuration");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var (hash, bt) = context.GetBuildInformation();
|
||||
context.CleanWpf();
|
||||
context.CleanArtifacts();
|
||||
context.BuildWpf("CICD");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("2. Remove extra files from build output");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var buildOutput = Path.Combine(Constants.MaaBuildOutputDirectory, "CICD");
|
||||
context.RemoveExtraWpf(buildOutput);
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("3. Set MaaWpf Version Number");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var version = $"{hash}-{bt}";
|
||||
context.Information($"MaaWpf Version: {version}");
|
||||
|
||||
context.Information("--------------------------------------------------");
|
||||
context.Information("4. Bundle MaaWpf Executables");
|
||||
context.Information("--------------------------------------------------");
|
||||
|
||||
var bundle = Path.Combine(Constants.MaaProjectArtifactDirectory, $"MaaWpf-{version}.zip");
|
||||
ZipFile.CreateFromDirectory(buildOutput, bundle);
|
||||
|
||||
context.Information($"Bundled MaaWpf Executables file: {bundle}");
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
<Application x:Class="MeoAsstGui.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:MeoAsstGui"
|
||||
xmlns:s="https://github.com/canton7/Stylet">
|
||||
<Application.Resources>
|
||||
<!--<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Indigo.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>-->
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<s:ApplicationLoader>
|
||||
<s:ApplicationLoader.Bootstrapper>
|
||||
<local:Bootstrapper />
|
||||
</s:ApplicationLoader.Bootstrapper>
|
||||
</s:ApplicationLoader>
|
||||
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
|
||||
<ResourceDictionary Source="Resources/Icon.xaml" />
|
||||
<ResourceDictionary Source="Resources/Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
<Application x:Class="MeoAsstGui.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:MeoAsstGui"
|
||||
xmlns:s="https://github.com/canton7/Stylet">
|
||||
<Application.Resources>
|
||||
<!--<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Indigo.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>-->
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<s:ApplicationLoader>
|
||||
<s:ApplicationLoader.Bootstrapper>
|
||||
<local:Bootstrapper />
|
||||
</s:ApplicationLoader.Bootstrapper>
|
||||
</s:ApplicationLoader>
|
||||
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
|
||||
<ResourceDictionary Source="Resources/Icon.xaml" />
|
||||
<ResourceDictionary Source="Resources/Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -16,6 +16,7 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -311,6 +312,34 @@ namespace MeoAsstGui
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 开发版、测试版不检查更新
|
||||
// 正式版:vX.X.X
|
||||
// DevBuild (CI):yyyy-MM-dd-HH-mm-ss-{CommitHash[..7]}
|
||||
// DevBuild (Local):yyyy-MM-dd-HH-mm-ss-{CommitHash[..7]}-Local
|
||||
// Release (Local Commit):v.{CommitHash[..7]}-Local
|
||||
// Release (Local Tag):{Tag}-Local
|
||||
// Debug (Local):DEBUG VERSION
|
||||
// Script Compiled:c{CommitHash[..7]}
|
||||
if (_curVersion == "DEBUG VERSION")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_curVersion.StartsWith("c"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_curVersion.Contains("Local"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var pattern = @"v((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)";
|
||||
var match = Regex.Match(_curVersion, pattern);
|
||||
if (match.Success is false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const int requestRetryMaxTimes = 5;
|
||||
var response = RequestApi(RequestUrl);
|
||||
for (int i = 0; response.Length == 0 && i >= requestRetryMaxTimes; i++)
|
||||
|
||||
2
src/dart/.gitignore
vendored
2
src/dart/.gitignore
vendored
@@ -3,11 +3,13 @@
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
*.exp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
cmake-build-debug/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
||||
1
src/dart/example/.gitignore
vendored
1
src/dart/example/.gitignore
vendored
@@ -15,6 +15,7 @@
|
||||
*.iws
|
||||
.idea/
|
||||
resource/
|
||||
runtime/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 5464c5bac742001448fe4fc0597be939379f88ea
|
||||
revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
- platform: linux
|
||||
create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
- platform: windows
|
||||
create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
||||
@@ -62,7 +62,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
@override
|
||||
void initState() {
|
||||
setState(() {
|
||||
_asst = MaaCore(p.current, callback);
|
||||
_asst = MaaCore(p.join(p.current), callback);
|
||||
_asst.connect('adb', 'emulator-5554');
|
||||
});
|
||||
super.initState();
|
||||
@@ -95,4 +95,5 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
maa_core
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
@@ -14,3 +17,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
||||
|
||||
@@ -42,7 +42,7 @@ packages:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
version: "1.16.0"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -56,7 +56,7 @@ packages:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
ffi:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -108,7 +108,7 @@ packages:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
version: "0.1.4"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -122,7 +122,7 @@ packages:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.8.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -134,7 +134,7 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -169,21 +169,14 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.8"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "0.4.9"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
sdks:
|
||||
dart: ">=2.16.2 <3.0.0"
|
||||
dart: ">=2.17.0-0 <3.0.0"
|
||||
flutter: ">=2.5.0"
|
||||
|
||||
17
src/dart/example/windows/.gitignore
vendored
Normal file
17
src/dart/example/windows/.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
flutter/ephemeral/
|
||||
|
||||
# Visual Studio user-specific files.
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Visual Studio build-related files.
|
||||
x64/
|
||||
x86/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
101
src/dart/example/windows/CMakeLists.txt
Normal file
101
src/dart/example/windows/CMakeLists.txt
Normal file
@@ -0,0 +1,101 @@
|
||||
# Project-level configuration.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
# The name of the executable created for the application. Change this to change
|
||||
# the on-disk name of your application.
|
||||
set(BINARY_NAME "example")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
# Define build configuration option.
|
||||
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(IS_MULTICONFIG)
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
||||
CACHE STRING "" FORCE)
|
||||
else()
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
endif()
|
||||
# Define settings for the Profile build mode.
|
||||
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
# Use Unicode for all projects.
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
#
|
||||
# Be cautious about adding new options here, as plugins use this function by
|
||||
# default. In most cases, you should add new options to specific targets instead
|
||||
# of modifying this function.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
||||
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
||||
target_compile_options(${TARGET} PRIVATE /EHsc)
|
||||
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
||||
endfunction()
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# Application build; see runner/CMakeLists.txt.
|
||||
add_subdirectory("runner")
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# Support files are copied into place next to the executable, so that it can
|
||||
# run in place. This is done instead of making a separate bundle (as on Linux)
|
||||
# so that building and running from within Visual Studio will work.
|
||||
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
|
||||
# Make the "install" step default, as it's required to run.
|
||||
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
CONFIGURATIONS Profile;Release
|
||||
COMPONENT Runtime)
|
||||
104
src/dart/example/windows/flutter/CMakeLists.txt
Normal file
104
src/dart/example/windows/flutter/CMakeLists.txt
Normal file
@@ -0,0 +1,104 @@
|
||||
# This file controls Flutter-level build steps. It should not be edited.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
|
||||
|
||||
# === Flutter Library ===
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"flutter_export.h"
|
||||
"flutter_windows.h"
|
||||
"flutter_messenger.h"
|
||||
"flutter_plugin_registrar.h"
|
||||
"flutter_texture_registrar.h"
|
||||
)
|
||||
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Wrapper ===
|
||||
list(APPEND CPP_WRAPPER_SOURCES_CORE
|
||||
"core_implementations.cc"
|
||||
"standard_codec.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
|
||||
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
|
||||
"plugin_registrar.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
|
||||
list(APPEND CPP_WRAPPER_SOURCES_APP
|
||||
"flutter_engine.cc"
|
||||
"flutter_view_controller.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
|
||||
|
||||
# Wrapper sources needed for a plugin.
|
||||
add_library(flutter_wrapper_plugin STATIC
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
)
|
||||
apply_standard_settings(flutter_wrapper_plugin)
|
||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
|
||||
target_include_directories(flutter_wrapper_plugin PUBLIC
|
||||
"${WRAPPER_ROOT}/include"
|
||||
)
|
||||
add_dependencies(flutter_wrapper_plugin flutter_assemble)
|
||||
|
||||
# Wrapper sources needed for the runner.
|
||||
add_library(flutter_wrapper_app STATIC
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
)
|
||||
apply_standard_settings(flutter_wrapper_app)
|
||||
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
|
||||
target_include_directories(flutter_wrapper_app PUBLIC
|
||||
"${WRAPPER_ROOT}/include"
|
||||
)
|
||||
add_dependencies(flutter_wrapper_app flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
|
||||
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
${PHONY_OUTPUT}
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
|
||||
windows-x64 $<CONFIG>
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter/plugin_registry.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||
23
src/dart/example/windows/flutter/generated_plugins.cmake
Normal file
23
src/dart/example/windows/flutter/generated_plugins.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
||||
32
src/dart/example/windows/runner/CMakeLists.txt
Normal file
32
src/dart/example/windows/runner/CMakeLists.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
# Define the application target. To change its name, change BINARY_NAME in the
|
||||
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
||||
# work.
|
||||
#
|
||||
# Any new source files that you add to the application should be added here.
|
||||
add_executable(${BINARY_NAME} WIN32
|
||||
"flutter_window.cpp"
|
||||
"main.cpp"
|
||||
"utils.cpp"
|
||||
"win32_window.cpp"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
"Runner.rc"
|
||||
"runner.exe.manifest"
|
||||
)
|
||||
|
||||
# Apply the standard set of build settings. This can be removed for applications
|
||||
# that need different build settings.
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
|
||||
# Disable Windows macros that collide with C++ standard library functions.
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
||||
|
||||
# Add dependency libraries and include directories. Add any application-specific
|
||||
# dependencies here.
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
# Run the Flutter tool portions of the build. This must not be removed.
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
121
src/dart/example/windows/runner/Runner.rc
Normal file
121
src/dart/example/windows/runner/Runner.rc
Normal file
@@ -0,0 +1,121 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#pragma code_page(65001)
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_APP_ICON ICON "resources\\app_icon.ico"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
#ifdef FLUTTER_BUILD_NUMBER
|
||||
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
|
||||
#else
|
||||
#define VERSION_AS_NUMBER 1,0,0
|
||||
#endif
|
||||
|
||||
#ifdef FLUTTER_BUILD_NAME
|
||||
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
|
||||
#else
|
||||
#define VERSION_AS_STRING "1.0.0"
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_AS_NUMBER
|
||||
PRODUCTVERSION VERSION_AS_NUMBER
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "com.example" "\0"
|
||||
VALUE "FileDescription", "example" "\0"
|
||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||
VALUE "InternalName", "example" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "example.exe" "\0"
|
||||
VALUE "ProductName", "example" "\0"
|
||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
61
src/dart/example/windows/runner/flutter_window.cpp
Normal file
61
src/dart/example/windows/runner/flutter_window.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "flutter_window.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "flutter/generated_plugin_registrant.h"
|
||||
|
||||
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
||||
: project_(project) {}
|
||||
|
||||
FlutterWindow::~FlutterWindow() {}
|
||||
|
||||
bool FlutterWindow::OnCreate() {
|
||||
if (!Win32Window::OnCreate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT frame = GetClientArea();
|
||||
|
||||
// The size here must match the window dimensions to avoid unnecessary surface
|
||||
// creation / destruction in the startup path.
|
||||
flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
|
||||
frame.right - frame.left, frame.bottom - frame.top, project_);
|
||||
// Ensure that basic setup of the controller was successful.
|
||||
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
|
||||
return false;
|
||||
}
|
||||
RegisterPlugins(flutter_controller_->engine());
|
||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlutterWindow::OnDestroy() {
|
||||
if (flutter_controller_) {
|
||||
flutter_controller_ = nullptr;
|
||||
}
|
||||
|
||||
Win32Window::OnDestroy();
|
||||
}
|
||||
|
||||
LRESULT
|
||||
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
// Give Flutter, including plugins, an opportunity to handle window messages.
|
||||
if (flutter_controller_) {
|
||||
std::optional<LRESULT> result =
|
||||
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
||||
lparam);
|
||||
if (result) {
|
||||
return *result;
|
||||
}
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_FONTCHANGE:
|
||||
flutter_controller_->engine()->ReloadSystemFonts();
|
||||
break;
|
||||
}
|
||||
|
||||
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
|
||||
}
|
||||
33
src/dart/example/windows/runner/flutter_window.h
Normal file
33
src/dart/example/windows/runner/flutter_window.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
||||
#define RUNNER_FLUTTER_WINDOW_H_
|
||||
|
||||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "win32_window.h"
|
||||
|
||||
// A window that does nothing but host a Flutter view.
|
||||
class FlutterWindow : public Win32Window {
|
||||
public:
|
||||
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||||
explicit FlutterWindow(const flutter::DartProject& project);
|
||||
virtual ~FlutterWindow();
|
||||
|
||||
protected:
|
||||
// Win32Window:
|
||||
bool OnCreate() override;
|
||||
void OnDestroy() override;
|
||||
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept override;
|
||||
|
||||
private:
|
||||
// The project to run.
|
||||
flutter::DartProject project_;
|
||||
|
||||
// The Flutter instance hosted by this window.
|
||||
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
|
||||
};
|
||||
|
||||
#endif // RUNNER_FLUTTER_WINDOW_H_
|
||||
43
src/dart/example/windows/runner/main.cpp
Normal file
43
src/dart/example/windows/runner/main.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "flutter_window.h"
|
||||
#include "utils.h"
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||
CreateAndAttachConsole();
|
||||
}
|
||||
|
||||
// Initialize COM, so that it is available for use in the library and/or
|
||||
// plugins.
|
||||
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
|
||||
flutter::DartProject project(L"data");
|
||||
|
||||
std::vector<std::string> command_line_arguments =
|
||||
GetCommandLineArguments();
|
||||
|
||||
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||
|
||||
FlutterWindow window(project);
|
||||
Win32Window::Point origin(10, 10);
|
||||
Win32Window::Size size(1280, 720);
|
||||
if (!window.CreateAndShow(L"example", origin, size)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
window.SetQuitOnClose(true);
|
||||
|
||||
::MSG msg;
|
||||
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
::CoUninitialize();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
16
src/dart/example/windows/runner/resource.h
Normal file
16
src/dart/example/windows/runner/resource.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Runner.rc
|
||||
//
|
||||
#define IDI_APP_ICON 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
BIN
src/dart/example/windows/runner/resources/app_icon.ico
Normal file
BIN
src/dart/example/windows/runner/resources/app_icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
20
src/dart/example/windows/runner/runner.exe.manifest
Normal file
20
src/dart/example/windows/runner/runner.exe.manifest
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
64
src/dart/example/windows/runner/utils.cpp
Normal file
64
src/dart/example/windows/runner/utils.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <flutter_windows.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void CreateAndAttachConsole() {
|
||||
if (::AllocConsole()) {
|
||||
FILE *unused;
|
||||
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
|
||||
_dup2(_fileno(stdout), 1);
|
||||
}
|
||||
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
|
||||
_dup2(_fileno(stdout), 2);
|
||||
}
|
||||
std::ios::sync_with_stdio();
|
||||
FlutterDesktopResyncOutputStreams();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> GetCommandLineArguments() {
|
||||
// Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
|
||||
int argc;
|
||||
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||
if (argv == nullptr) {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
std::vector<std::string> command_line_arguments;
|
||||
|
||||
// Skip the first argument as it's the binary name.
|
||||
for (int i = 1; i < argc; i++) {
|
||||
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
|
||||
}
|
||||
|
||||
::LocalFree(argv);
|
||||
|
||||
return command_line_arguments;
|
||||
}
|
||||
|
||||
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
|
||||
if (utf16_string == nullptr) {
|
||||
return std::string();
|
||||
}
|
||||
int target_length = ::WideCharToMultiByte(
|
||||
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||
-1, nullptr, 0, nullptr, nullptr);
|
||||
std::string utf8_string;
|
||||
if (target_length == 0 || target_length > utf8_string.max_size()) {
|
||||
return utf8_string;
|
||||
}
|
||||
utf8_string.resize(target_length);
|
||||
int converted_length = ::WideCharToMultiByte(
|
||||
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||
-1, utf8_string.data(),
|
||||
target_length, nullptr, nullptr);
|
||||
if (converted_length == 0) {
|
||||
return std::string();
|
||||
}
|
||||
return utf8_string;
|
||||
}
|
||||
19
src/dart/example/windows/runner/utils.h
Normal file
19
src/dart/example/windows/runner/utils.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef RUNNER_UTILS_H_
|
||||
#define RUNNER_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Creates a console for the process, and redirects stdout and stderr to
|
||||
// it for both the runner and the Flutter library.
|
||||
void CreateAndAttachConsole();
|
||||
|
||||
// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
|
||||
// encoded in UTF-8. Returns an empty std::string on failure.
|
||||
std::string Utf8FromUtf16(const wchar_t* utf16_string);
|
||||
|
||||
// Gets the command line arguments passed in as a std::vector<std::string>,
|
||||
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
|
||||
std::vector<std::string> GetCommandLineArguments();
|
||||
|
||||
#endif // RUNNER_UTILS_H_
|
||||
245
src/dart/example/windows/runner/win32_window.cpp
Normal file
245
src/dart/example/windows/runner/win32_window.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#include "win32_window.h"
|
||||
|
||||
#include <flutter_windows.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
||||
|
||||
// The number of Win32Window objects that currently exist.
|
||||
static int g_active_window_count = 0;
|
||||
|
||||
using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
|
||||
|
||||
// Scale helper to convert logical scaler values to physical using passed in
|
||||
// scale factor
|
||||
int Scale(int source, double scale_factor) {
|
||||
return static_cast<int>(source * scale_factor);
|
||||
}
|
||||
|
||||
// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
|
||||
// This API is only needed for PerMonitor V1 awareness mode.
|
||||
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
|
||||
HMODULE user32_module = LoadLibraryA("User32.dll");
|
||||
if (!user32_module) {
|
||||
return;
|
||||
}
|
||||
auto enable_non_client_dpi_scaling =
|
||||
reinterpret_cast<EnableNonClientDpiScaling*>(
|
||||
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
|
||||
if (enable_non_client_dpi_scaling != nullptr) {
|
||||
enable_non_client_dpi_scaling(hwnd);
|
||||
FreeLibrary(user32_module);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Manages the Win32Window's window class registration.
|
||||
class WindowClassRegistrar {
|
||||
public:
|
||||
~WindowClassRegistrar() = default;
|
||||
|
||||
// Returns the singleton registar instance.
|
||||
static WindowClassRegistrar* GetInstance() {
|
||||
if (!instance_) {
|
||||
instance_ = new WindowClassRegistrar();
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
// Returns the name of the window class, registering the class if it hasn't
|
||||
// previously been registered.
|
||||
const wchar_t* GetWindowClass();
|
||||
|
||||
// Unregisters the window class. Should only be called if there are no
|
||||
// instances of the window.
|
||||
void UnregisterWindowClass();
|
||||
|
||||
private:
|
||||
WindowClassRegistrar() = default;
|
||||
|
||||
static WindowClassRegistrar* instance_;
|
||||
|
||||
bool class_registered_ = false;
|
||||
};
|
||||
|
||||
WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
|
||||
|
||||
const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
||||
if (!class_registered_) {
|
||||
WNDCLASS window_class{};
|
||||
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
window_class.lpszClassName = kWindowClassName;
|
||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||
window_class.cbClsExtra = 0;
|
||||
window_class.cbWndExtra = 0;
|
||||
window_class.hInstance = GetModuleHandle(nullptr);
|
||||
window_class.hIcon =
|
||||
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
|
||||
window_class.hbrBackground = 0;
|
||||
window_class.lpszMenuName = nullptr;
|
||||
window_class.lpfnWndProc = Win32Window::WndProc;
|
||||
RegisterClass(&window_class);
|
||||
class_registered_ = true;
|
||||
}
|
||||
return kWindowClassName;
|
||||
}
|
||||
|
||||
void WindowClassRegistrar::UnregisterWindowClass() {
|
||||
UnregisterClass(kWindowClassName, nullptr);
|
||||
class_registered_ = false;
|
||||
}
|
||||
|
||||
Win32Window::Win32Window() {
|
||||
++g_active_window_count;
|
||||
}
|
||||
|
||||
Win32Window::~Win32Window() {
|
||||
--g_active_window_count;
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool Win32Window::CreateAndShow(const std::wstring& title,
|
||||
const Point& origin,
|
||||
const Size& size) {
|
||||
Destroy();
|
||||
|
||||
const wchar_t* window_class =
|
||||
WindowClassRegistrar::GetInstance()->GetWindowClass();
|
||||
|
||||
const POINT target_point = {static_cast<LONG>(origin.x),
|
||||
static_cast<LONG>(origin.y)};
|
||||
HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
|
||||
UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
|
||||
double scale_factor = dpi / 96.0;
|
||||
|
||||
HWND window = CreateWindow(
|
||||
window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
|
||||
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
||||
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
||||
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return OnCreate();
|
||||
}
|
||||
|
||||
// static
|
||||
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
if (message == WM_NCCREATE) {
|
||||
auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
||||
SetWindowLongPtr(window, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
|
||||
|
||||
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
||||
EnableFullDpiSupportIfAvailable(window);
|
||||
that->window_handle_ = window;
|
||||
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
||||
return that->MessageHandler(window, message, wparam, lparam);
|
||||
}
|
||||
|
||||
return DefWindowProc(window, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT
|
||||
Win32Window::MessageHandler(HWND hwnd,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
switch (message) {
|
||||
case WM_DESTROY:
|
||||
window_handle_ = nullptr;
|
||||
Destroy();
|
||||
if (quit_on_close_) {
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_DPICHANGED: {
|
||||
auto newRectSize = reinterpret_cast<RECT*>(lparam);
|
||||
LONG newWidth = newRectSize->right - newRectSize->left;
|
||||
LONG newHeight = newRectSize->bottom - newRectSize->top;
|
||||
|
||||
SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
|
||||
newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
case WM_SIZE: {
|
||||
RECT rect = GetClientArea();
|
||||
if (child_content_ != nullptr) {
|
||||
// Size and position the child window.
|
||||
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top, TRUE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_ACTIVATE:
|
||||
if (child_content_ != nullptr) {
|
||||
SetFocus(child_content_);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(window_handle_, message, wparam, lparam);
|
||||
}
|
||||
|
||||
void Win32Window::Destroy() {
|
||||
OnDestroy();
|
||||
|
||||
if (window_handle_) {
|
||||
DestroyWindow(window_handle_);
|
||||
window_handle_ = nullptr;
|
||||
}
|
||||
if (g_active_window_count == 0) {
|
||||
WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
|
||||
}
|
||||
}
|
||||
|
||||
Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
|
||||
return reinterpret_cast<Win32Window*>(
|
||||
GetWindowLongPtr(window, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
void Win32Window::SetChildContent(HWND content) {
|
||||
child_content_ = content;
|
||||
SetParent(content, window_handle_);
|
||||
RECT frame = GetClientArea();
|
||||
|
||||
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
|
||||
frame.bottom - frame.top, true);
|
||||
|
||||
SetFocus(child_content_);
|
||||
}
|
||||
|
||||
RECT Win32Window::GetClientArea() {
|
||||
RECT frame;
|
||||
GetClientRect(window_handle_, &frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
HWND Win32Window::GetHandle() {
|
||||
return window_handle_;
|
||||
}
|
||||
|
||||
void Win32Window::SetQuitOnClose(bool quit_on_close) {
|
||||
quit_on_close_ = quit_on_close;
|
||||
}
|
||||
|
||||
bool Win32Window::OnCreate() {
|
||||
// No-op; provided for subclasses.
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32Window::OnDestroy() {
|
||||
// No-op; provided for subclasses.
|
||||
}
|
||||
98
src/dart/example/windows/runner/win32_window.h
Normal file
98
src/dart/example/windows/runner/win32_window.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#ifndef RUNNER_WIN32_WINDOW_H_
|
||||
#define RUNNER_WIN32_WINDOW_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
|
||||
// inherited from by classes that wish to specialize with custom
|
||||
// rendering and input handling
|
||||
class Win32Window {
|
||||
public:
|
||||
struct Point {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
|
||||
};
|
||||
|
||||
struct Size {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
Size(unsigned int width, unsigned int height)
|
||||
: width(width), height(height) {}
|
||||
};
|
||||
|
||||
Win32Window();
|
||||
virtual ~Win32Window();
|
||||
|
||||
// Creates and shows a win32 window with |title| and position and size using
|
||||
// |origin| and |size|. New windows are created on the default monitor. Window
|
||||
// sizes are specified to the OS in physical pixels, hence to ensure a
|
||||
// consistent size to will treat the width height passed in to this function
|
||||
// as logical pixels and scale to appropriate for the default monitor. Returns
|
||||
// true if the window was created successfully.
|
||||
bool CreateAndShow(const std::wstring& title,
|
||||
const Point& origin,
|
||||
const Size& size);
|
||||
|
||||
// Release OS resources associated with window.
|
||||
void Destroy();
|
||||
|
||||
// Inserts |content| into the window tree.
|
||||
void SetChildContent(HWND content);
|
||||
|
||||
// Returns the backing Window handle to enable clients to set icon and other
|
||||
// window properties. Returns nullptr if the window has been destroyed.
|
||||
HWND GetHandle();
|
||||
|
||||
// If true, closing this window will quit the application.
|
||||
void SetQuitOnClose(bool quit_on_close);
|
||||
|
||||
// Return a RECT representing the bounds of the current client area.
|
||||
RECT GetClientArea();
|
||||
|
||||
protected:
|
||||
// Processes and route salient window messages for mouse handling,
|
||||
// size change and DPI. Delegates handling of these to member overloads that
|
||||
// inheriting classes can handle.
|
||||
virtual LRESULT MessageHandler(HWND window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept;
|
||||
|
||||
// Called when CreateAndShow is called, allowing subclass window-related
|
||||
// setup. Subclasses should return false if setup fails.
|
||||
virtual bool OnCreate();
|
||||
|
||||
// Called when Destroy is called.
|
||||
virtual void OnDestroy();
|
||||
|
||||
private:
|
||||
friend class WindowClassRegistrar;
|
||||
|
||||
// OS callback called by message pump. Handles the WM_NCCREATE message which
|
||||
// is passed when the non-client area is being created and enables automatic
|
||||
// non-client DPI scaling so that the non-client area automatically
|
||||
// responsponds to changes in DPI. All other messages are handled by
|
||||
// MessageHandler.
|
||||
static LRESULT CALLBACK WndProc(HWND const window,
|
||||
UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept;
|
||||
|
||||
// Retrieves a class instance pointer for |window|
|
||||
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
|
||||
|
||||
bool quit_on_close_ = false;
|
||||
|
||||
// window handle for top level window.
|
||||
HWND window_handle_ = nullptr;
|
||||
|
||||
// window handle for hosted content.
|
||||
HWND child_content_ = nullptr;
|
||||
};
|
||||
|
||||
#endif // RUNNER_WIN32_WINDOW_H_
|
||||
@@ -1,85 +1,150 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:maa_core/typedefs.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
class MaaCore implements MaaCoreInterface {
|
||||
late Assistant _asst;
|
||||
late AsstLoadResourceFunc _asstLoadResource;
|
||||
late AsstCreateFunc _asstCreate;
|
||||
late AsstCreateExFunc _asstCreateEx;
|
||||
late AsstConnectFunc _asstConnect;
|
||||
late AsstDestroyFunc _asstDestroy;
|
||||
late AsstAppendTaskFunc _asstAppendTask;
|
||||
late AsstSetTaskParamsFunc _asstSetTaskParams;
|
||||
late AsstStartFunc _asstStart;
|
||||
late AsstStopFunc _asstStop;
|
||||
late AsstCtrlerClickFunc _asstCtrlerClick;
|
||||
late AsstGetVersionFunc _asstGetVersion;
|
||||
late AsstLogFunc _asstLog;
|
||||
|
||||
// Native Symbols
|
||||
// MeoAssistant
|
||||
static late AsstLoadResourceFunc _asstLoadResource;
|
||||
static late AsstCreateExFunc _asstCreateEx;
|
||||
static late AsstConnectFunc _asstConnect;
|
||||
static late AsstDestroyFunc _asstDestroy;
|
||||
static late AsstAppendTaskFunc _asstAppendTask;
|
||||
static late AsstSetTaskParamsFunc _asstSetTaskParams;
|
||||
static late AsstStartFunc _asstStart;
|
||||
static late AsstStopFunc _asstStop;
|
||||
static late AsstCtrlerClickFunc _asstCtrlerClick;
|
||||
static late AsstGetVersionFunc _asstGetVersion;
|
||||
static late AsstLogFunc _asstLog;
|
||||
|
||||
// callbacklib
|
||||
static late InitDartApiFunc _initDartApi;
|
||||
static late Pointer<AsstCallbackNative> _asstCallback;
|
||||
static late NativeFreeFunc _nativeFree;
|
||||
|
||||
static bool _resourceLoaded = false;
|
||||
late ReceivePort? _receivePort;
|
||||
static bool _apiInited = false;
|
||||
ReceivePort? get receivePort => _receivePort;
|
||||
static bool _symbolsLoaded = false;
|
||||
|
||||
late ReceivePort? _receivePort;
|
||||
late Assistant _asst;
|
||||
late StreamSubscription _portSubscription;
|
||||
late List<Pointer> _allocated;
|
||||
|
||||
static Future<String> get platformVersion async {
|
||||
return Future<String>(() => '0.0.1');
|
||||
}
|
||||
|
||||
void _loadResource(String path) {
|
||||
final strPtr = toManagedString(path);
|
||||
final result = _asstLoadResource(strPtr);
|
||||
_resourceLoaded = _resourceLoaded || result;
|
||||
}
|
||||
|
||||
MaaCore(String libDir, [Function(String)? callback]) {
|
||||
_loadCppLib(libDir);
|
||||
if (!_apiInited) {
|
||||
final callbackLib = DynamicLibrary.open(p.join(libDir, 'libCallback.so'));
|
||||
final InitDartApiFunc initNativeApi =
|
||||
callbackLib.lookup<InitDartApiNative>('init_dart_api').asFunction();
|
||||
initNativeApi(NativeApi.initializeApiDLData);
|
||||
_apiInited = true;
|
||||
|
||||
ReceivePort? get receivePort => _receivePort;
|
||||
static List<String> get _deps {
|
||||
if (Platform.isWindows){
|
||||
return [
|
||||
'libiomp5md',
|
||||
'mklml',
|
||||
'mkldnn',
|
||||
'opencv_world453',
|
||||
'paddle_inference',
|
||||
'ppocr',
|
||||
];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
static String get meoAssistantLibName {
|
||||
if (Platform.isLinux) {
|
||||
return 'libMeoAssistant.so';
|
||||
} else if (Platform.isWindows) {
|
||||
return 'MeoAssistant.dll';
|
||||
}
|
||||
return 'libMeoAssistant.dylib';
|
||||
}
|
||||
|
||||
static String get callbackLibName {
|
||||
if (Platform.isLinux) {
|
||||
return 'libCallback.so';
|
||||
} else if (Platform.isWindows) {
|
||||
return 'Callback.dll';
|
||||
}
|
||||
return 'libCallback.dylib';
|
||||
}
|
||||
|
||||
static _loadResource(String dir) {
|
||||
print("init resource");
|
||||
final dirPtr = dir.toNativeUtf8();
|
||||
_asstLoadResource(dirPtr);
|
||||
malloc.free(dirPtr);
|
||||
_resourceLoaded = true;
|
||||
}
|
||||
|
||||
MaaCore(String libDir, [Function(String)? callback]) {
|
||||
init(libDir);
|
||||
|
||||
_allocated = [];
|
||||
if (!_resourceLoaded) {
|
||||
_loadResource(libDir);
|
||||
}
|
||||
_receivePort = ReceivePort();
|
||||
final nativePort = _receivePort!.sendPort.nativePort;
|
||||
final portPtr = malloc.allocate<Int64>(sizeOf<Int64>());
|
||||
_asst = _asstCreateEx(nativeCallback, portPtr.cast<Void>());
|
||||
_asst = _asstCreateEx(_asstCallback, portPtr.cast<Void>());
|
||||
_allocated.add(portPtr);
|
||||
portPtr.value = nativePort;
|
||||
|
||||
if (callback != null) {
|
||||
_portSubscription = _receivePort!.listen(_wrapCallback(callback));
|
||||
}
|
||||
}
|
||||
|
||||
static void init(String libDir, {bool reloadResource = false}) {
|
||||
if (!_symbolsLoaded) {
|
||||
_loadNativeSymbols(libDir);
|
||||
}
|
||||
|
||||
if (!_apiInited) {
|
||||
_initDartApi(NativeApi.initializeApiDLData);
|
||||
_apiInited = true;
|
||||
}
|
||||
|
||||
if (!_resourceLoaded || reloadResource) {
|
||||
_loadResource(libDir);
|
||||
}
|
||||
}
|
||||
|
||||
void Function(dynamic) _wrapCallback(void Function(String) cb) {
|
||||
return (dynamic data) {
|
||||
// c will manage the memory for the string
|
||||
String msg = data;
|
||||
final Pointer<Utf8> ptr = Pointer.fromAddress(data as int);
|
||||
String msg = ptr.toDartString();
|
||||
print("msg from ptr ($ptr): $msg before free");
|
||||
_nativeFree(ptr.cast<Void>());
|
||||
cb(msg);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
Pointer<AsstCallbackNative> get nativeCallback {
|
||||
return DynamicLibrary.open('./libCallback.so')
|
||||
.lookup<AsstCallbackNative>('callback');
|
||||
static void _loadNativeSymbols(String libDir) {
|
||||
_loadMeoAssistant(libDir);
|
||||
_loadCallbackLib(libDir);
|
||||
_symbolsLoaded = true;
|
||||
}
|
||||
|
||||
void _loadCppLib(String libDir) {
|
||||
final lib = DynamicLibrary.open(p.join(libDir, 'libMeoAssistant.so'));
|
||||
static void _loadCallbackLib(String libDir) {
|
||||
final lib = DynamicLibrary.open(p.join(libDir, callbackLibName));
|
||||
_initDartApi = lib.lookup<InitDartApiNative>('init_dart_api').asFunction();
|
||||
_nativeFree = lib.lookup<NativeFreeNative>('native_free').asFunction();
|
||||
_asstCallback = lib.lookup<AsstCallbackNative>('callback');
|
||||
}
|
||||
|
||||
static void _loadMeoAssistant(String libDir) {
|
||||
if (Platform.isWindows) {
|
||||
for (var dep in _deps) {
|
||||
print("load dep: $dep");
|
||||
DynamicLibrary.open(p.join(libDir, dep+'.dll'));
|
||||
print("loaded dep: $dep");
|
||||
}
|
||||
}
|
||||
final lib = DynamicLibrary.open(p.join(libDir, meoAssistantLibName));
|
||||
_asstLoadResource =
|
||||
lib.lookup<AsstLoadResourceNative>('AsstLoadResource').asFunction();
|
||||
_asstCreate = lib.lookup<AsstCreateNative>('AsstCreate').asFunction();
|
||||
_asstCreateEx = lib.lookup<AsstCreateExNative>('AsstCreateEx').asFunction();
|
||||
_asstConnect = lib.lookup<AsstConnectNative>('AsstConnect').asFunction();
|
||||
_asstDestroy = lib.lookup<AsstDestroyNative>('AsstDestroy').asFunction();
|
||||
@@ -171,4 +236,10 @@ class MaaCore implements MaaCoreInterface {
|
||||
_allocated.add(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static String get version {
|
||||
final ptr = _asstGetVersion();
|
||||
final str = ptr.toDartString();
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,9 @@ typedef InitDartApiNative = NativeFunction<Void Function(Pointer<Void>)>;
|
||||
typedef CleanUpDartVMFunc = void Function();
|
||||
typedef CleanUpDartVMNative = NativeFunction<Void Function()>;
|
||||
|
||||
typedef NativeFreeFunc = void Function(Pointer<Void>);
|
||||
typedef NativeFreeNative = NativeFunction<Void Function(Pointer<Void>)>;
|
||||
|
||||
abstract class MaaCoreInterface {
|
||||
void destroy();
|
||||
bool connect(String adbPath, String address,[String config = '']);
|
||||
|
||||
15
src/dart/native/CMakeSettings.json
Normal file
15
src/dart/native/CMakeSettings.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,16 +1,23 @@
|
||||
#include "dart_api_dl.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void callback(int, const char *, void *);
|
||||
void init_dart_api(void *);
|
||||
|
||||
void init_dart_api(void *api_data) {
|
||||
Dart_InitializeApiDL(api_data);
|
||||
}
|
||||
|
||||
void native_free(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void callback(int retval, const char *json_str, void *custom_arg) {
|
||||
Dart_Port port = *(Dart_Port *)custom_arg;
|
||||
|
||||
|
||||
int n_digits = 1;
|
||||
int k = retval;
|
||||
while (k > 10) {
|
||||
@@ -18,15 +25,14 @@ void callback(int retval, const char *json_str, void *custom_arg) {
|
||||
k /= 10;
|
||||
}
|
||||
Dart_CObject obj;
|
||||
int required_len = n_digits + strlen(json_str) + 1;
|
||||
char retstr[required_len];
|
||||
retstr[required_len-1] = 0;
|
||||
sprintf(retstr, "{\"retval\": %d, \"payload\": %s }", retval, json_str);
|
||||
int required_len = n_digits + strlen(json_str) + 30;
|
||||
char* retptr = calloc(required_len, sizeof(char));
|
||||
snprintf(retptr, required_len, "{\"retval\":%d,\"payload\":%s}", retval, json_str);
|
||||
obj.type = Dart_CObject_kString;
|
||||
obj.value.as_string = retstr;
|
||||
printf("C: Sending Pointer %ld to dart through port %ld\n", (int64_t)json_str, port);
|
||||
obj.value.as_int64 = (uintptr_t)retptr;
|
||||
printf("C: Sending Pointer %p to dart through port %ld\n", retptr, (int64_t) port);
|
||||
char res = Dart_PostCObject_DL(port, &obj);
|
||||
if (res == 0) {
|
||||
printf("C: Failed to send message to Dart\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user