bare-build 0.2.7 → 0.2.8

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.
package/CMakeLists.txt CHANGED
@@ -55,7 +55,6 @@ target_link_libraries(
55
55
  PUBLIC
56
56
  $<LINK_LIBRARY:WHOLE_ARCHIVE,bare_static>
57
57
  PRIVATE
58
- log_static
59
58
  rlimit_static
60
59
  path_static
61
60
  )
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # bare-build
2
2
 
3
- Application builder for Bare.
3
+ Application builder for Bare that allows developers to package their JavaScript code as either native application bundles or standalone executables for both desktop and mobile.
4
4
 
5
5
  ```
6
6
  npm i [-g] bare-build
@@ -29,6 +29,16 @@ bare-build \
29
29
  app.js
30
30
  ```
31
31
 
32
+ ## Formats
33
+
34
+ | Platform | Unpackaged | `--package` | `--standalone` |
35
+ | :------- | :------------------------- | :---------- | :------------------------------------------------------------ |
36
+ | Linux | `.AppDir`, Snap compatible | `.AppImage` | ELF executable with self-extracting `.so` libraries |
37
+ | Android | `.apk` | `.aab` | ELF executable with self-extracting `.so` libraries |
38
+ | macOS | `.app` | `.pkg` | Mach-O executable with self-extracting `.framework` libraries |
39
+ | iOS | `.app` | `.pkg` | Mach-O executable with self-extracting `.framework` libraries |
40
+ | Windows | Plain directory | `.msix` | PE executable with self-extracting `.dll` libraries |
41
+
32
42
  ## API
33
43
 
34
44
  #### `for await (const resource of build(entry[, preflight][, options]))`
@@ -0,0 +1,13 @@
1
+ const path = require('path')
2
+
3
+ module.exports = async function* createAPK(aab, out, opts = {}) {
4
+ const { createAPK } = require('bare-apk') // Optional
5
+
6
+ const { name } = opts
7
+
8
+ const apk = path.join(out, name + '.apk')
9
+ await createAPK(aab, apk, opts)
10
+ yield apk
11
+
12
+ return apk
13
+ }
@@ -0,0 +1,130 @@
1
+ const path = require('path')
2
+ const link = require('bare-link')
3
+ const fs = require('../../fs')
4
+ const prebuilds = require('../../prebuilds')
5
+
6
+ module.exports = async function* createAppBundle(base, bundle, hosts, out, opts = {}) {
7
+ const { createAppBundle, constants } = require('bare-apk') // Optional
8
+
9
+ const {
10
+ name,
11
+ identifier = toIdentifier(name),
12
+ minimumSDK = constants.DEFAULT_MINIMUM_SDK,
13
+ targetSDK = constants.DEFAULT_TARGET_SDK,
14
+ runtime = { prebuilds }
15
+ } = opts
16
+
17
+ const archs = new Map()
18
+
19
+ for (const host of hosts) {
20
+ let arch
21
+
22
+ switch (host) {
23
+ case 'android-arm64':
24
+ arch = 'arm64-v8a'
25
+ break
26
+ case 'android-arm':
27
+ arch = 'armeabi-v7a'
28
+ break
29
+ case 'android-ia32':
30
+ arch = 'x86'
31
+ break
32
+ case 'android-x64':
33
+ arch = 'x86_64'
34
+ break
35
+ default:
36
+ throw new Error(`Unknown host '${host}'`)
37
+ }
38
+
39
+ archs.set(arch, host)
40
+ }
41
+
42
+ const temp = []
43
+
44
+ try {
45
+ const build = await fs.tempDir()
46
+
47
+ temp.push(build)
48
+
49
+ const lib = path.join(build, 'lib')
50
+ await fs.makeDir(lib)
51
+
52
+ const assets = path.join(build, 'assets')
53
+ await fs.makeDir(assets)
54
+
55
+ const classes = path.join(build, 'dex')
56
+ await fs.makeDir(classes)
57
+
58
+ yield* link(base, { ...opts, hosts, out: lib })
59
+
60
+ for (const [arch, host] of archs) {
61
+ const prebuild = runtime.prebuilds[host]()
62
+
63
+ try {
64
+ for await (const file of await fs.openDir(
65
+ path.resolve(prebuild, '..', path.basename(prebuild, '.so').replace(/^lib/, ''))
66
+ )) {
67
+ switch (path.extname(file.name)) {
68
+ case '.so': {
69
+ const so = path.join(lib, arch, file.name)
70
+ await fs.copyFile(path.join(file.parentPath, file.name), so)
71
+ yield so
72
+ break
73
+ }
74
+ case '.dex': {
75
+ const dex = path.join(classes, file.name)
76
+ await fs.copyFile(path.join(file.parentPath, file.name), dex)
77
+ yield dex
78
+ break
79
+ }
80
+ }
81
+ }
82
+ } catch (err) {
83
+ if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') throw err
84
+ }
85
+
86
+ const so = path.join(lib, arch, path.basename(prebuild))
87
+ await fs.copyFile(prebuild, so)
88
+ yield so
89
+ }
90
+
91
+ const appBundle = path.join(assets, 'app.bundle')
92
+ await fs.writeFile(appBundle, bundle.toBuffer())
93
+ yield appBundle
94
+
95
+ const appManifest = path.join(build, 'AndroidManifest.xml')
96
+ await fs.writeFile(appManifest, createAndroidManifest(name, identifier, minimumSDK, targetSDK))
97
+ yield appManifest
98
+
99
+ const aab = path.join(out, name + '.aab')
100
+ await createAppBundle(appManifest, aab, { include: [lib, assets, classes] })
101
+ yield aab
102
+
103
+ return aab
104
+ } finally {
105
+ for (const dir of temp) await fs.rm(dir)
106
+ }
107
+ }
108
+
109
+ function createAndroidManifest(name, identifier, minimumSDK, targetSDK) {
110
+ return `\
111
+ <?xml version="1.0" encoding="utf-8"?>
112
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="${identifier}">
113
+ <uses-sdk android:minSdkVersion="${minimumSDK}" android:targetSdkVersion="${targetSDK}" />
114
+ <uses-permission android:name="android.permission.INTERNET" />
115
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
116
+ <application android:label="${name}" android:hasCode="true" android:usesCleartextTraffic="true">
117
+ <activity android:name="to.holepunch.bare.Activity" android:exported="true">
118
+ <intent-filter>
119
+ <action android:name="android.intent.action.MAIN" />
120
+ <category android:name="android.intent.category.LAUNCHER" />
121
+ </intent-filter>
122
+ </activity>
123
+ </application>
124
+ </manifest>
125
+ `
126
+ }
127
+
128
+ function toIdentifier(input) {
129
+ return input.replace(/[^a-z0-9_]+/gi, '_')
130
+ }
@@ -1,52 +1,56 @@
1
1
  const path = require('path')
2
- const link = require('bare-link')
3
2
  const fs = require('../fs')
4
- const prebuilds = require('../prebuilds')
3
+ const createAppBundle = require('./android/create-app-bundle')
4
+ const createAPK = require('./android/create-apk')
5
+ const createExecutable = require('./linux/create-executable')
5
6
 
6
7
  module.exports = async function* android(base, bundle, preflight, opts = {}) {
7
- const { createAppBundle, createAPK, constants } = require('bare-apk') // Optional
8
-
9
- const {
10
- hosts = [],
11
- name,
12
- identifier = toIdentifier(name),
13
- minimumSDK = constants.DEFAULT_MINIMUM_SDK,
14
- targetSDK = constants.DEFAULT_TARGET_SDK,
15
- runtime = { prebuilds },
16
- standalone = false,
17
- package = false,
18
- out = '.'
19
- } = opts
8
+ const { hosts = [], standalone = false, package = false, out = '.' } = opts
20
9
 
21
10
  if (standalone) {
22
- throw new Error('Standalone mode is not supported for Android')
23
- }
11
+ const archs = new Map()
12
+
13
+ for (const host of hosts) {
14
+ let arch
15
+
16
+ switch (host) {
17
+ case 'android-arm64':
18
+ arch = 'arm64-v8a'
19
+ break
20
+ case 'android-arm':
21
+ arch = 'armeabi-v7a'
22
+ break
23
+ case 'android-ia32':
24
+ arch = 'x86'
25
+ break
26
+ case 'android-x64':
27
+ arch = 'x86_64'
28
+ break
29
+ default:
30
+ throw new Error(`Unknown host '${host}'`)
31
+ }
24
32
 
25
- const archs = new Map()
33
+ archs.set(arch, host)
34
+ }
26
35
 
27
- for (const host of hosts) {
28
- let arch
36
+ const result = []
29
37
 
30
- switch (host) {
31
- case 'android-arm64':
32
- arch = 'arm64-v8a'
33
- break
34
- case 'android-arm':
35
- arch = 'armeabi-v7a'
36
- break
37
- case 'android-ia32':
38
- arch = 'x86'
39
- break
40
- case 'android-x64':
41
- arch = 'x86_64'
42
- break
43
- default:
44
- throw new Error(`Unknown host '${host}'`)
38
+ for (const [arch, host] of archs) {
39
+ result.push(
40
+ yield* createExecutable(
41
+ bundle,
42
+ host,
43
+ archs.size === 1 ? path.resolve(out) : path.resolve(out, arch),
44
+ opts
45
+ )
46
+ )
45
47
  }
46
48
 
47
- archs.set(arch, host)
49
+ return result
48
50
  }
49
51
 
52
+ if (package) return [yield* createAppBundle(base, bundle, hosts, out, opts)]
53
+
50
54
  const temp = []
51
55
 
52
56
  try {
@@ -54,91 +58,10 @@ module.exports = async function* android(base, bundle, preflight, opts = {}) {
54
58
 
55
59
  temp.push(build)
56
60
 
57
- const lib = path.join(build, 'lib')
58
- await fs.makeDir(lib)
59
-
60
- const assets = path.join(build, 'assets')
61
- await fs.makeDir(assets)
62
-
63
- const classes = path.join(build, 'dex')
64
- await fs.makeDir(classes)
65
-
66
- yield* link(base, { ...opts, hosts, out: lib })
67
-
68
- for (const [arch, host] of archs) {
69
- const prebuild = runtime.prebuilds[host]()
70
-
71
- try {
72
- for await (const file of await fs.openDir(
73
- path.resolve(prebuild, '..', path.basename(prebuild, '.so').replace(/^lib/, ''))
74
- )) {
75
- switch (path.extname(file.name)) {
76
- case '.so': {
77
- const so = path.join(lib, arch, file.name)
78
- await fs.copyFile(path.join(file.parentPath, file.name), so)
79
- yield so
80
- break
81
- }
82
- case '.dex': {
83
- const dex = path.join(classes, file.name)
84
- await fs.copyFile(path.join(file.parentPath, file.name), dex)
85
- yield dex
86
- break
87
- }
88
- }
89
- }
90
- } catch (err) {
91
- if (err.code !== 'ENOENT') throw err
92
- }
93
-
94
- const so = path.join(lib, arch, path.basename(prebuild))
95
- await fs.copyFile(prebuild, so)
96
- yield so
97
- }
98
-
99
- const appBundle = path.join(assets, 'app.bundle')
100
- await fs.writeFile(appBundle, bundle.toBuffer())
101
- yield appBundle
102
-
103
- const appManifest = path.join(build, 'AndroidManifest.xml')
104
- await fs.writeFile(appManifest, createAndroidManifest(name, identifier, minimumSDK, targetSDK))
105
- yield appManifest
106
-
107
- const aab = path.join(package ? out : build, name + '.aab')
108
- await createAppBundle(appManifest, aab, { include: [lib, assets, classes] })
109
- yield aab
61
+ const aab = yield* createAppBundle(base, bundle, hosts, build, opts)
110
62
 
111
- if (package) return [aab]
112
-
113
- const apk = path.join(out, name + '.apk')
114
- await createAPK(aab, apk, opts)
115
- yield apk
116
-
117
- return [apk]
63
+ return [yield* createAPK(aab, out, opts)]
118
64
  } finally {
119
65
  for (const dir of temp) await fs.rm(dir)
120
66
  }
121
67
  }
122
-
123
- function createAndroidManifest(name, identifier, minimumSDK, targetSDK) {
124
- return `\
125
- <?xml version="1.0" encoding="utf-8"?>
126
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="${identifier}">
127
- <uses-sdk android:minSdkVersion="${minimumSDK}" android:targetSdkVersion="${targetSDK}" />
128
- <uses-permission android:name="android.permission.INTERNET" />
129
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
130
- <application android:label="${name}" android:hasCode="true" android:usesCleartextTraffic="true">
131
- <activity android:name="to.holepunch.bare.Activity" android:exported="true">
132
- <intent-filter>
133
- <action android:name="android.intent.action.MAIN" />
134
- <category android:name="android.intent.category.LAUNCHER" />
135
- </intent-filter>
136
- </activity>
137
- </application>
138
- </manifest>
139
- `
140
- }
141
-
142
- function toIdentifier(input) {
143
- return input.replace(/[^a-z0-9_]+/gi, '_')
144
- }
@@ -10,30 +10,26 @@ module.exports = async function* createExecutable(bundle, host, out, opts = {})
10
10
 
11
11
  const binary = new ELF.Binary(await fs.readFile(runtime.prebuilds[host]()))
12
12
 
13
- let section = new ELF.Section('.bare')
13
+ let segment = new ELF.Segment()
14
14
 
15
- section.flags = ELF.Section.FLAGS.ALLOC
16
- section.content = bundle.toBuffer()
15
+ segment.type = ELF.Segment.TYPE.LOAD
16
+ segment.flags = ELF.Segment.FLAGS.R
17
+ segment.content = bundle.toBuffer()
17
18
 
18
- section = binary.addSection(section)
19
+ segment = binary.addSegment(segment)
19
20
 
20
- const sectionIndex = binary.getSectionIndex('.bare')
21
+ const sectionIndex = binary.getSectionIndex('.dynsym')
21
22
 
22
- const begin = new ELF.Symbol('__bare_bundle_begin')
23
+ const begin = binary.getDynamicSymbol('__bare_bundle_begin')
23
24
 
24
- begin.value = section.virtualAddress
25
- begin.binding = ELF.Symbol.BINDING.GLOBAL
25
+ begin.value = segment.virtualAddress
26
26
  begin.sectionIndex = sectionIndex
27
27
 
28
- const end = new ELF.Symbol('__bare_bundle_end')
28
+ const end = binary.getDynamicSymbol('__bare_bundle_end')
29
29
 
30
- end.value = section.virtualAddress + section.size
31
- end.binding = ELF.Symbol.BINDING.GLOBAL
30
+ end.value = segment.virtualAddress + segment.virtualSize
32
31
  end.sectionIndex = sectionIndex
33
32
 
34
- binary.addDynamicSymbol(begin)
35
- binary.addDynamicSymbol(end)
36
-
37
33
  const executable = path.join(out, toIdentifier(name))
38
34
  binary.toDisk(executable)
39
35
  await fs.chmod(executable, 0o755)
@@ -48,7 +48,7 @@ module.exports = async function* createMSIXContentDirectory(
48
48
  }
49
49
  }
50
50
  } catch (err) {
51
- if (err.code !== 'ENOENT') throw err
51
+ if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') throw err
52
52
  }
53
53
 
54
54
  const binary = new PE.Binary(await fs.readFile(prebuild))
package/lib/prebuilds.js CHANGED
@@ -1,13 +1,29 @@
1
1
  require.asset = require('require-asset')
2
2
 
3
- exports['darwin-x64'] = () => {
4
- return require.asset('../prebuilds/darwin-x64/bare', __filename)
3
+ exports['android-arm'] = () => {
4
+ return require.asset('../prebuilds/android-arm/bare', __filename)
5
+ }
6
+
7
+ exports['android-arm64'] = () => {
8
+ return require.asset('../prebuilds/android-arm64/bare', __filename)
9
+ }
10
+
11
+ exports['android-ia32'] = () => {
12
+ return require.asset('../prebuilds/android-ia32/bare', __filename)
13
+ }
14
+
15
+ exports['android-x64'] = () => {
16
+ return require.asset('../prebuilds/android-x64/bare', __filename)
5
17
  }
6
18
 
7
19
  exports['darwin-arm64'] = () => {
8
20
  return require.asset('../prebuilds/darwin-arm64/bare', __filename)
9
21
  }
10
22
 
23
+ exports['darwin-x64'] = () => {
24
+ return require.asset('../prebuilds/darwin-x64/bare', __filename)
25
+ }
26
+
11
27
  exports['ios-arm64'] = () => {
12
28
  return require.asset('../prebuilds/ios-arm64/bare', __filename)
13
29
  }
@@ -20,18 +36,18 @@ exports['ios-x64-simulator'] = () => {
20
36
  return require.asset('../prebuilds/ios-x64-simulator/bare', __filename)
21
37
  }
22
38
 
23
- exports['linux-x64'] = () => {
24
- return require.asset('../prebuilds/linux-x64/bare', __filename)
25
- }
26
-
27
39
  exports['linux-arm64'] = () => {
28
40
  return require.asset('../prebuilds/linux-arm64/bare', __filename)
29
41
  }
30
42
 
31
- exports['win32-x64'] = () => {
32
- return require.asset('../prebuilds/win32-x64/bare.exe', __filename)
43
+ exports['linux-x64'] = () => {
44
+ return require.asset('../prebuilds/linux-x64/bare', __filename)
33
45
  }
34
46
 
35
47
  exports['win32-arm64'] = () => {
36
48
  return require.asset('../prebuilds/win32-arm64/bare.exe', __filename)
37
49
  }
50
+
51
+ exports['win32-x64'] = () => {
52
+ return require.asset('../prebuilds/win32-x64/bare.exe', __filename)
53
+ }
package/lib/runtime.c CHANGED
@@ -1,7 +1,6 @@
1
1
  #include <assert.h>
2
2
  #include <bare.h>
3
3
  #include <js.h>
4
- #include <log.h>
5
4
  #include <path.h>
6
5
  #include <rlimit.h>
7
6
  #include <signal.h>
@@ -67,9 +66,6 @@ main(int argc, char *argv[]) {
67
66
  signal(SIGPIPE, SIG_IGN);
68
67
  #endif
69
68
 
70
- err = log_open("bare", 0);
71
- assert(err == 0);
72
-
73
69
  err = rlimit_set(rlimit_open_files, rlimit_infer);
74
70
  assert(err == 0);
75
71
 
@@ -137,9 +133,11 @@ main(int argc, char *argv[]) {
137
133
  err = uv_exepath(bin, &len);
138
134
  assert(err == 0);
139
135
 
136
+ #if defined(BARE_PLATFORM_LINUX)
140
137
  size_t dir;
141
138
  err = path_dirname(bin, &dir, path_behavior_system);
142
139
  assert(err == 0);
140
+ #endif
143
141
 
144
142
  char preflight[4096];
145
143
  len = 4096;
@@ -147,7 +145,7 @@ main(int argc, char *argv[]) {
147
145
  err = path_join(
148
146
  #if defined(BARE_PLATFORM_DARWIN) || defined(BARE_PLATFORM_WIN32)
149
147
  (const char *[]) {bin, "..", "..", "Resources", "preflight.bundle", NULL},
150
- #elif defined(BARE_PLATFORM_IOS)
148
+ #elif defined(BARE_PLATFORM_IOS) || defined(BARE_PLATFORM_ANDROID)
151
149
  (const char *[]) {bin, "..", "preflight.bundle", NULL},
152
150
  #elif defined(BARE_PLATFORM_LINUX)
153
151
  (const char *[]) {bin, "..", "..", "share", &bin[dir], "preflight.bundle", NULL},
@@ -184,7 +182,7 @@ main(int argc, char *argv[]) {
184
182
  err = path_join(
185
183
  #if defined(BARE_PLATFORM_DARWIN) || defined(BARE_PLATFORM_WIN32)
186
184
  (const char *[]) {bin, "..", "..", "Resources", "app.bundle", NULL},
187
- #elif defined(BARE_PLATFORM_IOS)
185
+ #elif defined(BARE_PLATFORM_IOS) || defined(BARE_PLATFORM_ANDROID)
188
186
  (const char *[]) {bin, "..", "app.bundle", NULL},
189
187
  #elif defined(BARE_PLATFORM_LINUX)
190
188
  (const char *[]) {bin, "..", "..", "share", &bin[dir], "app.bundle", NULL},
@@ -217,8 +215,5 @@ main(int argc, char *argv[]) {
217
215
 
218
216
  uv_thread_join(&thread);
219
217
 
220
- err = log_close();
221
- assert(err == 0);
222
-
223
218
  return exit_code;
224
219
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-build",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Application builder for Bare",
5
5
  "exports": {
6
6
  "./package": "./package.json",
@@ -54,7 +54,7 @@
54
54
  "dependencies": {
55
55
  "bare-bundle-id": "^1.0.2",
56
56
  "bare-fs": "^4.5.1",
57
- "bare-lief": "^0.1.1",
57
+ "bare-lief": "^0.1.3",
58
58
  "bare-link": "^2.1.2",
59
59
  "bare-module-resolve": "^1.12.0",
60
60
  "bare-module-traverse": "^1.8.1",
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file