bare-build 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CMakeLists.txt +27 -15
  2. package/README.md +2 -0
  3. package/bin.js +3 -0
  4. package/index.js +5 -5
  5. package/lib/assets/apple/icon.png +0 -0
  6. package/lib/assets/linux/icon.png +0 -0
  7. package/lib/assets/windows/icon.png +0 -0
  8. package/lib/assets.js +13 -0
  9. package/lib/builtins.json +7 -0
  10. package/lib/fs.js +2 -2
  11. package/lib/platform/apple/create-app.js +6 -8
  12. package/lib/platform/apple/create-executable.js +60 -0
  13. package/lib/platform/apple/create-package-component.js +2 -2
  14. package/lib/platform/apple/create-package.js +2 -2
  15. package/lib/platform/apple/sign.js +58 -9
  16. package/lib/platform/apple.js +24 -11
  17. package/lib/platform/linux/create-app-dir.js +2 -1
  18. package/lib/platform/linux/create-app-image.js +1 -1
  19. package/lib/platform/linux/create-executable.js +50 -0
  20. package/lib/platform/linux.js +24 -11
  21. package/lib/platform/windows/create-executable.js +50 -0
  22. package/lib/platform/windows/create-msix-content-directory.js +11 -5
  23. package/lib/platform/windows/create-msix.js +1 -1
  24. package/lib/platform/windows.js +24 -11
  25. package/lib/runtime/apple.h +22 -0
  26. package/lib/runtime/linux.h +17 -0
  27. package/lib/runtime/windows.h +45 -0
  28. package/lib/runtime.bundle.h +16696 -0
  29. package/lib/runtime.bundle.h.d +1 -0
  30. package/lib/runtime.c +81 -33
  31. package/lib/runtime.js +36 -0
  32. package/package.json +6 -3
  33. package/prebuilds/darwin-arm64/bare +0 -0
  34. package/prebuilds/darwin-x64/bare +0 -0
  35. package/prebuilds/ios-arm64/bare +0 -0
  36. package/prebuilds/ios-arm64-simulator/bare +0 -0
  37. package/prebuilds/ios-x64-simulator/bare +0 -0
  38. package/prebuilds/linux-arm64/bare +0 -0
  39. package/prebuilds/linux-x64/bare +0 -0
  40. package/prebuilds/win32-arm64/bare.exe +0 -0
  41. package/prebuilds/win32-x64/bare.exe +0 -0
package/CMakeLists.txt CHANGED
@@ -1,6 +1,7 @@
1
1
  cmake_minimum_required(VERSION 4.0)
2
2
 
3
3
  find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare)
4
+ find_package(cmake-bare-bundle REQUIRED PATHS node_modules/cmake-bare-bundle)
4
5
  find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch)
5
6
 
6
7
  project(bare_build C)
@@ -8,28 +9,39 @@ project(bare_build C)
8
9
  fetch_package("github:holepunchto/bare@1.24.3")
9
10
  fetch_package("github:holepunchto/libpath")
10
11
 
11
- add_executable(bare_build)
12
+ add_bare_bundle(
13
+ bare_runtime_bundle
14
+ ENTRY lib/runtime.js
15
+ OUT lib/runtime.bundle.h
16
+ BUILTINS lib/builtins.json
17
+ )
18
+
19
+ add_executable(bare_runtime)
12
20
 
13
21
  target_sources(
14
- bare_build
22
+ bare_runtime
15
23
  PRIVATE
16
24
  lib/runtime.c
25
+ lib/runtime.bundle.h
26
+ lib/runtime/apple.h
27
+ lib/runtime/linux.h
28
+ lib/runtime/windows.h
17
29
  )
18
30
 
19
31
  if(APPLE)
20
- set(bare_build_rpath "@loader_path/../Frameworks")
32
+ set(bare_runtime_rpath "@loader_path/../Frameworks")
21
33
  elseif(LINUX)
22
- set(bare_build_rpath "$ORIGIN/../lib")
34
+ set(bare_runtime_rpath "$ORIGIN/../lib")
23
35
  else()
24
36
  set(${target}_rpath "")
25
37
  endif()
26
38
 
27
39
  set_target_properties(
28
- bare_build
40
+ bare_runtime
29
41
  PROPERTIES
30
42
  OUTPUT_NAME bare
31
43
 
32
- INSTALL_RPATH "${bare_build_rpath}"
44
+ INSTALL_RPATH "${bare_runtime_rpath}"
33
45
  BUILD_WITH_INSTALL_RPATH ON
34
46
 
35
47
  ENABLE_EXPORTS ON
@@ -37,7 +49,7 @@ set_target_properties(
37
49
  )
38
50
 
39
51
  target_link_libraries(
40
- bare_build
52
+ bare_runtime
41
53
  PUBLIC
42
54
  $<LINK_LIBRARY:WHOLE_ARCHIVE,bare_static>
43
55
  PRIVATE
@@ -58,18 +70,18 @@ if(WIN32)
58
70
  file(GENERATE OUTPUT "runtime.manifest" CONTENT "${manifest}" NEWLINE_STYLE WIN32)
59
71
 
60
72
  target_sources(
61
- bare_build
73
+ bare_runtime
62
74
  PRIVATE
63
75
  "${CMAKE_CURRENT_BINARY_DIR}/runtime.manifest"
64
76
  )
65
-
66
- target_link_options(
67
- bare_build
68
- PRIVATE
69
- $<$<CONFIG:Release>:/subsystem:windows /entry:mainCRTStartup>
70
- )
71
77
  endif()
72
78
 
79
+ link_bare_module(bare_runtime bare-fs)
80
+ link_bare_module(bare_runtime bare-module)
81
+ link_bare_module(bare_runtime bare-module-lexer)
82
+ link_bare_module(bare_runtime bare-os)
83
+ link_bare_module(bare_runtime bare-url)
84
+
73
85
  bare_target(target)
74
86
 
75
- install(TARGETS bare_build RUNTIME DESTINATION ${target})
87
+ install(TARGETS bare_runtime RUNTIME DESTINATION ${target})
package/README.md CHANGED
@@ -44,6 +44,7 @@ options = {
44
44
  identifier,
45
45
  target: [],
46
46
  out: '.',
47
+ standalone: false,
47
48
  package: false,
48
49
  sign: false,
49
50
 
@@ -80,6 +81,7 @@ Flags include:
80
81
  --identifier <id> The unique application identifier
81
82
  --target|-t <host> The host to target
82
83
  --out|-o <dir> The output directory
84
+ --standalone Build a standalone executable
83
85
  --package Package the application for distribution
84
86
  --sign Sign the application
85
87
  --identity <id> The macOS signing identity
package/bin.js CHANGED
@@ -16,6 +16,7 @@ const cmd = command(
16
16
  flag('--identifier <id>', 'The unique application identifier'),
17
17
  flag('--target|-t <host>', 'The host to target').multiple(),
18
18
  flag('--out|-o <dir>', 'The output directory'),
19
+ flag('--standalone', 'Build a standalone executable'),
19
20
  flag('--package', 'Package the application for distribution'),
20
21
  flag('--sign', 'Sign the application'),
21
22
  flag('--identity <id>', 'The macOS signing identity'),
@@ -39,6 +40,7 @@ const cmd = command(
39
40
  identifier,
40
41
  target,
41
42
  out,
43
+ standalone,
42
44
  package,
43
45
  sign,
44
46
  identity,
@@ -64,6 +66,7 @@ const cmd = command(
64
66
  identifier,
65
67
  target,
66
68
  out,
69
+ standalone,
67
70
  package,
68
71
  sign,
69
72
  identity,
package/index.js CHANGED
@@ -3,10 +3,10 @@ const { pathToFileURL } = require('url')
3
3
  const { resolve } = require('bare-module-traverse')
4
4
  const id = require('bare-bundle-id')
5
5
  const pack = require('bare-pack')
6
- const fs = require('bare-pack/fs')
6
+ const { readModule, listPrefix } = require('bare-pack/fs')
7
7
 
8
8
  module.exports = async function* build(entry, opts = {}) {
9
- const { base = '.', target = [], hosts = target } = opts
9
+ const { base = '.', target = [], hosts = target, standalone = false } = opts
10
10
 
11
11
  let pkg
12
12
  try {
@@ -19,11 +19,11 @@ module.exports = async function* build(entry, opts = {}) {
19
19
  pathToFileURL(entry),
20
20
  {
21
21
  hosts,
22
- linked: true,
22
+ linked: standalone === false,
23
23
  resolve: resolve.bare
24
24
  },
25
- fs.readModule,
26
- fs.listPrefix
25
+ readModule,
26
+ listPrefix
27
27
  )
28
28
 
29
29
  bundle = bundle.unmount(pathToFileURL(base))
Binary file
Binary file
Binary file
package/lib/assets.js ADDED
@@ -0,0 +1,13 @@
1
+ require.asset = require('require-asset')
2
+
3
+ module.exports = {
4
+ apple: {
5
+ icon: require.asset('./assets/apple/icon.png', __filename)
6
+ },
7
+ linux: {
8
+ icon: require.asset('./assets/linux/icon.png', __filename)
9
+ },
10
+ windows: {
11
+ icon: require.asset('./assets/windows/icon.png', __filename)
12
+ }
13
+ }
@@ -0,0 +1,7 @@
1
+ [
2
+ { "addon": "bare-fs" },
3
+ { "addon": "bare-module" },
4
+ { "addon": "bare-module-lexer" },
5
+ { "addon": "bare-os" },
6
+ { "addon": "bare-url" }
7
+ ]
package/lib/fs.js CHANGED
@@ -54,9 +54,9 @@ exports.writeFile = async function writeFile(name, data) {
54
54
  }
55
55
 
56
56
  exports.readFile = async function readFile(name) {
57
- return new Promise((resolve) => {
57
+ return new Promise((resolve, reject) => {
58
58
  fs.readFile(name, (err, data) => {
59
- resolve(err ? null : data)
59
+ err ? reject(err) : resolve(data)
60
60
  })
61
61
  })
62
62
  }
@@ -4,15 +4,16 @@ const unpack = require('bare-unpack')
4
4
  const { MachO } = require('bare-lief')
5
5
  const fs = require('../../fs')
6
6
  const prebuilds = require('../../prebuilds')
7
+ const { apple } = require('../../assets')
7
8
  const sign = require('./sign')
8
9
  const toIdentifier = require('./to-identifier')
9
10
 
10
11
  // https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle
11
12
  module.exports = async function* createApp(base, pkg, bundle, hosts, out, opts = {}) {
12
13
  const {
13
- name = pkg.name,
14
- version = pkg.version,
15
- icon,
14
+ name = pkg.name || 'App',
15
+ version = pkg.version || '1.0.0',
16
+ icon = apple.icon,
16
17
  identity,
17
18
  applicationIdentity = identity
18
19
  } = opts
@@ -32,11 +33,7 @@ module.exports = async function* createApp(base, pkg, bundle, hosts, out, opts =
32
33
 
33
34
  const frameworks = path.join(main, 'Frameworks')
34
35
 
35
- const executable = isMac ? path.join(main, 'MacOS', name) : path.join(main, name)
36
-
37
- if (isMac) {
38
- await fs.makeDir(path.join(main, 'MacOS'))
39
- }
36
+ if (isMac) await fs.makeDir(path.join(main, 'MacOS'))
40
37
 
41
38
  yield* link(base, { ...opts, hosts, identity: applicationIdentity, out: frameworks })
42
39
 
@@ -48,6 +45,7 @@ module.exports = async function* createApp(base, pkg, bundle, hosts, out, opts =
48
45
 
49
46
  const fat = MachO.FatBinary.merge(binaries)
50
47
 
48
+ const executable = isMac ? path.join(main, 'MacOS', name) : path.join(main, name)
51
49
  fat.toDisk(executable)
52
50
  await fs.chmod(executable, 0o755)
53
51
  await sign(executable, opts)
@@ -0,0 +1,60 @@
1
+ const path = require('path')
2
+ const { MachO } = require('bare-lief')
3
+ const fs = require('../../fs')
4
+ const prebuilds = require('../../prebuilds')
5
+ const sign = require('./sign')
6
+
7
+ module.exports = async function* createExecutable(pkg, bundle, hosts, out, opts = {}) {
8
+ const { name = pkg.name || 'App' } = opts
9
+
10
+ await fs.makeDir(out)
11
+
12
+ const temp = await fs.tempDir()
13
+ try {
14
+ for (const addon of bundle.addons) {
15
+ const target = path.join(temp, addon)
16
+ await fs.makeDir(path.dirname(target))
17
+ await fs.writeFile(target, bundle.read(addon))
18
+ await sign(target, opts)
19
+
20
+ bundle.write(addon, await fs.readFile(target))
21
+ }
22
+ } finally {
23
+ await fs.rm(temp)
24
+ }
25
+
26
+ const inputs = hosts.map((host) => prebuilds[host]())
27
+
28
+ const binaries = []
29
+
30
+ for (const input of inputs) binaries.push(new MachO.FatBinary(await fs.readFile(input)))
31
+
32
+ const fat = MachO.FatBinary.merge(binaries)
33
+
34
+ const section = new MachO.Section('__bundle', bundle.toBuffer())
35
+
36
+ const segment = new MachO.SegmentCommand('__BARE')
37
+
38
+ segment.maxProtection = segment.initialProtection = MachO.SegmentCommand.VM_PROTECTIONS.READ
39
+
40
+ segment.addSection(section)
41
+
42
+ for (const binary of fat) {
43
+ binary.addSegmentCommand(segment)
44
+ }
45
+
46
+ const executable = path.join(out, toIdentifier(name))
47
+ fat.toDisk(executable)
48
+ await fs.chmod(executable, 0o755)
49
+ await sign(executable, opts)
50
+ yield executable
51
+
52
+ return executable
53
+ }
54
+
55
+ function toIdentifier(input) {
56
+ return input
57
+ .replace(/[^a-z0-9]+/gi, '-')
58
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
59
+ .toLowerCase()
60
+ }
@@ -10,8 +10,8 @@ module.exports = async function* createPackageComponent(pkg, root, id, opts = {}
10
10
  }
11
11
 
12
12
  let {
13
- name = pkg.name,
14
- version = pkg.version,
13
+ name = pkg.name || 'App',
14
+ version = pkg.version || '1.0.0',
15
15
  identifier = toIdentifier(name),
16
16
  sign = false,
17
17
  identity = 'Apple Development',
@@ -4,8 +4,8 @@ const run = require('../../run')
4
4
 
5
5
  module.exports = async function* createPackage(pkg, root, components, out, opts = {}) {
6
6
  const {
7
- name = pkg.name,
8
- version = pkg.version,
7
+ name = pkg.name || 'App',
8
+ version = pkg.version || '1.0.0',
9
9
  sign = false,
10
10
  identity = 'Apple Development',
11
11
  installerIdentity = identity,
@@ -1,4 +1,5 @@
1
1
  const path = require('path')
2
+ const fs = require('../../fs')
2
3
  const run = require('../../run')
3
4
 
4
5
  module.exports = async function sign(resource, opts = {}) {
@@ -11,17 +12,65 @@ module.exports = async function sign(resource, opts = {}) {
11
12
  hardenedRuntime = false
12
13
  } = opts
13
14
 
14
- if (sign) {
15
- const args = ['--timestamp', '--force', '--sign', applicationIdentity]
15
+ const temp = []
16
16
 
17
- if (keychain) args.push('--keychain', keychain)
18
- if (entitlements) args.push('--entitlements', path.resolve(entitlements))
19
- if (hardenedRuntime) args.push('--options', 'runtime')
17
+ try {
18
+ if (sign) {
19
+ const args = ['--timestamp', '--force', '--sign', applicationIdentity]
20
20
 
21
- args.push(resource)
21
+ if (keychain) args.push('--keychain', keychain)
22
22
 
23
- await run('codesign', args)
24
- } else {
25
- await run('codesign', ['--timestamp=none', '--force', '--sign', '-', resource])
23
+ if (entitlements) args.push('--entitlements', path.resolve(entitlements))
24
+ else {
25
+ const out = await fs.tempDir()
26
+
27
+ temp.push(out)
28
+
29
+ const entitlements = path.join(out, 'Entitlements.plist')
30
+
31
+ await fs.writeFile(entitlements, createEntitlements(opts))
32
+
33
+ args.push('--entitlements', entitlements)
34
+ }
35
+
36
+ if (hardenedRuntime) args.push('--options', 'runtime')
37
+
38
+ args.push(resource)
39
+
40
+ await run('codesign', args)
41
+ } else {
42
+ await run('codesign', ['--timestamp=none', '--force', '--sign', '-', resource])
43
+ }
44
+ } finally {
45
+ for (const dir of temp) await fs.rm(dir)
26
46
  }
27
47
  }
48
+
49
+ function createEntitlements(opts = {}) {
50
+ const { hardenedRuntime = false } = opts
51
+
52
+ const entitlements = []
53
+
54
+ if (hardenedRuntime) {
55
+ entitlements.push(
56
+ 'com.apple.security.cs.allow-jit',
57
+ 'com.apple.security.cs.allow-unsigned-executable-memory'
58
+ )
59
+ }
60
+
61
+ return `\
62
+ <?xml version="1.0" encoding="UTF-8"?>
63
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
64
+ <plist version="1.0">
65
+ <dict>${entitlements
66
+ .map(
67
+ (entitlement) => `
68
+ <key>${entitlement}</key>
69
+ <true/>
70
+ `
71
+ )
72
+ .join('\n')}
73
+ </dict>
74
+ </plist>
75
+ `
76
+ }
@@ -1,11 +1,12 @@
1
1
  const path = require('path')
2
2
  const fs = require('../fs')
3
3
  const createApp = require('./apple/create-app')
4
+ const createExecutable = require('./apple/create-executable')
4
5
  const createPackage = require('./apple/create-package')
5
6
  const createPackageComponent = require('./apple/create-package-component')
6
7
 
7
8
  module.exports = async function* apple(base, pkg, bundle, opts = {}) {
8
- const { hosts = [], package = false, out = '.' } = opts
9
+ const { hosts = [], standalone = false, package = false, out = '.' } = opts
9
10
 
10
11
  const archs = new Map([
11
12
  ['macos', []],
@@ -55,16 +56,28 @@ module.exports = async function* apple(base, pkg, bundle, opts = {}) {
55
56
 
56
57
  yield* createApp(base, pkg, bundle, hosts, path.join(root, 'Applications'), opts)
57
58
  } else {
58
- const app = yield* createApp(
59
- base,
60
- pkg,
61
- bundle,
62
- hosts,
63
- archs.size === 1 ? path.resolve(out) : path.resolve(out, os),
64
- opts
65
- )
66
-
67
- result.push(app)
59
+ if (standalone) {
60
+ result.push(
61
+ yield* createExecutable(
62
+ pkg,
63
+ bundle,
64
+ hosts,
65
+ archs.size === 1 ? path.resolve(out) : path.resolve(out, os),
66
+ opts
67
+ )
68
+ )
69
+ } else {
70
+ result.push(
71
+ yield* createApp(
72
+ base,
73
+ pkg,
74
+ bundle,
75
+ hosts,
76
+ archs.size === 1 ? path.resolve(out) : path.resolve(out, os),
77
+ opts
78
+ )
79
+ )
80
+ }
68
81
 
69
82
  continue
70
83
  }
@@ -3,10 +3,11 @@ const link = require('bare-link')
3
3
  const unpack = require('bare-unpack')
4
4
  const fs = require('../../fs')
5
5
  const prebuilds = require('../../prebuilds')
6
+ const { linux } = require('../../assets')
6
7
 
7
8
  // https://docs.appimage.org/packaging-guide/manual.html#creating-an-appdir-manually
8
9
  module.exports = async function* createAppDir(base, pkg, bundle, host, out, opts = {}) {
9
- const { name = pkg.name, icon } = opts
10
+ const { name = pkg.name || 'App', icon = linux.icon } = opts
10
11
 
11
12
  const app = path.resolve(out, name + '.AppDir')
12
13
 
@@ -4,7 +4,7 @@ const path = require('path')
4
4
  module.exports = async function* createAppImage(pkg, appDir, out, opts = {}) {
5
5
  const createAppImage = require('bare-app-image') // Optional
6
6
 
7
- const { name = pkg.name, sign = false, key } = opts
7
+ const { name = pkg.name || 'App', sign = false, key } = opts
8
8
 
9
9
  const appImage = path.resolve(out, name + '.AppImage')
10
10
 
@@ -0,0 +1,50 @@
1
+ const path = require('path')
2
+ const { ELF } = require('bare-lief')
3
+ const fs = require('../../fs')
4
+ const prebuilds = require('../../prebuilds')
5
+
6
+ module.exports = async function* createExecutable(pkg, bundle, host, out, opts = {}) {
7
+ const { name = pkg.name || 'App' } = opts
8
+
9
+ await fs.makeDir(out)
10
+
11
+ const binary = new ELF.Binary(await fs.readFile(prebuilds[host]()))
12
+
13
+ let section = new ELF.Section('.bare')
14
+
15
+ section.flags = ELF.Section.FLAGS.ALLOC
16
+ section.content = bundle.toBuffer()
17
+
18
+ section = binary.addSection(section)
19
+
20
+ const sectionIndex = binary.getSectionIndex('.bare')
21
+
22
+ const begin = new ELF.Symbol('__bare_bundle_begin')
23
+
24
+ begin.value = section.virtualAddress
25
+ begin.binding = ELF.Symbol.BINDING.GLOBAL
26
+ begin.sectionIndex = sectionIndex
27
+
28
+ const end = new ELF.Symbol('__bare_bundle_end')
29
+
30
+ end.value = section.virtualAddress + section.size
31
+ end.binding = ELF.Symbol.BINDING.GLOBAL
32
+ end.sectionIndex = sectionIndex
33
+
34
+ binary.addDynamicSymbol(begin)
35
+ binary.addDynamicSymbol(end)
36
+
37
+ const executable = path.join(out, toIdentifier(name))
38
+ binary.toDisk(executable)
39
+ await fs.chmod(executable, 0o755)
40
+ yield executable
41
+
42
+ return executable
43
+ }
44
+
45
+ function toIdentifier(input) {
46
+ return input
47
+ .replace(/[^a-z0-9]+/gi, '-')
48
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
49
+ .toLowerCase()
50
+ }
@@ -2,9 +2,10 @@ const path = require('path')
2
2
  const fs = require('../fs')
3
3
  const createAppDir = require('./linux/create-app-dir')
4
4
  const createAppImage = require('./linux/create-app-image')
5
+ const createExecutable = require('./linux/create-executable')
5
6
 
6
7
  module.exports = exports = async function* linux(base, pkg, bundle, opts = {}) {
7
- const { hosts = [], package = false, out = '.' } = opts
8
+ const { hosts = [], standalone = false, package = false, out = '.' } = opts
8
9
 
9
10
  const archs = new Map()
10
11
 
@@ -39,16 +40,28 @@ module.exports = exports = async function* linux(base, pkg, bundle, opts = {}) {
39
40
 
40
41
  appDir = yield* createAppDir(base, pkg, bundle, host, out, opts)
41
42
  } else {
42
- appDir = yield* createAppDir(
43
- base,
44
- pkg,
45
- bundle,
46
- host,
47
- archs.size === 1 ? path.resolve(out) : path.resolve(out, arch),
48
- opts
49
- )
50
-
51
- result.push(appDir)
43
+ if (standalone) {
44
+ result.push(
45
+ yield* createExecutable(
46
+ pkg,
47
+ bundle,
48
+ host,
49
+ archs.size === 1 ? path.resolve(out) : path.resolve(out, arch),
50
+ opts
51
+ )
52
+ )
53
+ } else {
54
+ result.push(
55
+ yield* createAppDir(
56
+ base,
57
+ pkg,
58
+ bundle,
59
+ host,
60
+ archs.size === 1 ? path.resolve(out) : path.resolve(out, arch),
61
+ opts
62
+ )
63
+ )
64
+ }
52
65
 
53
66
  continue
54
67
  }
@@ -0,0 +1,50 @@
1
+ const path = require('path')
2
+ const { PE } = require('bare-lief')
3
+ const fs = require('../../fs')
4
+ const prebuilds = require('../../prebuilds')
5
+ const sign = require('./sign')
6
+
7
+ module.exports = async function* createExecutable(pkg, bundle, host, out, opts = {}) {
8
+ const { name = pkg.name || 'App' } = opts
9
+
10
+ await fs.makeDir(out)
11
+
12
+ const temp = await fs.tempDir()
13
+ try {
14
+ for (const addon of bundle.addons) {
15
+ const target = path.join(temp, addon)
16
+ await fs.makeDir(path.dirname(target))
17
+ await fs.writeFile(target, bundle.read(addon))
18
+ await sign(target, opts)
19
+
20
+ bundle.write(addon, await fs.readFile(target))
21
+ }
22
+ } finally {
23
+ await fs.rm(temp)
24
+ }
25
+
26
+ const binary = new PE.Binary(await fs.readFile(prebuilds[host]()))
27
+
28
+ binary.optionalHeader.subsystem = PE.OptionalHeader.SUBSYSTEM.WINDOWS_CUI
29
+
30
+ let section = new PE.Section('.bare')
31
+
32
+ section.characteristics =
33
+ PE.Section.CHARACTERISTICS.MEM_READ | PE.Section.CHARACTERISTICS.CNT_INITIALIZED_DATA
34
+ section.content = bundle.toBuffer()
35
+
36
+ binary.addSection(section)
37
+
38
+ const executable = path.join(out, toIdentifier(name) + '.exe')
39
+ binary.toDisk(executable)
40
+ yield executable
41
+
42
+ return executable
43
+ }
44
+
45
+ function toIdentifier(input) {
46
+ return input
47
+ .replace(/[^a-z0-9]+/gi, '-')
48
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
49
+ .toLowerCase()
50
+ }