Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update webview, add linux ARM target #189

Merged
merged 25 commits into from
Jan 29, 2025
Merged
51 changes: 36 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ jobs:
timeout-minutes: 60
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
os:
[
macos-latest,
macos-13,
windows-latest,
ubuntu-latest,
ubuntu-24.04-arm,
eliassjogreen marked this conversation as resolved.
Show resolved Hide resolved
]

steps:
- name: Clone repository
Expand All @@ -33,10 +40,22 @@ jobs:
deno-version: v2.x

- name: install webkit2gtk (Linux)
if: matrix.os == 'ubuntu-latest'
if: startsWith(matrix.os, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y webkit2gtk-4.0
sudo apt-get install -y webkitgtk-6.0 libwebkitgtk-6.0-dev cmake ninja-build clang pkg-config libgtk-4-dev

- name: Install ninja (macOS)
if: startsWith(matrix.os, 'macos')
run: |
brew install ninja
brew install llvm
echo "WEBVIEW_CLANG_FORMAT_EXE=$(brew --prefix llvm)/bin/clang-format" >> $GITHUB_ENV

- name: Install ninja (Windows)
if: matrix.os == 'windows-latest'
run: |
choco install ninja

- name: Build dynamic library
run: deno task build
Expand All @@ -50,15 +69,17 @@ jobs:
build/*.dylib
build/*.so

# - name: Release Plugin
# uses: softprops/action-gh-release@master
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# tag_name: "webview_deno release"
# draft: true
# files: |
# build/libwebview.x86_64.dylib
# build/libwebview.so
# build/webview.dll
# build/Webview2Loader.dll
# - name: Release Plugin
# uses: softprops/action-gh-release@master
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# tag_name: "webview_deno release"
# draft: true
# files: |
# build/libwebview.x86_64.dylib
# build/libwebview.aarch64.dylib
# build/libwebview.x86_64.so
# build/libwebview.aarch64.so
# build/webview.dll
# build/Webview2Loader.dll
71 changes: 12 additions & 59 deletions script/build.bat
Original file line number Diff line number Diff line change
@@ -1,76 +1,29 @@
@echo off

echo Prepare directories...
set script_dir=%~dp0
set src_dir=%script_dir%..\webview
set build_dir=%script_dir%..\build
mkdir "%build_dir%"

echo Webview directory: %src_dir%
echo Build directory: %build_dir%

:: If you update the nuget package, change its version here
set nuget_version=1.0.1150.38
echo Using Nuget Package microsoft.web.webview2.%nuget_version%
if not exist "%script_dir%\microsoft.web.webview2.%nuget_version%" (
curl -sSLO https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
nuget.exe install Microsoft.Web.Webview2 -Version %nuget_version% -OutputDirectory %script_dir%
echo Nuget package installed
)

echo Looking for vswhere.exe...
set "vswhere=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
if not exist "%vswhere%" set "vswhere=%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"
if not exist "%vswhere%" (
echo ERROR: Failed to find vswhere.exe
exit /b 1
echo ERROR: Failed to find vswhere.exe
exit /b 1
)
echo Found %vswhere%

echo Looking for VC...
for /f "usebackq tokens=*" %%i in (`"%vswhere%" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (
set vc_dir=%%i
set vc_dir=%%i
)
if not exist "%vc_dir%\Common7\Tools\vsdevcmd.bat" (
echo ERROR: Failed to find VC tools x86/x64
exit /b 1
echo ERROR: Failed to find VC tools x86/x64
exit /b 1
)
echo Found %vc_dir%

:: 4100: unreferenced formal parameter
set warning_params=/W4 /wd4100

:: build dlls if not found
if not exist "%src_dir%\dll\x64\webview.dll" (
mkdir "%src_dir%\dll\x86"
mkdir "%src_dir%\dll\x64"
copy "%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\x64\WebView2Loader.dll" "%src_dir%\dll\x64"
copy "%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\x86\WebView2Loader.dll" "%src_dir%\dll\x86"

call "%vc_dir%\Common7\Tools\vsdevcmd.bat" -arch=x86 -host_arch=x64

echo "Building webview.dll (x86)"
cl %warning_params% ^
/D "WEBVIEW_API=__declspec(dllexport)" ^
/I "%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\include" ^
"%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\x86\WebView2Loader.dll.lib" ^
/std:c++17 /EHsc "/Fo%build_dir%"\ ^
"%src_dir%\webview.cc" /link /DLL "/OUT:%src_dir%\dll\x86\webview.dll" || exit \b
call "%vc_dir%\Common7\Tools\vsdevcmd.bat" -arch=x64 -host_arch=x64
cd %~dp0..\webview

call "%vc_dir%\Common7\Tools\vsdevcmd.bat" -arch=x64 -host_arch=x64
echo "Building webview.dll (x64)"
cl %warning_params% ^
/D "WEBVIEW_API=__declspec(dllexport)" ^
/I "%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\include" ^
"%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\x64\WebView2Loader.dll.lib" ^
/std:c++17 /EHsc "/Fo%build_dir%"\ ^
"%src_dir%\webview.cc" /link /DLL "/OUT:%src_dir%\dll\x64\webview.dll" || exit \b
)
if not exist "%build_dir%\webview.dll" (
copy "%src_dir%\dll\x64\webview.dll" %build_dir%
)
if not exist "%build_dir%\WebView2Loader.dll" (
copy "%script_dir%\microsoft.web.webview2.%nuget_version%\build\native\x64\WebView2Loader.dll" "%build_dir%"
)
cmake -G "Ninja Multi-Config" -B build -S . ^
-DWEBVIEW_BUILD_DOCS=OFF ^
-DWEBVIEW_USE_CLANG_TIDY=OFF ^
-DWEBVIEW_USE_CLANG_FORMAT=OFF

call "%vc_dir%\Common7\Tools\vsdevcmd.bat" -arch=x64 -host_arch=x64
cmake --build build --config Release
188 changes: 32 additions & 156 deletions script/build.ts
Original file line number Diff line number Diff line change
@@ -1,162 +1,38 @@
import { ensureDir } from "jsr:@std/fs@0.218/ensure_dir";
import { $ } from "jsr:@david/dax@0.42.0";

const decoder = new TextDecoder();
const architectures = [["x86_64", "x86_64"], ["aarch64", "arm64"]] as const;
const { os } = Deno.build;
$.setPrintCommand(true);

const ExitType = {
Exit: "exit",
Fail: "fail",
Never: "never",
} as const;
type ExitType = typeof ExitType[keyof typeof ExitType];

const LogType = {
Success: "success",
Always: "always",
Fail: "fail",
Never: "never",
} as const;
type LogType = typeof LogType[keyof typeof LogType];

function indent(source: string, spaces = 2): string {
return source.split("\n").map((line) => `${" ".repeat(spaces)}${line}\n`)
.join("");
}

async function command<T extends Deno.CommandOptions>(
cmd: string,
{ opts, exit, log }: { opts?: T; exit?: ExitType; log?: LogType } = {},
): Promise<{
code: number;
stdout: string;
stderr: string;
}> {
if (opts !== undefined) {
opts.stdout = "piped";
opts.stderr = "piped";
}

exit ??= ExitType.Never;
log ??= LogType.Always;

const command = new Deno.Command(cmd, opts);
const { code, stdout, stderr } = await command.output();

const stdoutStr = decoder.decode(stdout);
const stderrStr = decoder.decode(stderr);

if (code === 0) {
if (log !== "never") {
console.log(`Successfully ran "${cmd} ${(opts?.args ?? []).join(" ")}"`);
}

if (log === "success" || log === "always") {
if (stdoutStr.length !== 0) {
console.log(`stdout:\n${indent(stdoutStr)}`);
}
if (stderrStr.length !== 0) {
console.log(`stderr:\n${indent(stderrStr)}`);
}
}
} else {
if (log !== "never") {
console.log(`Failed run "${cmd}"`);
}

if (log === "fail" || log === "always") {
if (stdoutStr.length !== 0) {
console.log(`stdout:\n${indent(stdoutStr)}`);
}
if (stderrStr.length !== 0) {
console.log(`stderr:\n${indent(stderrStr)}`);
}
console.log(`code: ${code}`);
}

if (exit === ExitType.Fail) {
Deno.exit(code);
}
}

if (exit === ExitType.Exit) {
Deno.exit(code);
}

return {
code,
stdout: stdoutStr,
stderr: stderrStr,
};
}

await ensureDir("build");

switch (Deno.build.os) {
case "windows": {
await command("script/build.bat", {
exit: ExitType.Exit,
});
await $.path("./build").ensureDir();
switch (os) {
case "windows":
await $`script/build.bat`;
await $`cp webview/build/core/Release/webview.dll build/webview.dll`;
break;
}

case "darwin": {
for (const [denoArch, gccArch] of architectures) {
await command("c++", {
opts: {
exit: ExitType.Fail,
args: [
"webview/webview.cc",
"-dynamiclib",
"-fpic",
"-DWEBVIEW_COCOA",
"-std=c++11",
"-Wall",
"-Wextra",
"-pedantic",
"-framework",
"WebKit",
"-arch",
gccArch,
"-o",
`build/libwebview.${denoArch}.dylib`,
],
},
});
}
Deno.exit(0);
case "linux":
$.cd("webview");
await $`export PATH=/usr/lib/llvm14/bin/:/usr/lib/llvm-14/bin/:/usr/lib64/llvm15/bin/:$PATH`;
await $`cmake -G Ninja -B build -S . -D CMAKE_BUILD_TYPE=Release -D WEBVIEW_WEBKITGTK_API=6.0 -DWEBVIEW_ENABLE_CHECKS=false -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/host-llvm.cmake -DWEBVIEW_USE_CLANG_TIDY=OFF -DWEBVIEW_BUILD_DOCS=OFF -DWEBVIEW_USE_CLANG_FORMAT=OFF`;
await $`cmake --build build`;
await $`cp build/core/libwebview.so ../build/libwebview.${Deno.build.arch}.so`;
await $`strip ../build/libwebview.${Deno.build.arch}.so`;
break;
}

case "linux": {
const { stdout } = await command("pkg-config", {
opts: {
args: [
"--cflags",
"--libs",
"gtk+-3.0",
"webkit2gtk-4.0",
],
},
});
await command("c++", {
opts: {
exit: ExitType.Fail,
args: [
"webview/webview.cc",
"-DWEBVIEW_GTK",
"-shared",
"-std=c++11",
"-Wall",
"-Wextra",
"-pedantic",
"-fpic",
...stdout.trim().split(" "),
"-o",
"build/libwebview.so",
],
},
});
Deno.exit(0);
case "darwin":
$.cd("webview");
await $`cmake -G "Ninja Multi-Config" -B build -S . \
-DCMAKE_BUILD_TYPE=Release \
-DWEBVIEW_BUILD_TESTS=OFF \
-DWEBVIEW_BUILD_EXAMPLES=OFF \
-DWEBVIEW_USE_CLANG_TOOLS=OFF \
-DWEBVIEW_ENABLE_CHECKS=OFF \
-DWEBVIEW_USE_CLANG_TIDY=OFF \
-DWEBVIEW_BUILD_DOCS=OFF \
-DWEBVIEW_USE_CLANG_FORMAT=OFF \
-DWEBVIEW_CLANG_FORMAT_EXE=${Deno.env.get(
"WEBVIEW_CLANG_FORMAT_EXE",
)!}`;
await $`cmake --build build --config Release`;
await $`cp build/core/Release/libwebview.dylib ../build/libwebview.${Deno.build.arch}.dylib`;
await $`strip -x -S ../build/libwebview.${Deno.build.arch}.dylib`;
break;
}
}
1 change: 1 addition & 0 deletions src/ffi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export const lib = await dlopen(
url,
cache,
suffixes: {
linux: `.${Deno.build.arch}`,
darwin: `.${Deno.build.arch}`,
},
},
Expand Down
2 changes: 1 addition & 1 deletion webview
Submodule webview updated 116 files