diff --git a/bin/builders/BuilderFactory.ts b/bin/builders/BuilderFactory.ts index bec51fc..aa3e97c 100644 --- a/bin/builders/BuilderFactory.ts +++ b/bin/builders/BuilderFactory.ts @@ -1,7 +1,8 @@ -import { IS_MAC, IS_WIN } from '@/utils/platform.js'; +import { IS_MAC, IS_WIN, IS_LINUX } from '@/utils/platform.js'; import { IBuilder } from './base.js'; import MacBuilder from './MacBuilder.js'; import WinBuilder from './WinBulider.js'; +import LinuxBuilder from './LinuxBuilder.js'; export default class BuilderFactory { static create(): IBuilder { @@ -12,6 +13,9 @@ export default class BuilderFactory { if (IS_WIN) { return new WinBuilder(); } + if (IS_LINUX) { + return new LinuxBuilder(); + } throw new Error('The current system does not support!!'); } } diff --git a/bin/builders/LinuxBuilder.ts b/bin/builders/LinuxBuilder.ts index e69de29..278fa0b 100644 --- a/bin/builders/LinuxBuilder.ts +++ b/bin/builders/LinuxBuilder.ts @@ -0,0 +1,87 @@ +import fs from 'fs/promises'; +import path from 'path'; +import prompts from 'prompts'; +import { checkRustInstalled, installRust } from '@/helpers/rust.js'; +import { PakeAppOptions } from '@/types.js'; +import { IBuilder } from './base.js'; +import { shellExec } from '@/utils/shell.js'; +// @ts-expect-error 加上resolveJsonModule rollup会打包报错 +// import tauriConf from '../../src-tauri/tauri.windows.conf.json'; +import tauriConf from './tauriConf.js'; + +import { fileURLToPath } from 'url'; +import logger from '@/options/logger.js'; +import { mergeTauriConfig } from './common.js'; +import { npmDirectory } from '@/utils/dir.js'; + +export default class LinuxBuilder implements IBuilder { + async prepare() { + logger.info( + 'To build the Windows app, you need to install Rust and VS Build Tools.' + ); + logger.info( + 'See more in https://tauri.app/v1/guides/getting-started/prerequisites#installing\n' + ); + if (checkRustInstalled()) { + return; + } + + const res = await prompts({ + type: 'confirm', + message: 'We detected that you have not installed Rust. Install it now?', + name: 'value', + }); + + if (res.value) { + // TODO 国内有可能会超时 + await installRust(); + } else { + logger.error('Error: Pake needs Rust to package your webapp!!!'); + process.exit(2); + } + } + + async build(url: string, options: PakeAppOptions) { + logger.debug('PakeAppOptions', options); + const { name } = options; + + await mergeTauriConfig(url, options, tauriConf); + // write desktop + const assertSrc = `src-tauri/assets/${name}.desktop`; + const assertPath = path.join(npmDirectory, assertSrc); + const desktopStr = ` +[Desktop Entry] +Encoding=UTF-8 +Categories=Office +Exec=${name} +Icon=${name} +Name=${name} +StartupNotify=true +Terminal=false +Type=Application + ` + await fs.writeFile(assertPath, desktopStr); + const _ = await shellExec(`cd ${npmDirectory} && npm install && npm run build:release`); + let arch = ""; + if (process.arch === "x64") { + arch = "amd64"; + } else { + arch = process.arch; + } + const debName = `${name}_${tauriConf.package.version}_${arch}.deb`; + const appPath = this.getBuildedAppPath(npmDirectory, debName); + const distPath = path.resolve(`${name}.deb`); + await fs.copyFile(appPath, distPath); + await fs.unlink(appPath); + logger.success('Build success!'); + logger.success('You can find the app installer in', distPath); + } + + getBuildedAppPath(npmDirectory: string, dmgName: string) { + return path.join( + npmDirectory, + 'src-tauri/target/release/bundle/deb', + dmgName + ); + } +} \ No newline at end of file diff --git a/bin/builders/common.ts b/bin/builders/common.ts index 91ad334..ed0ac2e 100644 --- a/bin/builders/common.ts +++ b/bin/builders/common.ts @@ -44,8 +44,18 @@ export async function mergeTauriConfig( if (process.platform === "win32") { const ico_path = path.join(npmDirectory, 'src-tauri/png/weread_32.ico'); await fs.copyFile(options.icon, ico_path); - } + if (process.platform === "linux") { + const installSrc = `/usr/share/applications/${name}.desktop`; + const assertSrc = `src-tauri/assets/${name}.desktop`; + const assertPath = path.join(npmDirectory, assertSrc); + tauriConf.tauri.bundle.deb.files = { + [installSrc]: assertPath + } + + } + + let configPath = ""; switch (process.platform) { case "win32": { @@ -56,6 +66,10 @@ export async function mergeTauriConfig( configPath = path.join(npmDirectory, 'src-tauri/tauri.macos.conf.json'); break; } + case "linux": { + configPath = path.join(npmDirectory, 'src-tauri/tauri.linux.conf.json'); + break; + } } let bundleConf = {tauri: {bundle: tauriConf.tauri.bundle}}; diff --git a/bin/builders/tauriConf.js b/bin/builders/tauriConf.js index 6fa52e9..2b5fd20 100644 --- a/bin/builders/tauriConf.js +++ b/bin/builders/tauriConf.js @@ -1,6 +1,7 @@ import CommonConf from '../../src-tauri/tauri.conf.json'; import WinConf from '../../src-tauri/tauri.windows.conf.json'; import MacConf from '../../src-tauri/tauri.macos.conf.json'; +import LinuxConf from '../../src-tauri/tauri.linux.conf.json'; let tauriConf = { package: CommonConf.package, @@ -15,6 +16,10 @@ switch (process.platform) { tauriConf.tauri.bundle = MacConf.tauri.bundle; break; } + case "linux": { + tauriConf.tauri.bundle = LinuxConf.tauri.bundle; + break; + } } export default tauriConf; diff --git a/dist/cli.js b/dist/cli.js index 018abeb..b294c23 100644 --- a/dist/cli.js +++ b/dist/cli.js @@ -15,29 +15,29 @@ import ora from 'ora'; import shelljs from 'shelljs'; import updateNotifier from 'update-notifier'; -/****************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ - -function __awaiter(thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); } const DEFAULT_PAKE_OPTIONS = { @@ -1620,9 +1620,16 @@ function mergeTauriConfig(url, options, tauriConf) { tauriConf.tauri.bundle.icon = [options.icon]; if (process.platform === "win32") { const ico_path = path.join(npmDirectory, 'src-tauri/png/weread_32.ico'); - // tauriConf.tauri.bundle.resources = [options.icon]; yield fs.copyFile(options.icon, ico_path); } + if (process.platform === "linux") { + const installSrc = `/usr/share/applications/${name}.desktop`; + const assertSrc = `src-tauri/assets/${name}.desktop`; + const assertPath = path.join(npmDirectory, assertSrc); + tauriConf.tauri.bundle.deb.files = { + [installSrc]: assertPath + }; + } let configPath = ""; switch (process.platform) { case "win32": { @@ -1633,10 +1640,13 @@ function mergeTauriConfig(url, options, tauriConf) { configPath = path.join(npmDirectory, 'src-tauri/tauri.macos.conf.json'); break; } + case "linux": { + configPath = path.join(npmDirectory, 'src-tauri/tauri.linux.conf.json'); + break; + } } let bundleConf = { tauri: { bundle: tauriConf.tauri.bundle } }; yield fs.writeFile(configPath, Buffer.from(JSON.stringify(bundleConf), 'utf-8')); - // delete tauriConf.tauri.bundle; const configJsonPath = path.join(npmDirectory, 'src-tauri/tauri.conf.json'); yield fs.writeFile(configJsonPath, Buffer.from(JSON.stringify(tauriConf), 'utf-8')); }); @@ -1764,7 +1774,7 @@ function handleOptions(options, url) { const IS_MAC = process.platform === 'darwin'; const IS_WIN = process.platform === 'win32'; -process.platform === 'linux'; +const IS_LINUX = process.platform === 'linux'; function shellExec(command) { return new Promise((resolve, reject) => { @@ -1799,7 +1809,7 @@ function checkRustInstalled() { return shelljs.exec('rustc --version', { silent: true }).code === 0; } -var tauri$2 = { +var tauri$3 = { windows: [ { url: "https://www.baidu.com", @@ -1818,43 +1828,47 @@ var tauri$2 = { }, bundle: { icon: [ - "C:\\Users\\18826\\Documents\\electron_build\\Pake\\src-tauri\\png\\code_256.ico" + "/home/tlntin/文档/Program/Pake/src-tauri/png/code_512.png" ], identifier: "pake-f9751d", active: true, category: "DeveloperTool", copyright: "", + deb: { + depends: [ + "libwebkit2gtk-4.0-dev", + "build-essential", + "curl", + "wget", + "libssl-dev", + "libgtk-3-dev", + "libayatana-appindicator3-dev", + "librsvg2-dev" + ], + files: { + "/usr/share/applications/pake-f9751d-baidu.desktop": "/home/tlntin/文档/Program/Pake/src-tauri/assets/pake-f9751d-baidu.desktop" + } + }, externalBin: [ ], longDescription: "", resources: [ - "C:\\Users\\18826\\Documents\\electron_build\\Pake\\src-tauri\\png\\code_256.ico" ], shortDescription: "", targets: [ - "msi" - ], - windows: { - certificateThumbprint: null, - digestAlgorithm: "sha256", - timestampUrl: "", - wix: { - language: [ - "en-US" - ] - } - } + "deb" + ] } }; var CommonConf = { "package": { - version: "1.0.0", - productName: "baidu" + productName: "baidu", + version: "1.0.0" }, - tauri: tauri$2 + tauri: tauri$3 }; -var tauri$1 = { +var tauri$2 = { bundle: { icon: [ "png/weread_256.ico", @@ -1887,10 +1901,10 @@ var tauri$1 = { } }; var WinConf = { - tauri: tauri$1 + tauri: tauri$2 }; -var tauri = { +var tauri$1 = { bundle: { icon: [ "icons/weread.icns" @@ -1919,6 +1933,45 @@ var tauri = { } }; var MacConf = { + tauri: tauri$1 +}; + +var tauri = { + bundle: { + icon: [ + "/home/tlntin/文档/Program/Pake/src-tauri/png/code_512.png" + ], + identifier: "pake-f9751d", + active: true, + category: "DeveloperTool", + copyright: "", + deb: { + depends: [ + "libwebkit2gtk-4.0-dev", + "build-essential", + "curl", + "wget", + "libssl-dev", + "libgtk-3-dev", + "libayatana-appindicator3-dev", + "librsvg2-dev" + ], + files: { + "/usr/share/applications/pake-f9751d-baidu.desktop": "/home/tlntin/文档/Program/Pake/src-tauri/assets/pake-f9751d-baidu.desktop" + } + }, + externalBin: [ + ], + longDescription: "", + resources: [ + ], + shortDescription: "", + targets: [ + "deb" + ] + } +}; +var LinuxConf = { tauri: tauri }; @@ -1935,6 +1988,10 @@ switch (process.platform) { tauriConf.tauri.bundle = MacConf.tauri.bundle; break; } + case "linux": { + tauriConf.tauri.bundle = LinuxConf.tauri.bundle; + break; + } } class MacBuilder { @@ -2024,6 +2081,71 @@ class WinBuilder { } } +class LinuxBuilder { + prepare() { + return __awaiter(this, void 0, void 0, function* () { + logger.info('To build the Windows app, you need to install Rust and VS Build Tools.'); + logger.info('See more in https://tauri.app/v1/guides/getting-started/prerequisites#installing\n'); + if (checkRustInstalled()) { + return; + } + const res = yield prompts({ + type: 'confirm', + message: 'We detected that you have not installed Rust. Install it now?', + name: 'value', + }); + if (res.value) { + // TODO 国内有可能会超时 + yield installRust(); + } + else { + logger.error('Error: Pake needs Rust to package your webapp!!!'); + process.exit(2); + } + }); + } + build(url, options) { + return __awaiter(this, void 0, void 0, function* () { + logger.debug('PakeAppOptions', options); + const { name } = options; + yield mergeTauriConfig(url, options, tauriConf); + // write desktop + const assertSrc = `src-tauri/assets/${name}.desktop`; + const assertPath = path.join(npmDirectory, assertSrc); + const desktopStr = ` +[Desktop Entry] +Encoding=UTF-8 +Categories=Office +Exec=${name} +Icon=${name} +Name=${name} +StartupNotify=true +Terminal=false +Type=Application + `; + yield fs.writeFile(assertPath, desktopStr); + yield shellExec(`cd ${npmDirectory} && npm install && npm run build:release`); + let arch = ""; + if (process.arch === "x64") { + arch = "amd64"; + } + else { + arch = process.arch; + } + const debName = `${name}_${tauriConf.package.version}_${arch}.deb`; + const appPath = this.getBuildedAppPath(npmDirectory, debName); + const distPath = path.resolve(`${name}.deb`); + yield fs.copyFile(appPath, distPath); + yield fs.unlink(appPath); + logger.success('Build success!'); + logger.success('You can find the app installer in', distPath); + }); + } + getBuildedAppPath(npmDirectory, dmgName) { + return path.join(npmDirectory, 'src-tauri/target/release/bundle/deb', dmgName); + } +} + class BuilderFactory { static create() { console.log("now platform is ", process.platform); @@ -2033,6 +2155,9 @@ class BuilderFactory { if (IS_WIN) { return new WinBuilder(); } + if (IS_LINUX) { + return new LinuxBuilder(); + } throw new Error('The current system does not support!!'); } } diff --git a/script/build.sh b/script/build.sh index 36f71ad..45662cf 100755 --- a/script/build.sh +++ b/script/build.sh @@ -28,18 +28,13 @@ total=$(sed -n '$=' app.csv) export total=$((total-1)) export index=1 -old_name="weread" -old_title="WeRead" -old_zh_name="微信阅读" -old_url="https://weread.qq.com/" -package_prefix="com-tw93" +export old_name="weread" +export old_title="WeRead" +export old_zh_name="微信阅读" +export old_url="https://weread.qq.com/" +export package_prefix="com-tw93" -# set init name, we will recovery code to init when build finish. -export init_name=${old_name} -export init_title=${old_title} -export init_zh_name=${old_zh_name} -export init_url=${old_url} if [[ "$OSTYPE" =~ ^linux ]]; then echo "===============" @@ -71,7 +66,6 @@ do package_title=${arr[1]} package_zh_name=${arr[2]} url=${arr[3]} - echo "update package name and url" # replace package info $sd "${old_url}" "${url}" src-tauri/tauri.conf.json $sd "${old_name}" "${package_name}" src-tauri/tauri.conf.json @@ -123,21 +117,5 @@ do done echo "build all package success!" -if [[ "$OSTYPE" =~ ^linux ]]; then - # recovery linux code - $sd "\"productName\": \"com-tw93-weread\"" "\"productName\": \"WeRead\"" src-tauri/tauri.conf.json - $sd "${package_name}" "${init_name}" src-tauri/tauri.linux.conf.json - echo "result file in output/linux" -fi - -if [[ "$OSTYPE" =~ ^darwin ]]; then - # recovery macos code - $sd "\"productName\": \"weread\"" "\"productName\": \"WeRead\"" src-tauri/tauri.conf.json - $sd "${package_name}" "${init_name}" src-tauri/tauri.macos.conf.json - echo "result file in output/macos" -fi - -# recovery code -$sd "${url}" "${init_url}" src-tauri/tauri.conf.json -$sd ${package_name}" "${init_name}" src-tauri/tauri.conf.json -$sd ${package_name}" "${init_name}" src-tauri/src/main.rs \ No newline at end of file +echo "you run `rm src-tauri/assets/*.desktop && git checkout src-tauri` to recovery code" +# rm src-tauri/assets/*.desktop && git checkout src-tauri