diff --git a/.github/actions/build-jni/action.yml b/.github/actions/build-jni/action.yml new file mode 100644 index 0000000..0f5f18e --- /dev/null +++ b/.github/actions/build-jni/action.yml @@ -0,0 +1,28 @@ +name: 'Build JNI' +description: 'Builds the JNI Native library' +inputs: + architecture: + description: 'The CPU architecture for which to build the lib' + required: true + variant: + description: 'The library type to build' + required: true + target-os: + description: 'The target Operating system identifier' + required: true + +runs: + using: "composite" + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - uses: actions/download-artifact@v3 + with: + path: dist + - run: ./build.cmd LibAlphaSkiaJni --target-os ${{ inputs.target-os }} --architecture ${{ inputs.architecture }} --variant ${{ inputs.variant }} + - uses: actions/upload-artifact@v3 + with: + name: alphaskia-${{ inputs.target-os }}-jni-${{ inputs.architecture }}-${{ inputs.variant }} + path: artifacts + diff --git a/.github/actions/build-skia/action.yml b/.github/actions/build-skia/action.yml new file mode 100644 index 0000000..f0d9f79 --- /dev/null +++ b/.github/actions/build-skia/action.yml @@ -0,0 +1,42 @@ +name: 'Build Skia' +description: 'Builds the Skia Native library' +inputs: + use-cache: + description: 'Whether to try using the pre-compiled binary from the cache.' + required: false + default: 'false' + architecture: + description: 'The CPU architecture for which to build the lib' + required: true + variant: + description: 'The library type to build' + required: true + target-os: + description: 'The target Operating system identifier' + required: true + +runs: + using: "composite" + steps: + - uses: actions/checkout@v3 + with: + submodules: false + + - uses: actions/cache/restore@v3 + if: ${{ inputs.use-cache }} + with: + path: dist + restore-keys: alphaskia-${{ inputs.target-os }}-${{ inputs.architecture }}-${{ inputs.variant }} + + - run: ./build.cmd LibAlphaSkia --target-os ${{ inputs.target-os }} --architecture ${{ inputs.architecture }} --variant ${{ inputs.variant }} --use-cache ${{ inputs.use-cache }} + - uses: actions/upload-artifact@v3 + with: + name: alphaskia-${{ inputs.target-os }}-${{ inputs.architecture }}-${{ inputs.variant }} + path: artifacts + + - uses: actions/cache/save@v3 + with: + path: dist + key: alphaskia-${{ inputs.target-os }}-${{ inputs.architecture }}-${{ inputs.variant }}-${{ github.run_id }} + + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 668f736..10692e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,15 @@ on: workflow_dispatch: + inputs: + use-skia-cache: + type: boolean + description: Use Skia Binary from cache + default: 'false' jobs: + +# +# Windows windows: runs-on: windows-latest strategy: @@ -9,17 +17,13 @@ jobs: matrix: architecture: [x64, x86, arm64] variant: ['shared', 'static'] - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - run: ./build.cmd WindowsSkia --architecture ${{ matrix.architecture }} --variant ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + - uses: ./.github/actions/build-skia with: - name: alphaskia-windows-${{ matrix.architecture }}-${{ matrix.variant }} - path: artifacts - + use-cache: ${{ inputs.use-skia-cache }} + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: windows windows-jni: runs-on: windows-latest needs: [windows] @@ -28,20 +32,15 @@ jobs: matrix: architecture: [x64, x86, arm64] variant: ['shared'] - steps: - - uses: actions/checkout@v3 + - uses: ./.github/actions/build-jni with: - submodules: true - - uses: actions/download-artifact@v3 - with: - path: dist - - run: ./build.cmd WindowsJni --architecture ${{ matrix.architecture }} --variant ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 - with: - name: alphaskia-windows-jni-${{ matrix.architecture }}-${{ matrix.variant }} - path: artifacts + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: windows +# +# Linux linux: runs-on: ubuntu-latest strategy: @@ -51,16 +50,12 @@ jobs: # TODO architecture: [x64, x86, arm64] variant: ['shared', 'static'] steps: - - uses: actions/checkout@v3 - with: - submodules: true - - run: ./externals/skia/tools/install_dependencies.sh - - run: ./build.sh LinuxSkia --architecture ${{ matrix.architecture }} --variant ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + - uses: ./.github/actions/build-skia with: - name: alphaskia-linux-${{ matrix.architecture }}-${{ matrix.variant }} - path: artifacts - + use-cache: ${{ inputs.use-skia-cache }} + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: linux linux-jni: runs-on: ubuntu-latest needs: [linux] @@ -70,20 +65,15 @@ jobs: # TODO architecture: [x64, x86, arm64] architecture: [x64] variant: ['shared'] - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - uses: actions/download-artifact@v3 + - uses: ./.github/actions/build-jni with: - path: dist - - run: ./build.cmd LinuxJni --architecture ${{ matrix.architecture }} --variant ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 - with: - name: alphaskia-linux-jni-${{ matrix.architecture }}-${{ matrix.variant }} - path: artifacts + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: linux +# +# Android android: runs-on: ubuntu-latest strategy: @@ -91,18 +81,13 @@ jobs: matrix: architecture: [x64, x86, arm, arm64] variant: ['shared', 'static'] - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - run: ./externals/skia/tools/install_dependencies.sh - - run: ./build.sh AndroidSkia --architecture ${{ matrix.architecture }} --variant ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + - uses: ./.github/actions/build-skia with: - name: alphaskia-android-${{ matrix.architecture }}-${{ matrix.variant }} - path: artifacts - + use-cache: ${{ inputs.use-skia-cache }} + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: android android-jni: runs-on: ubuntu-latest needs: [android] @@ -111,23 +96,47 @@ jobs: matrix: architecture: [x64, x86, arm, arm64] variant: ['shared'] - steps: - - uses: actions/checkout@v3 + - uses: ./.github/actions/build-jni with: - submodules: true - - uses: actions/download-artifact@v3 + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: android +# +# MacOs + macos: + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + architecture: [x64, arm64] + variant: ['shared', 'static'] + steps: + - uses: ./.github/actions/build-skia with: - path: dist - - run: ./build.cmd AndroidJni --architecture ${{ matrix.architecture }} --variant ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + use-cache: ${{ inputs.use-skia-cache }} + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: macos + macos-jni: + runs-on: macos-latest + needs: [macos] + strategy: + fail-fast: false + matrix: + architecture: [x64, arm64] + variant: ['shared'] + steps: + - uses: ./.github/actions/build-jni with: - name: alphaskia-android-jni-${{ matrix.architecture }}-${{ matrix.variant }} - path: artifacts - + architecture: ${{ matrix.architecture }} + variant: ${{ matrix.variant }} + target-os: macos +# +# Libraries dotnet: runs-on: windows-latest - needs: [windows, linux] + needs: [windows, linux, android, macos] steps: - uses: actions/checkout@v3 with: @@ -145,7 +154,7 @@ jobs: java: runs-on: ubuntu-latest - needs: [windows-jni, linux-jni, android-jni] + needs: [windows-jni, linux-jni, android-jni, macos-jni] steps: - uses: actions/checkout@v3 with: @@ -158,7 +167,4 @@ jobs: with: name: Jars path: | - lib/java/main/build/libs/*.jar - lib/java/linux/build/libs/*.jar - lib/java/android/build/libs/*.jar - lib/java/windows/build/libs/*.jar + lib/java/*/build/libs/*.jar diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 412b126..97538c5 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -9,6 +9,7 @@ "Architecture": { "type": "string", "enum": [ + "Arm", "Arm64", "X64", "X86" @@ -61,6 +62,9 @@ "LlvmHome": { "type": "string" }, + "NdkPath": { + "type": "string" + }, "NinjaExe": { "type": "string" }, @@ -102,6 +106,11 @@ "items": { "type": "string", "enum": [ + "AndroidJni", + "AndroidSkia", + "Compile", + "CompileTests", + "CompileWithCache", "DotNet", "DotNetBuild", "DotNetPack", @@ -111,11 +120,15 @@ "Java", "LinuxJni", "LinuxSkia", + "MacOsJni", + "MacOsSkia", "PatchSkiaBuildFiles", + "PrepareForBuild", "PrepareGitHubArtifacts", "SetupDepotTools", "WindowsJni", - "WindowsSkia" + "WindowsSkia", + "WithDependencies" ] } }, @@ -125,6 +138,11 @@ "items": { "type": "string", "enum": [ + "AndroidJni", + "AndroidSkia", + "Compile", + "CompileTests", + "CompileWithCache", "DotNet", "DotNetBuild", "DotNetPack", @@ -134,14 +152,21 @@ "Java", "LinuxJni", "LinuxSkia", + "MacOsJni", + "MacOsSkia", "PatchSkiaBuildFiles", + "PrepareForBuild", "PrepareGitHubArtifacts", "SetupDepotTools", "WindowsJni", - "WindowsSkia" + "WindowsSkia", + "WithDependencies" ] } }, + "use-cache": { + "type": "string" + }, "Variant": { "type": "string", "enum": [ diff --git a/README.md b/README.md index 26582bf..6217895 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ In the initial release of the library we plan to support following platform matr | linux-x86 | ✅ | ✅ | ✅ | | linux-arm | ✅ | ✅ | ✅ | | linux-arm64 | ✅ | ✅ | ✅ | -| osx-x64 | ✅ | ✅ | ✅ | -| osx-arm64 | ✅ | ✅ | ✅ | +| macos-x64 | ✅ | ✅ | ✅ | +| macos-arm64 | ✅ | ✅ | ✅ | | android-x64 | ✅ | ✅ | | | android-x86 | ✅ | ✅ | | | android-arm | ✅ | ✅ | | diff --git a/build/Build.Android.cs b/build/Build.Android.cs index 0e71cb2..8dd82d9 100644 --- a/build/Build.Android.cs +++ b/build/Build.Android.cs @@ -44,32 +44,14 @@ static string FindNdk() return string.Empty; } - - public Target AndroidSkia => _ => _ - .DependsOn(GitSyncDepsSkia, PatchSkiaBuildFiles) - .Requires(() => Architecture) - .Requires(() => Variant) - .Executes(() => - { - BuildSkiaAndroidMain(Architecture, Variant); - }); - - public Target AndroidJni => _ => _ - .DependsOn(PrepareGitHubArtifacts, GitSyncDepsJni, PatchSkiaBuildFiles) - .Requires(() => Architecture) - .Requires(() => Variant == Variant.Shared) - .Executes(() => - { - BuildSkiaAndroidJni(Architecture, Variant); - }); - - void BuildSkiaAndroidMain(Architecture arch, Variant variant) + + void BuildLibAlphaSkiaAndroid() { var gnArgs = new Dictionary(); gnArgs["ndk"] = NdkPath; string[] filesToCopy; - var isShared = variant == Variant.Shared; + var isShared = Variant == Variant.Shared; if (isShared) { filesToCopy = new[] @@ -86,10 +68,10 @@ void BuildSkiaAndroidMain(Architecture arch, Variant variant) }; } - BuildSkiaAndroid("libAlphaSkia", arch, variant, gnArgs, filesToCopy); + BuildSkiaAndroid("libAlphaSkia", gnArgs, filesToCopy); } - void BuildSkiaAndroidJni(Architecture arch, Variant variant) + void BuildLibAlphaSkiaJniAndroid() { var gnArgs = new Dictionary(); var alphaSkiaInclude = DistBasePath / "include"; @@ -99,30 +81,17 @@ void BuildSkiaAndroidJni(Architecture arch, Variant variant) gnArgs["extra_cflags"] = $"[ '-I{alphaSkiaInclude}', '-I{jniInclude}', '-I{jniWinInclude}' ]"; // Add Libs and lib search paths - var staticLibPath = DistBasePath / $"libAlphaSkia-android-{arch}-static"; - gnArgs["extra_ldflags"] = - $"[ '-L{staticLibPath}', '-lAlphaSkia', '-lskia' ]"; + var staticLibPath = DistBasePath / GetLibDirectory(variant: Variant.Shared); + gnArgs["extra_ldflags"] = $"[ '-L{staticLibPath}', '-lAlphaSkia', '-lskia' ]"; - BuildSkiaAndroid("libAlphaSkiaJni", arch, variant, gnArgs, new[] { "libAlphaSkiaJni.so" }); + BuildSkiaAndroid("libAlphaSkiaJni", gnArgs, new[] { "libAlphaSkiaJni.so" }); } - void BuildSkiaAndroid(string buildTarget, Architecture arch, Variant variant, Dictionary gnArgs, + void BuildSkiaAndroid(string buildTarget, Dictionary gnArgs, string[] filesToCopy) { - if (OperatingSystem.IsWindows()) - { - SetClangWindows(gnArgs); - } - else if (OperatingSystem.IsLinux()) - { - SetClangLinux(arch, gnArgs); - } - - // gnArgs["skia_enable_ganesh"] = "true"; gnArgs["skia_use_system_freetype2"] = "false"; - // -Wdeprecated-declarations - - BuildSkia(buildTarget, "android", arch, variant, gnArgs, filesToCopy); + BuildSkia(buildTarget, gnArgs, filesToCopy); } } \ No newline at end of file diff --git a/build/Build.DotNet.cs b/build/Build.DotNet.cs index 082f478..8683663 100644 --- a/build/Build.DotNet.cs +++ b/build/Build.DotNet.cs @@ -8,6 +8,7 @@ partial class Build .DependsOn(DotNetPack); public Target DotNetPack => _ => _ + .Unlisted() .DependsOn(DotNetTest) .Executes(() => { @@ -17,6 +18,7 @@ partial class Build ); }); public Target DotNetTest => _ => _ + .Unlisted() .DependsOn(DotNetBuild) .Executes(() => { @@ -26,6 +28,7 @@ partial class Build ); }); public Target DotNetBuild => _ => _ + .Unlisted() .DependsOn(PrepareGitHubArtifacts) .Executes(() => { diff --git a/build/Build.Linux.cs b/build/Build.Linux.cs index 5ed4545..f0bfeef 100644 --- a/build/Build.Linux.cs +++ b/build/Build.Linux.cs @@ -1,34 +1,12 @@ -using System; using System.Collections.Generic; -using Nuke.Common; partial class Build { - public Target LinuxSkia => _ => _ - .DependsOn(GitSyncDepsSkia, PatchSkiaBuildFiles) - .Requires(() => Architecture) - .Requires(() => Variant) - .OnlyWhenStatic(OperatingSystem.IsLinux) - .Executes(() => - { - BuildSkiaLinuxMain(Architecture, Variant); - }); - - public Target LinuxJni => _ => _ - .DependsOn(PrepareGitHubArtifacts, GitSyncDepsJni, PatchSkiaBuildFiles) - .Requires(() => Architecture) - .Requires(() => Variant == Variant.Shared) - .OnlyWhenStatic(OperatingSystem.IsLinux) - .Executes(() => - { - BuildSkiaLinuxJni(Architecture, Variant); - }); - - void BuildSkiaLinuxMain(Architecture arch, Variant variant) + void BuildLibAlphaSkiaLinux() { var gnArgs = new Dictionary(); string[] filesToCopy; - var isShared = variant == Variant.Shared; + var isShared = Variant == Variant.Shared; if (isShared) { filesToCopy = new[] @@ -45,10 +23,10 @@ void BuildSkiaLinuxMain(Architecture arch, Variant variant) }; } - BuildSkiaLinux("libAlphaSkia", arch, variant, gnArgs, filesToCopy); + BuildSkiaLinux("libAlphaSkia", gnArgs, filesToCopy); } - void BuildSkiaLinuxJni(Architecture arch, Variant variant) + void BuildLibAlphaSkiaJniLinux() { var gnArgs = new Dictionary(); var alphaSkiaInclude = DistBasePath / "include"; @@ -57,41 +35,39 @@ void BuildSkiaLinuxJni(Architecture arch, Variant variant) gnArgs["extra_cflags"] = $"[ '-I{alphaSkiaInclude}', '-I{jniInclude}', '-I{jniWinInclude}' ]"; // Add Libs and lib search paths - var staticLibPath = DistBasePath / $"libAlphaSkia-linux-{arch}-static"; + var staticLibPath = DistBasePath / GetLibDirectory(variant: Variant.Shared); gnArgs["extra_ldflags"] = $"[ '-L{staticLibPath}', '-lAlphaSkia', '-lskia' ]"; - BuildSkiaLinux("libAlphaSkiaJni", arch, variant, gnArgs, new[] { "libAlphaSkiaJni.so" }); + BuildSkiaLinux("libAlphaSkiaJni", gnArgs, new[] { "libAlphaSkiaJni.so" }); } - void BuildSkiaLinux(string buildTarget, Architecture arch, Variant variant, Dictionary gnArgs, + void BuildSkiaLinux(string buildTarget, Dictionary gnArgs, string[] filesToCopy) { - SetClangLinux(arch, gnArgs); - gnArgs["skia_use_system_freetype2"] = "false"; - BuildSkia(buildTarget, "linux", arch, variant, gnArgs, filesToCopy); + BuildSkia(buildTarget, gnArgs, filesToCopy); } - void SetClangLinux(Architecture arch, Dictionary gnArgs) + void SetClangLinux(Dictionary gnArgs) { AppendToFlagList(gnArgs, "extra_cflags", "'-DHAVE_SYSCALL_GETRANDOM', '-DXML_DEV_URANDOM'"); - if (arch == Architecture.X64) + if (Architecture == Architecture.X64) { gnArgs["cc"] = "clang"; gnArgs["cxx"] = "'clang++'"; AppendToFlagList(gnArgs, "extra_ldflags", "'-static-libstdc++', '-static-libgcc'"); } - else if (arch == Architecture.X86) + else if (Architecture == Architecture.X86) { // TODO gnArgs["cc"] = "clang"; gnArgs["cxx"] = "'clang++'"; AppendToFlagList(gnArgs, "extra_ldflags", "'-static-libstdc++', '-static-libgcc'"); } - else if (arch == Architecture.Arm64) // aka AArch64 + else if (Architecture == Architecture.Arm64) // aka AArch64 { // TODO gnArgs["cc"] = "clang"; diff --git a/build/Build.MacOs.cs b/build/Build.MacOs.cs new file mode 100644 index 0000000..515a3f6 --- /dev/null +++ b/build/Build.MacOs.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; + +partial class Build +{ + void BuildLibAlphaSkiaMacOs() + { + var gnArgs = new Dictionary(); + string[] filesToCopy; + var isShared = Variant == Variant.Shared; + if (isShared) + { + filesToCopy = new[] + { + "libAlphaSkia.dylib" + }; + } + else + { + filesToCopy = new[] + { + "libAlphaSkia.a", + "libskia.a" + }; + } + + BuildSkiaMacOs("libAlphaSkia", gnArgs, filesToCopy); + } + + void BuildLibAlphaSkiaJniMacOs() + { + var gnArgs = new Dictionary(); + var alphaSkiaInclude = DistBasePath / "include"; + var jniInclude = JavaHome / "include"; + var jniWinInclude = JavaHome / "include" / "darwin"; + gnArgs["extra_cflags"] = $"[ '-I{alphaSkiaInclude}', '-I{jniInclude}', '-I{jniWinInclude}' ]"; + + // Add Libs and lib search paths + var staticLibPath = DistBasePath / GetLibDirectory(variant: Variant.Static); + gnArgs["extra_ldflags"] = + $"[ '-L{staticLibPath}', '-lAlphaSkia', '-lskia' ]"; + + BuildSkiaMacOs("libAlphaSkiaJni", gnArgs, new[] { "libAlphaSkiaJni.dylib" }); + } + + void BuildSkiaMacOs(string buildTarget, Dictionary gnArgs, + string[] filesToCopy) + { + gnArgs["skia_use_system_freetype2"] = "false"; + gnArgs["skia_use_metal"] = "true"; + + BuildSkia(buildTarget, gnArgs, filesToCopy); + } + + void SetClangMacOs(Dictionary gnArgs) + { + AppendToFlagList(gnArgs, "extra_cflags", "'-DHAVE_ARC4RANDOM_BUF', '-stdlib=libc++'"); + + gnArgs["cc"] = "clang"; + gnArgs["cxx"] = "'clang++'"; + AppendToFlagList(gnArgs, "extra_ldflags", "'-stdlib=libc++'"); + + // gnArgs["ar"] = "llvm-ar"; + } +} \ No newline at end of file diff --git a/build/Build.Native.cs b/build/Build.Native.cs index a7757a5..bb5d418 100644 --- a/build/Build.Native.cs +++ b/build/Build.Native.cs @@ -11,6 +11,17 @@ using Serilog; using static Nuke.Common.EnvironmentInfo; +[TypeConverter(typeof(TypeConverter))] +public class TargetOperatingSystem : Enumeration +{ + public static TargetOperatingSystem Windows = new() { Value = "windows", SkiaTargetOs = "win", RuntimeIdentifier = "win" }; + public static TargetOperatingSystem Linux = new() { Value = "linux", SkiaTargetOs = "linux", RuntimeIdentifier = "linux" }; + public static TargetOperatingSystem Android = new() { Value = "android", SkiaTargetOs = "android", RuntimeIdentifier = "android" }; + public static TargetOperatingSystem MacOs = new() { Value = "macos", SkiaTargetOs = "mac", RuntimeIdentifier = "macos" }; + + public string SkiaTargetOs { get; private set; } + public string RuntimeIdentifier { get; private set; } +} [TypeConverter(typeof(TypeConverter))] public class Architecture : Enumeration @@ -56,11 +67,16 @@ partial class Build Tool GitTool => File.Exists(GitExe) ? ToolResolver.GetTool(GitExe) : ToolResolver.GetPathTool("git"); // Output Options + [Parameter] readonly TargetOperatingSystem TargetOs; [Parameter] readonly Architecture Architecture; [Parameter] readonly Variant Variant; + [Parameter(Name = "use-cache")] readonly string UseCacheParam; - public Target GitSyncDepsSkia => _ => _ + bool UseCache => "true".Equals(UseCacheParam, StringComparison.OrdinalIgnoreCase); + + public Target GitSyncDepsAlphaSkia => _ => _ + .Unlisted() .DependsOn(SetupDepotTools) .Executes(() => { @@ -86,7 +102,8 @@ partial class Build return GitSyncDepsCustom(requiredDependencies); }); - public Target GitSyncDepsJni => _ => _ + public Target GitSyncDepsLibAlphaSkiaJni => _ => _ + .Unlisted() .DependsOn(SetupDepotTools) .Executes(() => { @@ -98,6 +115,74 @@ partial class Build return GitSyncDepsCustom(requiredDependencies); }); + public Target LibAlphaSkiaWithCache => _ => _ + .Unlisted() + .OnlyWhenStatic(() => !CanUseCachedBinaries("libAlphaSkia", TargetOs.RuntimeIdentifier)) + .Requires(() => Architecture) + .Requires(() => Variant) + .Requires(() => TargetOs) + .Triggers(LibAlphaSkia); + + public Target LibAlphaSkia => _ => _ + .DependsOn(GitSyncDepsAlphaSkia, PatchSkiaBuildFiles) + .Requires(() => Architecture) + .Requires(() => Variant) + .Requires(() => TargetOs) + .Executes(() => + { + if (TargetOs == TargetOperatingSystem.Windows) + { + BuildLibAlphaSkiaWindows(); + } + else if (TargetOs == TargetOperatingSystem.Linux) + { + BuildLibAlphaSkiaLinux(); + } + else if (TargetOs == TargetOperatingSystem.Android) + { + BuildLibAlphaSkiaAndroid(); + } + else if (TargetOs == TargetOperatingSystem.MacOs) + { + BuildLibAlphaSkiaMacOs(); + } + }); + + public Target LibAlphaSkiaJni => _ => _ + .DependsOn(PrepareGitHubArtifacts, GitSyncDepsLibAlphaSkiaJni, PatchSkiaBuildFiles) + .Requires(() => Architecture) + .Requires(() => Variant) + .Requires(() => TargetOs) + .Executes(() => + { + if (TargetOs == TargetOperatingSystem.Windows) + { + BuildLibAlphaSkiaJniWindows(); + } + else if (TargetOs == TargetOperatingSystem.Linux) + { + BuildLibAlphaSkiaJniLinux(); + } + else if (TargetOs == TargetOperatingSystem.Android) + { + BuildLibAlphaSkiaJniAndroid(); + } + else if (TargetOs == TargetOperatingSystem.MacOs) + { + BuildLibAlphaSkiaJniMacOs(); + } + }); + + string GetLibDirectory(string libName = "libAlphaSkia", TargetOperatingSystem targetOs = null, + Architecture arch = null, Variant variant = null) + { + targetOs ??= TargetOs; + arch ??= Architecture; + variant ??= Variant; + + return $"{libName}-{targetOs.RuntimeIdentifier}-{arch}-{variant}"; + } + Task GitSyncDepsCustom(string[] requiredDependencies) { var depsFile = SkiaPath / "DEPS"; @@ -230,6 +315,7 @@ Dictionary ReadDepsData(TextReader reader) } public Target SetupDepotTools => _ => _ + .Unlisted() .Executes(() => { var oldValue = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process); @@ -248,6 +334,7 @@ Dictionary ReadDepsData(TextReader reader) }); public Target PatchSkiaBuildFiles => _ => _ + .Unlisted() .Executes(() => { var buildConfigNew = new StringBuilder(); @@ -315,6 +402,13 @@ Dictionary ReadDepsData(TextReader reader) buildNew.AppendLine(" \"../../lib/java/jni/src/AlphaSkiaImage.cpp\","); buildNew.AppendLine(" \"../../lib/java/jni/src/AlphaSkiaTypeface.cpp\""); buildNew.AppendLine(" ]"); + buildNew.AppendLine(" if (is_mac) {"); + buildNew.AppendLine(" frameworks = ["); + buildNew.AppendLine(" \"AppKit.framework\","); + buildNew.AppendLine(" \"ApplicationServices.framework\","); + buildNew.AppendLine(" \"Metal.framework\","); + buildNew.AppendLine(" ]"); + buildNew.AppendLine(" }"); buildNew.AppendLine(); buildNew.AppendLine("}"); PatchSkiaFile(SkiaPath / "BUILD.gn", buildNew.ToString()); @@ -413,19 +507,29 @@ string QuoteValue(string value) void BuildSkia( string buildTarget, - string targetOs, - string arch, - Variant variant, Dictionary gnArgs, string[] filesToCopy) { - var isShared = variant == Variant.Shared; - var artifactDir = $"{buildTarget}-{targetOs}-{arch}-{variant}"; - var distPath = DistBasePath / artifactDir; - var artifactsLibPath = IsGitHubActions ? ArtifactBasePath / artifactDir : null; - - gnArgs["target_os"] = targetOs; - gnArgs["target_cpu"] = arch; + if (OperatingSystem.IsWindows()) + { + SetClangWindows(gnArgs); + } + else if (OperatingSystem.IsLinux()) + { + SetClangLinux(gnArgs); + } + else if (OperatingSystem.IsMacOS()) + { + SetClangMacOs(gnArgs); + } + + var isShared = Variant == Variant.Shared; + var libDir = GetLibDirectory(buildTarget, TargetOs, Architecture, Variant); + var distPath = DistBasePath / libDir; + var artifactsLibPath = IsGitHubActions ? ArtifactBasePath / libDir : null; + + gnArgs["target_os"] = TargetOs.SkiaTargetOs; + gnArgs["target_cpu"] = Architecture; gnArgs["is_shared_alphaskia"] = isShared.ToString().ToLowerInvariant(); // disable features we don't need @@ -460,9 +564,9 @@ void BuildSkia( gnArgs["skia_enable_ganesh"] = "true"; gnArgs["skia_use_vulkan"] = "true"; - GnNinja($"out/{buildTarget}/{targetOs}/{arch}/{variant}", buildTarget, gnArgs, SkiaPath); + GnNinja($"out/{libDir}", buildTarget, gnArgs, SkiaPath); - var outDir = SkiaPath / "out" / buildTarget / targetOs / arch / variant; + var outDir = SkiaPath / "out" / libDir; try { foreach (var file in filesToCopy) @@ -492,4 +596,10 @@ void BuildSkia( throw new IOException("Copy files failed. existing files: " + string.Join(", ", fileList), e); } } + + bool HasCachedFiles(string buildTarget, string targetOsOutDir) + { + var expectedDirectory = DistBasePath / $"{buildTarget}-{targetOsOutDir}-{Architecture}-{Variant}"; + return expectedDirectory.DirectoryExists() && expectedDirectory.GetFiles().Any(); + } } \ No newline at end of file diff --git a/build/Build.Windows.cs b/build/Build.Windows.cs index 29a277f..f648158 100644 --- a/build/Build.Windows.cs +++ b/build/Build.Windows.cs @@ -2,32 +2,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Nuke.Common; using Nuke.Common.IO; using Nuke.Common.Tooling; partial class Build { - public Target WindowsSkia => _ => _ - .DependsOn(GitSyncDepsSkia, PatchSkiaBuildFiles) - .Requires(() => Architecture) - .Requires(() => Variant) - .OnlyWhenStatic(OperatingSystem.IsWindows) - .Executes(() => - { - BuildSkiaWindowsMain(Architecture, Variant); - }); - - public Target WindowsJni => _ => _ - .DependsOn(PrepareGitHubArtifacts, GitSyncDepsJni, PatchSkiaBuildFiles) - .Requires(() => Architecture) - .Requires(() => Variant == Variant.Shared) - .OnlyWhenStatic(OperatingSystem.IsWindows) - .Executes(() => - { - BuildSkiaWindowsJni(Architecture, Variant); - }); - Tool VsWhere => ToolResolver.GetPathTool(Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft Visual Studio", "Installer", "vswhere.exe")); @@ -53,11 +32,11 @@ string VsInstall } } - void BuildSkiaWindowsMain(Architecture arch, Variant variant) + void BuildLibAlphaSkiaWindows() { var gnArgs = new Dictionary(); string[] filesToCopy; - var isShared = variant == Variant.Shared; + var isShared = Variant == Variant.Shared; if (isShared) { filesToCopy = new[] @@ -76,10 +55,10 @@ void BuildSkiaWindowsMain(Architecture arch, Variant variant) }; } - BuildSkiaWindows("libAlphaSkia", arch, variant, gnArgs, filesToCopy); + BuildSkiaWindows("libAlphaSkia", gnArgs, filesToCopy); } - void BuildSkiaWindowsJni(Architecture arch, Variant variant) + void BuildLibAlphaSkiaJniWindows() { var gnArgs = new Dictionary(); var alphaSkiaInclude = DistBasePath / "include"; @@ -88,11 +67,11 @@ void BuildSkiaWindowsJni(Architecture arch, Variant variant) gnArgs["extra_cflags"] = $"[ '-I{alphaSkiaInclude}', '-I{jniInclude}', '-I{jniWinInclude}' ]"; // Add Libs and lib search paths - var staticLibPath = DistBasePath / $"libAlphaSkia-win-{arch}-static"; + var staticLibPath = DistBasePath / GetLibDirectory(variant: Variant.Static); gnArgs["extra_ldflags"] = $"[ '/LIBPATH:{staticLibPath}', 'libAlphaSkia.lib', 'skia.lib', 'user32.lib', 'OpenGL32.lib' ]"; - BuildSkiaWindows("libAlphaSkiaJni", arch, variant, gnArgs, new[] + BuildSkiaWindows("libAlphaSkiaJni", gnArgs, new[] { "libAlphaSkiaJni.dll", "libAlphaSkiaJni.dll.lib", @@ -100,14 +79,11 @@ void BuildSkiaWindowsJni(Architecture arch, Variant variant) }); } - void BuildSkiaWindows(string buildTarget, Architecture arch, Variant variant, Dictionary gnArgs, + void BuildSkiaWindows(string buildTarget, Dictionary gnArgs, string[] filesToCopy) { - SetClangWindows(gnArgs); - gnArgs["skia_enable_fontmgr_win_gdi"] = "false"; - - BuildSkia(buildTarget, "win", arch, variant, gnArgs, filesToCopy); + BuildSkia(buildTarget, gnArgs, filesToCopy); } void SetClangWindows(Dictionary gnArgs) @@ -128,7 +104,7 @@ void SetClangWindows(Dictionary gnArgs) gnArgs["cc"] = "clang"; gnArgs["cxx"] = "'clang++'"; - + // override win_vc with the command line args var vsInstall = VsInstall; if (!string.IsNullOrEmpty(vsInstall)) @@ -137,7 +113,7 @@ void SetClangWindows(Dictionary gnArgs) winVc /= "VC"; gnArgs["win_vc"] = winVc; } - + AppendToFlagList(gnArgs, "extra_cflags", "'/MT', '/EHsc', '/Z7', '-D_HAS_AUTO_PTR_ETC=1'"); AppendToFlagList(gnArgs, "extra_ldflags", "'/DEBUG:FULL'"); } diff --git a/build/Build.cs b/build/Build.cs index 1cc9840..5b5d2e8 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -72,4 +72,24 @@ static void AppendToFlagList( } } }); + + bool CanUseCachedBinaries(string buildTarget, string targetOsDir) + { + if (!UseCache) + { + Log.Debug("Cache use is disabled."); + return false; + } + + if (!HasCachedFiles(buildTarget, targetOsDir)) + { + Log.Information("Did not find cached binaries."); + return false; + } + + Log.Information("Can use cached binaries, copying them to artifact output"); + FileSystemTasks.CopyDirectoryRecursively(DistBasePath, ArtifactBasePath, DirectoryExistsPolicy.Merge, FileExistsPolicy.OverwriteIfNewer); + + return true; + } } \ No newline at end of file diff --git a/lib/dotnet/AlphaSkia.Native.MacOs/AlphaSkia.Native.MacOs.csproj b/lib/dotnet/AlphaSkia.Native.MacOs/AlphaSkia.Native.MacOs.csproj new file mode 100644 index 0000000..04ef781 --- /dev/null +++ b/lib/dotnet/AlphaSkia.Native.MacOs/AlphaSkia.Native.MacOs.csproj @@ -0,0 +1,15 @@ + + + true + false + netstandard2.0 + README.md + $(NoWarn);NU5128 + + + + + + + + diff --git a/lib/dotnet/AlphaSkia.Native.MacOs/Marker.cs b/lib/dotnet/AlphaSkia.Native.MacOs/Marker.cs new file mode 100644 index 0000000..ad3c170 --- /dev/null +++ b/lib/dotnet/AlphaSkia.Native.MacOs/Marker.cs @@ -0,0 +1,6 @@ +namespace AlphaSkia.Native.Linux +{ + internal class Marker + { + } +} \ No newline at end of file diff --git a/lib/dotnet/AlphaSkia.Native.MacOs/README.md b/lib/dotnet/AlphaSkia.Native.MacOs/README.md new file mode 100644 index 0000000..a3b4da2 --- /dev/null +++ b/lib/dotnet/AlphaSkia.Native.MacOs/README.md @@ -0,0 +1,3 @@ +# AlphaSkia Linux Runtime Dependencies + +This package contains the AlphaSkia runtime dependencies for Linux \ No newline at end of file diff --git a/lib/dotnet/AlphaSkia.Test/AlphaSkia.Test.csproj b/lib/dotnet/AlphaSkia.Test/AlphaSkia.Test.csproj index 4530cbf..cca3adc 100644 --- a/lib/dotnet/AlphaSkia.Test/AlphaSkia.Test.csproj +++ b/lib/dotnet/AlphaSkia.Test/AlphaSkia.Test.csproj @@ -42,5 +42,14 @@ + + + + + diff --git a/lib/dotnet/AlphaSkia.sln b/lib/dotnet/AlphaSkia.sln index 15bd3c2..903164b 100644 --- a/lib/dotnet/AlphaSkia.sln +++ b/lib/dotnet/AlphaSkia.sln @@ -12,6 +12,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaSkia.Test", "AlphaSkia EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaSkia.Native.Android", "AlphaSkia.Native.Android\AlphaSkia.Native.Android.csproj", "{0500984B-5733-499A-850F-3CD964B9BE5A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaSkia.Native.MacOs", "AlphaSkia.Native.MacOs\AlphaSkia.Native.MacOs.csproj", "{6727C66F-7AD0-4E81-BDDE-E9422B0601A5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -38,6 +40,10 @@ Global {0500984B-5733-499A-850F-3CD964B9BE5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {0500984B-5733-499A-850F-3CD964B9BE5A}.Release|Any CPU.ActiveCfg = Release|Any CPU {0500984B-5733-499A-850F-3CD964B9BE5A}.Release|Any CPU.Build.0 = Release|Any CPU + {6727C66F-7AD0-4E81-BDDE-E9422B0601A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6727C66F-7AD0-4E81-BDDE-E9422B0601A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6727C66F-7AD0-4E81-BDDE-E9422B0601A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6727C66F-7AD0-4E81-BDDE-E9422B0601A5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {3693A53C-386E-4DBC-9B5E-9C3B7723FBE0} = {20757D78-DE4E-450B-97CC-24F926593193} diff --git a/lib/dotnet/AlphaSkia/AlphaSkiaPlatform.cs b/lib/dotnet/AlphaSkia/AlphaSkiaPlatform.cs index 00f28b1..9a2911e 100644 --- a/lib/dotnet/AlphaSkia/AlphaSkiaPlatform.cs +++ b/lib/dotnet/AlphaSkia/AlphaSkiaPlatform.cs @@ -72,7 +72,7 @@ private static string BuildKnownRid(out string libExtension) { PlatformID.Unix => "linux", PlatformID.Win32NT => "win", - PlatformID.MacOSX => "osx", + PlatformID.MacOSX => "macos", _ => officialOs }; if (string.IsNullOrEmpty(os)) diff --git a/lib/java/.idea/gradle.xml b/lib/java/.idea/gradle.xml index 0ccee45..5bd1ce6 100644 --- a/lib/java/.idea/gradle.xml +++ b/lib/java/.idea/gradle.xml @@ -11,6 +11,7 @@