reflex-packager 0.1.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.
- checksums.yaml +7 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- data/.github/workflows/release-gem.yml +51 -0
- data/.github/workflows/tag.yml +35 -0
- data/.github/workflows/test.yml +37 -0
- data/.github/workflows/utils.rb +127 -0
- data/.gitignore +6 -0
- data/CONTRIBUTING.md +7 -0
- data/ChangeLog.md +16 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +166 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/bin/reflex +22 -0
- data/lib/reflex/packager/cli.rb +114 -0
- data/lib/reflex/packager/config.rb +183 -0
- data/lib/reflex/packager/extension.rb +32 -0
- data/lib/reflex/packager/macos.rb +190 -0
- data/lib/reflex/packager/platform.rb +73 -0
- data/lib/reflex/packager/profile.rb +45 -0
- data/lib/reflex/packager/templates/macos/Podfile.erb +30 -0
- data/lib/reflex/packager/templates/macos/main.mm.erb +43 -0
- data/lib/reflex/packager/templates/macos/project.yml.erb +40 -0
- data/lib/reflex/packager.rb +12 -0
- data/reflex-packager.gemspec +37 -0
- data/test/helper.rb +28 -0
- data/test/test_packager_cli.rb +80 -0
- data/test/test_packager_config.rb +240 -0
- data/test/test_packager_macos.rb +225 -0
- metadata +132 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f5b9334c8f2959003958be6fed84204918e8e8e30c1f7354f5e01834aeb0d985
|
|
4
|
+
data.tar.gz: d4a4efe7e3ea26f0de8958c0e1c39e9a4afa4909d6d8b72fcf46059a3b616f21
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 963784c653d3af8eb62017ab139263a0ca2139cf9004f9756f6815bc8abc9ae5d7feb76a653ec8aa38b0c642f1f35e1a2fa08d6222878817a6dda0c86f3213b5
|
|
7
|
+
data.tar.gz: 2f5c2559229709a09ac563c4f709daf59b7734b97018110d2d72ce92ebb910381eb201468c747a28953b1cbbf6404e8cdc2aaa1ec1c0484a7a7bd5811695323d
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## Pull Requests Not Accepted
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
However, this repository does not accept pull requests directly.
|
|
5
|
+
|
|
6
|
+
### Where to Contribute?
|
|
7
|
+
|
|
8
|
+
Please submit your changes to the [xord/all](https://github.com/xord/all) monorepo, which serves as the primary repository for all our main libraries.
|
|
9
|
+
|
|
10
|
+
For more details, please refer to our [contribution guidelines](../CONTRIBUTING.md).
|
|
11
|
+
|
|
12
|
+
Thanks for your understanding!
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Release Gem
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ['v[0-9]*']
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
release:
|
|
12
|
+
runs-on: macos-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: ruby 3.2
|
|
16
|
+
uses: ruby/setup-ruby@v1
|
|
17
|
+
with:
|
|
18
|
+
ruby-version: 3.2
|
|
19
|
+
|
|
20
|
+
- name: checkout
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: setup gems
|
|
24
|
+
run: bundle install
|
|
25
|
+
|
|
26
|
+
- name: setup dependencies
|
|
27
|
+
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies'"
|
|
28
|
+
|
|
29
|
+
- name: test
|
|
30
|
+
run: bundle exec rake packages test
|
|
31
|
+
|
|
32
|
+
- name: create gem
|
|
33
|
+
id: gem
|
|
34
|
+
run: |
|
|
35
|
+
bundle exec rake gem
|
|
36
|
+
echo path=$(ruby -e 'print Dir.glob("*.gem").first') >> $GITHUB_OUTPUT
|
|
37
|
+
|
|
38
|
+
- name: create github release
|
|
39
|
+
env:
|
|
40
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
41
|
+
run: ruby -I.github/workflows -rutils -e 'release(*ARGV)' ./${{ steps.gem.outputs.path }}
|
|
42
|
+
|
|
43
|
+
- name: upload to rubygems
|
|
44
|
+
env:
|
|
45
|
+
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }}
|
|
46
|
+
run: |
|
|
47
|
+
mkdir -p $HOME/.gem
|
|
48
|
+
touch $HOME/.gem/credentials
|
|
49
|
+
chmod 0600 $HOME/.gem/credentials
|
|
50
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
|
51
|
+
bundle exec rake upload
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Tag
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
tag:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
|
|
11
|
+
steps:
|
|
12
|
+
- name: ruby 3.2
|
|
13
|
+
uses: ruby/setup-ruby@v1
|
|
14
|
+
with:
|
|
15
|
+
ruby-version: 3.2
|
|
16
|
+
|
|
17
|
+
- name: checkout
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
token: ${{ secrets.PAT }}
|
|
22
|
+
|
|
23
|
+
- name: setup dependencies
|
|
24
|
+
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies only: :xot'"
|
|
25
|
+
|
|
26
|
+
- name: setup user name and email
|
|
27
|
+
run: |
|
|
28
|
+
git config --global user.email "xordog@gmail.com"
|
|
29
|
+
git config --global user.name "xord"
|
|
30
|
+
|
|
31
|
+
- name: tag versions
|
|
32
|
+
run: "ruby -I.github/workflows -rutils -e 'tag_versions'"
|
|
33
|
+
|
|
34
|
+
- name: push tags
|
|
35
|
+
run: git push origin --tags
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: macos-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- name: ruby 3.2
|
|
14
|
+
uses: ruby/setup-ruby@v1
|
|
15
|
+
with:
|
|
16
|
+
ruby-version: 3.2
|
|
17
|
+
|
|
18
|
+
- name: checkout
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: setup gems
|
|
22
|
+
run: bundle install
|
|
23
|
+
|
|
24
|
+
- name: setup dependencies
|
|
25
|
+
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies'"
|
|
26
|
+
|
|
27
|
+
- name: packages
|
|
28
|
+
run: bundle exec rake verbose packages
|
|
29
|
+
|
|
30
|
+
- name: lib
|
|
31
|
+
run: bundle exec rake verbose lib
|
|
32
|
+
|
|
33
|
+
- name: ext
|
|
34
|
+
run: bundle exec rake verbose ext
|
|
35
|
+
|
|
36
|
+
- name: test
|
|
37
|
+
run: bundle exec rake verbose test
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require 'shellwords'
|
|
2
|
+
|
|
3
|
+
ALL_REPO = 'xord/all'
|
|
4
|
+
ALL_DIR = '../all'
|
|
5
|
+
ALL_FETCH_DEPTH = 100
|
|
6
|
+
|
|
7
|
+
RENAMES = {reflex: 'reflexion'}
|
|
8
|
+
|
|
9
|
+
def sh(cmd)
|
|
10
|
+
puts cmd
|
|
11
|
+
system cmd
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def setup_dependencies(only: nil)
|
|
15
|
+
gemspec_path = `git ls-files`.lines(chomp: true).find {|l| l =~ /\.gemspec$/}
|
|
16
|
+
return unless gemspec_path
|
|
17
|
+
|
|
18
|
+
gemspec = File.read gemspec_path
|
|
19
|
+
name = File.basename gemspec_path, '.gemspec'
|
|
20
|
+
|
|
21
|
+
exts = File.readlines('Rakefile')
|
|
22
|
+
.map {|l| l[%r|^\s*require\W+([\w\-\_]+)/extension\W+$|, 1]}
|
|
23
|
+
.compact
|
|
24
|
+
.reject {|ext| ext == name}
|
|
25
|
+
exts = exts & [only].flatten.map(&:to_s) if only
|
|
26
|
+
return if exts.empty?
|
|
27
|
+
|
|
28
|
+
unless setup_dependencies_via_monorepo(exts)
|
|
29
|
+
setup_dependencies_via_each_repo_by_version(gemspec, exts)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
exts.each {|ext| sh %( cd ../#{ext} && rake ext )}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def setup_dependencies_via_monorepo(exts)
|
|
36
|
+
return false unless checkout_monorepo
|
|
37
|
+
exts.each {|ext| sh %( ln -snf all/#{ext} ../#{ext} )}
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def checkout_monorepo()
|
|
42
|
+
uuid = `git log -1 --format=%B`[/^\[\[([0-9a-fA-F-]+)\]\]$/, 1]
|
|
43
|
+
return false unless uuid
|
|
44
|
+
|
|
45
|
+
commit = setup_monorepo uuid
|
|
46
|
+
return false unless commit
|
|
47
|
+
|
|
48
|
+
Dir.chdir(ALL_DIR) {sh %( git checkout -q #{commit} )}
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def setup_monorepo(uuid)
|
|
53
|
+
unless File.directory? ALL_DIR
|
|
54
|
+
url = "https://github.com/#{ALL_REPO}.git"
|
|
55
|
+
sh %( git clone --no-tags --depth #{ALL_FETCH_DEPTH} #{url} #{ALL_DIR} )
|
|
56
|
+
end
|
|
57
|
+
loop do
|
|
58
|
+
commit = find_monorepo_commit uuid
|
|
59
|
+
return commit if commit
|
|
60
|
+
|
|
61
|
+
deepened = Dir.chdir ALL_DIR do
|
|
62
|
+
before = `git rev-list --count HEAD`.to_i
|
|
63
|
+
sh %( git fetch --deepen #{ALL_FETCH_DEPTH} )
|
|
64
|
+
`git rev-list --count HEAD`.to_i > before
|
|
65
|
+
end
|
|
66
|
+
return nil unless deepened
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def find_monorepo_commit(uuid)
|
|
71
|
+
Dir.chdir ALL_DIR do
|
|
72
|
+
out = `git log origin/HEAD -F --grep="[[#{uuid}]]" --format=%H -1`.strip
|
|
73
|
+
out.empty? ? nil : out
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def setup_dependencies_via_each_repo_by_version(gemspec, exts)
|
|
78
|
+
exts.each do |ext|
|
|
79
|
+
gem = RENAMES[ext.to_sym].then {|s| s || ext}
|
|
80
|
+
ver = gemspec[/add_dependency.*['"]#{gem}['"].*['"]\s*~>\s*([\d\.]+)\s*['"]/, 1]
|
|
81
|
+
opts = '-c advice.detachedHead=false --depth 1'
|
|
82
|
+
clone = "git clone #{opts} https://github.com/xord/#{ext}.git ../#{ext}"
|
|
83
|
+
|
|
84
|
+
# 'rake subtree:push' pushes all subrepos, so cloning by new tag
|
|
85
|
+
# often fails before tagging each new tag
|
|
86
|
+
sh %( #{clone} --branch v#{ver} || #{clone} )
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def tag_versions()
|
|
91
|
+
changes = changelogs
|
|
92
|
+
tags = `git tag`.lines chomp: true
|
|
93
|
+
vers = `git log --oneline ./VERSION`
|
|
94
|
+
.lines(chomp: true)
|
|
95
|
+
.map {|line| line.split.first[/^\w+$/]}
|
|
96
|
+
.map {|sha| [`git cat-file -p #{sha}:./VERSION 2>/dev/null`[/[\d\.]+/], sha]}
|
|
97
|
+
.select {|ver, sha| ver && sha}
|
|
98
|
+
.reverse
|
|
99
|
+
.to_h
|
|
100
|
+
|
|
101
|
+
vers.to_a.reverse.each do |ver, sha|
|
|
102
|
+
tag = "v#{ver}"
|
|
103
|
+
break if tags.include?(tag)
|
|
104
|
+
sh %( git tag -a -m \"#{changes[tag]&.gsub '"', '\\"'}\" #{tag} #{sha} )
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def release(*paths)
|
|
109
|
+
tag = ENV['GITHUB_REF']&.sub(%r|^refs/tags/|, '') || raise('GITHUB_REF tag not set')
|
|
110
|
+
notes = (changelogs[tag] || '').shellescape
|
|
111
|
+
paths = paths.flatten.join ' '
|
|
112
|
+
|
|
113
|
+
sh(%( gh release create #{tag} #{paths} --notes #{notes} )) ||
|
|
114
|
+
sh(%( gh release upload #{tag} #{paths} --clobber )) ||
|
|
115
|
+
raise('failed to upload to releases')
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def changelogs()
|
|
119
|
+
File.read('ChangeLog.md')
|
|
120
|
+
.split(/^\s*##\s*\[\s*(v[\d\.]+)\s*\].*$/)
|
|
121
|
+
.slice(1..)
|
|
122
|
+
.each_slice(2)
|
|
123
|
+
.to_h
|
|
124
|
+
.transform_values(&:strip!)
|
|
125
|
+
rescue Errno::ENOENT
|
|
126
|
+
raise 'failed to get changelogs'
|
|
127
|
+
end
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Contribution Guide
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
However, this repository does not accept pull requests.
|
|
5
|
+
Instead, please submit your changes to the [xord/all](https://github.com/xord/all) monorepo, which serves as the primary repository for all our main libraries.
|
|
6
|
+
|
|
7
|
+
For any questions, feel free to open an issue.
|
data/ChangeLog.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xord.org
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Reflex Packager - Package Reflex apps as native macOS bundles
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
## :warning: Notice
|
|
7
|
+
|
|
8
|
+
This repository is a read-only mirror of our monorepo.
|
|
9
|
+
We do not accept pull requests or direct contributions here.
|
|
10
|
+
|
|
11
|
+
### :repeat: Where to Contribute?
|
|
12
|
+
|
|
13
|
+
All development happens in our [xord/all](https://github.com/xord/all) monorepo, which contains all our main libraries.
|
|
14
|
+
If you'd like to contribute, please submit your changes there.
|
|
15
|
+
|
|
16
|
+
For more details, check out our [Contribution Guidelines](./CONTRIBUTING.md).
|
|
17
|
+
|
|
18
|
+
## :rocket: About
|
|
19
|
+
|
|
20
|
+
**Reflex Packager** is a CLI tool that packages [Reflex](https://github.com/xord/reflex) applications as native macOS `.app` bundles. It generates an Xcode project, fetches [CRuby](https://github.com/xord/cruby) and Reflex via CocoaPods, and builds a self-contained application that embeds the Ruby runtime.
|
|
21
|
+
|
|
22
|
+
The packager is runtime-agnostic — each gem (Reflex, [RubySketch](https://github.com/xord/rubysketch), ...) supplies its own profile and reuses this packager as the engine.
|
|
23
|
+
|
|
24
|
+
## :clipboard: Requirements
|
|
25
|
+
|
|
26
|
+
- Ruby **3.0.0** or later
|
|
27
|
+
- [XcodeGen](https://github.com/yonaskolb/XcodeGen) (`brew install xcodegen`)
|
|
28
|
+
- [CocoaPods](https://cocoapods.org/) (`brew install cocoapods`)
|
|
29
|
+
- Xcode (with command line tools)
|
|
30
|
+
- The dependent gems are installed automatically: `xot`, `rucy`, `rays`, `reflexion`
|
|
31
|
+
|
|
32
|
+
## :package: Installation
|
|
33
|
+
|
|
34
|
+
Add this line to your Gemfile:
|
|
35
|
+
```ruby
|
|
36
|
+
gem 'reflex-packager'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then install:
|
|
40
|
+
```bash
|
|
41
|
+
$ bundle install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or install it directly:
|
|
45
|
+
```bash
|
|
46
|
+
$ gem install reflex-packager
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## :bulb: Usage
|
|
50
|
+
|
|
51
|
+
### Create a new project
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
$ reflex new myapp
|
|
55
|
+
$ cd myapp
|
|
56
|
+
$ ruby main.rb # run the application directly
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This generates a project directory with `main.rb` and `reflex.yml`.
|
|
60
|
+
|
|
61
|
+
### Package as a macOS app
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
$ cd myapp
|
|
65
|
+
$ reflex package .
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The built `.app` bundle is placed in `dist/`.
|
|
69
|
+
|
|
70
|
+
### CLI options
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Usage: reflex <command> [options]
|
|
74
|
+
|
|
75
|
+
Commands:
|
|
76
|
+
new NAME create a new application project
|
|
77
|
+
package [DIR] package the application in DIR (default: .) as an app
|
|
78
|
+
|
|
79
|
+
Options:
|
|
80
|
+
-h, --help show this message
|
|
81
|
+
--version show version
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Package command options:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
reflex package [options] [DIR]
|
|
88
|
+
|
|
89
|
+
--platform PLATFORM target platform (default: macos)
|
|
90
|
+
--config PATH config file path (default: DIR/reflex.yml)
|
|
91
|
+
--generate-only generate project files but do not build
|
|
92
|
+
--verbose verbose output
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## :gear: Configuration
|
|
96
|
+
|
|
97
|
+
The project is configured via `reflex.yml` (or `reflex.yaml`) in the project directory.
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
name: MyApp
|
|
101
|
+
bundle_id: com.example.myapp
|
|
102
|
+
version: 1.0.0
|
|
103
|
+
icon: icon.png
|
|
104
|
+
# main: main.rb
|
|
105
|
+
# files:
|
|
106
|
+
# - "lib/**/*.rb"
|
|
107
|
+
|
|
108
|
+
# macos:
|
|
109
|
+
# deployment_target: "11.0"
|
|
110
|
+
# archs: arm64
|
|
111
|
+
# codesign:
|
|
112
|
+
# identity: "-"
|
|
113
|
+
# team_id: XXXXXXXXXX
|
|
114
|
+
|
|
115
|
+
# pods:
|
|
116
|
+
# cruby:
|
|
117
|
+
# path: /path/to/cruby
|
|
118
|
+
# reflex:
|
|
119
|
+
# path: /path/to/reflex
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
| Key | Default | Description |
|
|
123
|
+
|-----|---------|-------------|
|
|
124
|
+
| `name` | directory name | Application name |
|
|
125
|
+
| `bundle_id` | `org.xord.reflex.<name>` | macOS bundle identifier |
|
|
126
|
+
| `version` | `0.1.0` | Application version |
|
|
127
|
+
| `main` | `main.rb` | Entry point script |
|
|
128
|
+
| `icon` | none | Path to an icon image (PNG) |
|
|
129
|
+
| `files` | none | Additional files to bundle (glob patterns) |
|
|
130
|
+
| `macos.deployment_target` | `11.0` | Minimum macOS version |
|
|
131
|
+
| `macos.archs` | `arm64` | Target architectures |
|
|
132
|
+
| `macos.codesign.identity` | `-` | Code signing identity |
|
|
133
|
+
| `macos.codesign.team_id` | none | Development team ID |
|
|
134
|
+
|
|
135
|
+
### Pod overrides
|
|
136
|
+
|
|
137
|
+
By default the packager fetches CRuby and Reflex pods from their git repositories. To use local checkouts instead, set paths in the config or via the `REFLEX_PODS_PATH` environment variable:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
$ export REFLEX_PODS_PATH=/path/to/pods
|
|
141
|
+
$ reflex package .
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## :wrench: How it works
|
|
145
|
+
|
|
146
|
+
1. Copies application files into a build directory
|
|
147
|
+
2. Generates an Xcode project (via XcodeGen) and a Podfile
|
|
148
|
+
3. Runs `pod install` to fetch CRuby and Reflex pods
|
|
149
|
+
4. Builds the `.app` bundle with `xcodebuild`
|
|
150
|
+
5. Copies the result to `dist/`
|
|
151
|
+
|
|
152
|
+
The generated native wrapper embeds CRuby, registers the Reflex extensions, and runs the application's `main.rb` at launch.
|
|
153
|
+
|
|
154
|
+
## :hammer_and_wrench: Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
$ rake test # run the test suite
|
|
158
|
+
$ rake # default task
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
In the [`xord/all`](https://github.com/xord/all) monorepo you can scope by module.
|
|
162
|
+
|
|
163
|
+
## :scroll: License
|
|
164
|
+
|
|
165
|
+
**Reflex Packager** is licensed under the MIT License.
|
|
166
|
+
See the [LICENSE](./LICENSE) file for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- mode: ruby -*-
|
|
2
|
+
|
|
3
|
+
%w[../xot ../rucy ../rays ../reflex .]
|
|
4
|
+
.map {|s| File.expand_path "#{s}/lib", __dir__}
|
|
5
|
+
.each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
|
|
6
|
+
|
|
7
|
+
require 'rake/testtask'
|
|
8
|
+
require 'rucy/rake'
|
|
9
|
+
|
|
10
|
+
require 'xot/extension'
|
|
11
|
+
require 'rucy/extension'
|
|
12
|
+
require 'rays/extension'
|
|
13
|
+
require 'reflex/extension'
|
|
14
|
+
require 'reflex/packager/extension'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
EXTENSIONS = [Xot, Rucy, Rays, Reflex, Reflex::Packager]
|
|
18
|
+
|
|
19
|
+
ENV['RDOC'] = 'yardoc --no-private'
|
|
20
|
+
|
|
21
|
+
default_tasks
|
|
22
|
+
use_bundler
|
|
23
|
+
test_ruby_extension
|
|
24
|
+
generate_documents
|
|
25
|
+
build_ruby_gem
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.2
|
data/bin/reflex
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'reflex/extension'
|
|
4
|
+
require 'reflex/packager'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
profile = Reflex::Packager::Profile.new(
|
|
8
|
+
pod: 'Reflex',
|
|
9
|
+
git: 'https://github.com/xord/reflex',
|
|
10
|
+
version: Reflex::Extension.version,
|
|
11
|
+
libraries: %w[Xot Rucy Rays Reflex],
|
|
12
|
+
extensions: %w[rays_ext reflex_ext],
|
|
13
|
+
config_files: %w[reflex.yml reflex.yaml],
|
|
14
|
+
template: <<~RUBY)
|
|
15
|
+
require 'reflex'
|
|
16
|
+
|
|
17
|
+
Reflex.start do
|
|
18
|
+
Reflex::Window.new(title: '{{name}}', frame: [100, 100, 400, 300]).show
|
|
19
|
+
end
|
|
20
|
+
RUBY
|
|
21
|
+
|
|
22
|
+
Reflex::Packager::CLI.new(profile).run ARGV.dup
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'xot/block_util'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module Reflex
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
module Packager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Command line interface for a packager executable. Instantiated with the
|
|
13
|
+
# runtime profile to package for (Reflex by default).
|
|
14
|
+
#
|
|
15
|
+
class CLI
|
|
16
|
+
|
|
17
|
+
def initialize(profile)
|
|
18
|
+
@profile = profile
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def run(argv)
|
|
22
|
+
argv = argv.dup
|
|
23
|
+
parser = OptionParser.new do |o|
|
|
24
|
+
o.on('--version') {puts @profile.version; return}
|
|
25
|
+
o.on('-h', '--help') {puts usage; return}
|
|
26
|
+
end
|
|
27
|
+
parser.order! argv
|
|
28
|
+
|
|
29
|
+
case command = argv.shift
|
|
30
|
+
when 'new' then create argv
|
|
31
|
+
when 'package' then package argv
|
|
32
|
+
when nil then puts usage
|
|
33
|
+
else
|
|
34
|
+
$stderr.puts "unknown command: '#{command}'", '', usage
|
|
35
|
+
exit 1
|
|
36
|
+
end
|
|
37
|
+
rescue OptionParser::ParseError, Error => e
|
|
38
|
+
$stderr.puts "Error: #{e.message}"
|
|
39
|
+
exit 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def create(argv)
|
|
43
|
+
argv, = parse argv, "Usage: #{@profile.pod_key} new NAME"
|
|
44
|
+
|
|
45
|
+
name = argv.shift
|
|
46
|
+
raise Error, 'project name required' unless name
|
|
47
|
+
raise Error, "'#{name}' already exists" if File.exist? name
|
|
48
|
+
|
|
49
|
+
FileUtils.mkdir_p name
|
|
50
|
+
File.write File.join(name, 'main.rb'),
|
|
51
|
+
@profile.template.gsub('{{name}}') {name}
|
|
52
|
+
File.write File.join(name, @profile.config_files.first), <<~END
|
|
53
|
+
name: #{name}
|
|
54
|
+
#bundle_id: com.example.#{name.downcase.gsub(/[^a-z0-9]+/, '')}
|
|
55
|
+
#version: 1.0.0
|
|
56
|
+
#icon: icon.png
|
|
57
|
+
END
|
|
58
|
+
puts "Created #{name}/"
|
|
59
|
+
puts " cd #{name} && ruby main.rb # run the application"
|
|
60
|
+
puts " cd #{name} && #{@profile.pod_key} package . # package as an application"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def package(argv)
|
|
64
|
+
profile = @profile # capture for the instance_eval'd parse block below
|
|
65
|
+
argv, params = parse argv, "Usage: #{profile.pod_key} package [options] [DIR]" do
|
|
66
|
+
on '--platform PLATFORM', 'target platform (default: macos)'
|
|
67
|
+
on '--config PATH',
|
|
68
|
+
"config file path (default: DIR/#{profile.config_files.first})"
|
|
69
|
+
on '--generate-only', 'generate project files but do not build'
|
|
70
|
+
on '--verbose', 'verbose output'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
dir = argv.shift || '.'
|
|
74
|
+
platform = (params[:platform] || 'macos').to_sym
|
|
75
|
+
klass = PLATFORMS[platform]
|
|
76
|
+
raise Error, "unknown platform: '#{platform}'" unless klass
|
|
77
|
+
|
|
78
|
+
config = Config.load @profile, dir, params[:config]
|
|
79
|
+
klass.new(config, verbose: params[:verbose])
|
|
80
|
+
.package generate_only: params[:'generate-only']
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def usage()
|
|
86
|
+
<<~END
|
|
87
|
+
Usage: #{@profile.pod_key} <command> [options]
|
|
88
|
+
|
|
89
|
+
Commands:
|
|
90
|
+
new NAME create a new application project
|
|
91
|
+
package [DIR] package the application in DIR (default: .) as an app
|
|
92
|
+
|
|
93
|
+
Options:
|
|
94
|
+
-h, --help show this message
|
|
95
|
+
--version show version
|
|
96
|
+
END
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def parse(argv, banner = nil, &block)
|
|
100
|
+
opt = OptionParser.new
|
|
101
|
+
opt.banner = banner if banner
|
|
102
|
+
Xot::BlockUtil.instance_eval_or_block_call opt, &block if block
|
|
103
|
+
params = {}
|
|
104
|
+
argv = opt.parse argv.dup, into: params
|
|
105
|
+
return argv, params
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end# CLI
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
end# Packager
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
end# Reflex
|