refactor: remove js2asar.py and port logic to JS in more readable / GN-style way (#16718)
* refactor: remove js2asar.py and port logic to JS in more readable / GN-style way * refactor: further clean up ASAR impl, add new node_action GN template
This commit is contained in:
Родитель
8582325e85
Коммит
b202ad1e24
53
BUILD.gn
53
BUILD.gn
|
@ -137,7 +137,12 @@ action("atom_js2c") {
|
|||
rebase_path(sources, root_build_dir)
|
||||
}
|
||||
|
||||
asar("js2asar") {
|
||||
target_gen_electron_js = "$target_gen_dir/js/electron"
|
||||
target_gen_default_app_js = "$target_gen_dir/js/default_app"
|
||||
|
||||
# TODO(MarshallOfSound)
|
||||
# This copy will be replaced by a call to tsc in the future
|
||||
copy("lib_js") {
|
||||
sources = filenames.js_sources
|
||||
if (enable_desktop_capturer) {
|
||||
sources += [
|
||||
|
@ -156,18 +161,50 @@ asar("js2asar") {
|
|||
"lib/browser/api/views/text-field.js",
|
||||
]
|
||||
}
|
||||
|
||||
outputs = [
|
||||
"$target_gen_electron_js/{{source}}",
|
||||
]
|
||||
}
|
||||
|
||||
asar("electron_asar") {
|
||||
deps = [
|
||||
":lib_js",
|
||||
]
|
||||
|
||||
root = "$target_gen_electron_js/electron/lib"
|
||||
sources = get_target_outputs(":lib_js")
|
||||
outputs = [
|
||||
"$root_out_dir/resources/electron.asar",
|
||||
]
|
||||
root = "lib"
|
||||
}
|
||||
|
||||
asar("app2asar") {
|
||||
copy("default_app_js") {
|
||||
sources = filenames.default_app_sources
|
||||
outputs = [
|
||||
"$target_gen_default_app_js/{{source}}",
|
||||
]
|
||||
}
|
||||
|
||||
copy("default_app_octicon_deps") {
|
||||
sources = filenames.default_app_octicon_sources
|
||||
outputs = [
|
||||
"$target_gen_default_app_js/electron/default_app/octicon/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
|
||||
asar("default_app_asar") {
|
||||
deps = [
|
||||
":default_app_js",
|
||||
":default_app_octicon_deps",
|
||||
]
|
||||
|
||||
root = "$target_gen_default_app_js/electron/default_app"
|
||||
sources = get_target_outputs(":default_app_js") +
|
||||
get_target_outputs(":default_app_octicon_deps")
|
||||
outputs = [
|
||||
"$root_out_dir/resources/default_app.asar",
|
||||
]
|
||||
root = "default_app"
|
||||
}
|
||||
|
||||
grit("resources") {
|
||||
|
@ -712,9 +749,9 @@ if (is_mac) {
|
|||
|
||||
bundle_data("electron_app_resources") {
|
||||
public_deps = [
|
||||
":app2asar",
|
||||
":default_app_asar",
|
||||
":electron_app_strings_bundle_data",
|
||||
":js2asar",
|
||||
":electron_asar",
|
||||
]
|
||||
sources = [
|
||||
"$root_out_dir/resources/default_app.asar",
|
||||
|
@ -760,10 +797,10 @@ if (is_mac) {
|
|||
sources = filenames.app_sources
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":app2asar",
|
||||
":default_app_asar",
|
||||
":electron_app_manifest",
|
||||
":electron_asar",
|
||||
":electron_lib",
|
||||
":js2asar",
|
||||
":packed_resources",
|
||||
"//content:sandbox_helper_win",
|
||||
"//ui/strings",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import("npm.gni")
|
||||
import("node.gni")
|
||||
|
||||
# TODO(MarshallOfSound): Move to electron/node, this is the only place it is used now
|
||||
# Run an action with a given working directory. Behaves identically to the
|
||||
# action() target type, with the exception that it changes directory before
|
||||
# running the script.
|
||||
|
@ -32,19 +33,28 @@ template("chdir_action") {
|
|||
|
||||
template("asar") {
|
||||
assert(defined(invoker.sources),
|
||||
"Need sources in $target_name listing the JS files.")
|
||||
"Need sources in $target_name listing the source files")
|
||||
assert(defined(invoker.outputs),
|
||||
"Need asar name (as 1-element array, e.g. \$root_out_dir/foo.asar)")
|
||||
assert(defined(invoker.root), "Need asar root directory")
|
||||
asar_root = invoker.root
|
||||
assert(defined(invoker.root), "Need the base dir for generating the ASAR")
|
||||
|
||||
# js2asar.py expects relative paths to its inputs, so we must run it in a
|
||||
# working directory in which those relative paths make sense.
|
||||
chdir_action(target_name) {
|
||||
sources = invoker.sources
|
||||
outputs = invoker.outputs
|
||||
script = "//electron/tools/js2asar.py"
|
||||
cwd = rebase_path(get_path_info(".", "abspath"))
|
||||
args = rebase_path(outputs, cwd) + [ asar_root ] + rebase_path(sources, ".")
|
||||
node_action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
"*",
|
||||
[
|
||||
"script",
|
||||
"args",
|
||||
])
|
||||
|
||||
script = "//electron/script/gn-asar.js"
|
||||
args = [
|
||||
"--base",
|
||||
rebase_path(root),
|
||||
"--files",
|
||||
] + rebase_path(sources) +
|
||||
[
|
||||
"--out",
|
||||
rebase_path(outputs[0]),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
template("node_action") {
|
||||
assert(defined(invoker.script), "Need script path to run")
|
||||
assert(defined(invoker.args), "Need script argumets")
|
||||
|
||||
action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"deps",
|
||||
"public_deps",
|
||||
"sources",
|
||||
"inputs",
|
||||
"outputs",
|
||||
])
|
||||
if (!defined(inputs)) {
|
||||
inputs = []
|
||||
}
|
||||
inputs += [ invoker.script ]
|
||||
script = "//electron/build/run-node.py"
|
||||
args = [ rebase_path(invoker.script) ] + invoker.args
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
SOURCE_ROOT = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
def main():
|
||||
# Proxy all args to node script
|
||||
script = os.path.join(SOURCE_ROOT, sys.argv[1])
|
||||
subprocess.check_call(['node', script] + [str(x) for x in sys.argv[2:]])
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -4,7 +4,7 @@
|
|||
<title>Electron</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'" />
|
||||
<link href="./styles.css" type="text/css" rel="stylesheet" />
|
||||
<link href="./node_modules/octicons/build/build.css" type="text/css" rel="stylesheet" />
|
||||
<link href="./octicon/build.css" type="text/css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -35,7 +35,7 @@ function initialize () {
|
|||
document.querySelector('.command-example').innerText = `${electronPath} path-to-app`
|
||||
|
||||
function getOcticonSvg (name) {
|
||||
const octiconPath = path.resolve(__dirname, 'node_modules', 'octicons', 'build', 'svg', `${name}.svg`)
|
||||
const octiconPath = path.resolve(__dirname, 'octicon', `${name}.svg`)
|
||||
if (fs.existsSync(octiconPath)) {
|
||||
const content = fs.readFileSync(octiconPath, 'utf8')
|
||||
const div = document.createElement('div')
|
||||
|
|
|
@ -99,6 +99,9 @@ filenames = {
|
|||
"default_app/package.json",
|
||||
"default_app/renderer.js",
|
||||
"default_app/styles.css",
|
||||
]
|
||||
|
||||
default_app_octicon_sources = [
|
||||
"node_modules/octicons/build/build.css",
|
||||
"node_modules/octicons/build/svg/gist.svg",
|
||||
"node_modules/octicons/build/svg/mark-github.svg",
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
const asar = require('asar')
|
||||
const assert = require('assert')
|
||||
const fs = require('fs-extra')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
|
||||
const getArgGroup = (name) => {
|
||||
const group = []
|
||||
let inGroup = false
|
||||
for (const arg of process.argv) {
|
||||
// At the next flag we stop being in the current group
|
||||
if (arg.startsWith('--')) inGroup = false
|
||||
// Push all args in the group
|
||||
if (inGroup) group.push(arg)
|
||||
// If we find the start flag, start pushing
|
||||
if (arg === `--${name}`) inGroup = true
|
||||
}
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
const base = getArgGroup('base')
|
||||
const files = getArgGroup('files')
|
||||
const out = getArgGroup('out')
|
||||
|
||||
assert(base.length === 1, 'should have a single base dir')
|
||||
assert(files.length >= 1, 'should have at least one input file')
|
||||
assert(out.length === 1, 'should have a single out path')
|
||||
|
||||
// Ensure all files are inside the base dir
|
||||
for (const file of files) {
|
||||
if (!file.startsWith(base[0])) {
|
||||
console.error(`Expected all files to be inside the base dir but "${file}" was not in "${base[0]}"`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const tmpPath = fs.mkdtempSync(path.resolve(os.tmpdir(), 'electron-gn-asar-'))
|
||||
|
||||
try {
|
||||
// Copy all files to a tmp dir to avoid including scrap files in the ASAR
|
||||
for (const file of files) {
|
||||
const newLocation = path.resolve(tmpPath, path.relative(base[0], file))
|
||||
fs.mkdirsSync(path.dirname(newLocation))
|
||||
fs.writeFileSync(newLocation, fs.readFileSync(file))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Unexpected error while generating ASAR', err)
|
||||
fs.removeSync(tmpPath)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Create the ASAR archive
|
||||
asar.createPackageWithOptions(tmpPath, out[0], {}, (err) => {
|
||||
fs.removeSync(tmpPath)
|
||||
|
||||
if (err) {
|
||||
console.error('Unexpected error while generating ASAR', err)
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
|
@ -1,51 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import errno
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
SOURCE_ROOT = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def main():
|
||||
archive = sys.argv[1]
|
||||
folder_name = sys.argv[2]
|
||||
source_files = sys.argv[3:]
|
||||
|
||||
output_dir = tempfile.mkdtemp()
|
||||
copy_files(source_files, output_dir, folder_name)
|
||||
call_asar(archive, os.path.join(output_dir, folder_name))
|
||||
shutil.rmtree(output_dir)
|
||||
|
||||
|
||||
def copy_files(source_files, output_dir, folder_name):
|
||||
for source_file in source_files:
|
||||
output_path = os.path.join(output_dir, source_file)
|
||||
# Files that aren't in the default_app folder need to be put inside
|
||||
# the temp one we are making so they end up in the ASAR
|
||||
if not os.path.normpath(source_file).startswith(folder_name + os.sep):
|
||||
output_path = os.path.join(output_dir, folder_name, source_file)
|
||||
safe_mkdir(os.path.dirname(output_path))
|
||||
shutil.copy2(source_file, output_path)
|
||||
|
||||
|
||||
def call_asar(archive, output_dir):
|
||||
asar = os.path.join(SOURCE_ROOT, 'node_modules', '.bin', 'asar')
|
||||
if sys.platform in ['win32', 'cygwin']:
|
||||
asar += '.cmd'
|
||||
subprocess.check_call([asar, 'pack', output_dir, archive])
|
||||
|
||||
|
||||
def safe_mkdir(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
Загрузка…
Ссылка в новой задаче