This is is a follow-up from my previous PR (#65). It makes gomobile
aware of GOOS=ios and adds support for specifying specific Apple
platforms, instead of overloading the "ios" platform.
Supported platforms: ios, iossimulator, macos, and maccatalyst
These can now be specified the -target argument to gomobile, e.g.:
gomobile build -target=ios,iossimulator,macos,maccatalyst
It preserves the current behavior of -target=ios, which will build for
ios and iossimulator on supported architectures (arm64 and amd64).
It adds platform-specific build tags so Go code can discriminate between
different Apple platforms like maccatalyst (UIKit on macOS).
This PR also fixes a number of broken tests.
TODO: cgo has a bug where c-archive builds targeting Catalyst will fail
unless -tags=ios is supplied. See https://golang.org/issues/47228
Fixes https://golang.org/issues/47212
Updates https://golang.org/issues/47228
Change-Id: Ib1a2f5302c5edd0704c13ffbe8f4061211f50d4e
GitHub-Last-Rev: 01ab28e63fe6890a9f9783e3fc41b1c895b0274d
GitHub-Pull-Request: golang/mobile#70
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/334689
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Trust: Hajime Hoshi <hajimehoshi@gmail.com>
The check when looking for android platform is unnecessarily stringent
in that the error would be caught by the call to os.Stat, and
it fails when the android platform folder is a symlink,
which is the case when developing on NixOs.
Change-Id: I07a96c969ffa29dea8bf8e353264e8597dcdc550
GitHub-Last-Rev: c684b80402ad30ad52eb854951aab69657ad7a5d
GitHub-Pull-Request: golang/mobile#55
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/267081
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
As of Go1.16, `go build` fails if go.sum does not exist. This change
fixes this issue by forcing to create go.sum by calling `go mod tidy`.
Closesgolang/go#44162
Change-Id: Ibba738503d1a58c6533b2427dd4efa6954b8eaa3
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/290409
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
Trust: Than McIntosh <thanm@google.com>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This CL enables Go modules in gomobile-bind command. This CL
generates go.mod at $WORK/src based on the modules state of the
working directory, and use it when executing go-build.
Updates golang/go#27234
Change-Id: I6958f29a317c0d2fb9ffa373f6e3c4cabdc4e898
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/210380
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Before this change, all the gomobile commands forced Go modules
to be off internally, regardless of the current Go modules state.
After this change, gomobile-init command follows the current Go
modules state. The other gomobile commands are not changed.
This is also a preparation to support Go modules in gomobile-bind
and gomobile-build.
Updates golang/go#27234
Change-Id: I3d9eedd667cba4d30de3ac0543f037be36cd3e51
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/210477
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
This is a preparation to enable Go modules for gomobile commands.
When Go modules is used, $GOPATH is not available. To build a
local package with Go modules, changing the working directory and
specifying the package by a relative path begining with `./` is
required. Changing the working directory is necessary because
building outside of modules is forbidden.
Specifying $GOPATH is still needed for reverse bindings (i.e.
special packages begining with `Java/` or `ObjC/`). Note that
gomobile with Go modules cannot support reverse bindings so far.
Updates golang/go#27234
Change-Id: Ib19300e1b8a973e76e06d24472c63a98605d65f7
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/209137
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This CL is a pure refactoring. This removes a global variable ctx,
which is a build.Default.
Before this change, ctx was used to keep build tags and its state
affected go command executions. As the variable is mutable, the
code was not readable.
This changes introduces another global variable buildTags instead,
but this is more consistent with other build flags, and this is
immutable.
Updates golang/go#27234
Change-Id: Id8d0c779de21b249e96febd2f40833cd0c84534f
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/208060
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This is a preparation to use Go modules at gomobile-bind.
Updates golang/go#27234
Change-Id: I33684888b4181cc1ebd4d3c8872a6b2e62950855
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/206777
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
No test as I couldn't figure out how to persuade gradle test to
strip classes.
Fixesgolang/go#30251
Change-Id: I7dca9169a4a8eb31b981ad49047a6bdfa6f6efd7
Reviewed-on: https://go-review.googlesource.com/c/164798
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
To use the NDK before version r19b standalone toolchains had to be
generated. Version r19b added prebuilt standalone toolchains.
Use the prebuilt for gomobile build and gomobile bind and
stop generating toolchains during gomobile init.
gomobile init is now only necessary for building OpenAL for
gomobile build programs.
This change is not compatible with NDK versions < r19b, but the
user is instructed how to upgrade when running gomobile build or
gomobile bind.
Change-Id: I96953298ecce42402459a9dd15169c09fe6b6f8b
Reviewed-on: https://go-review.googlesource.com/c/163378
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
A previous CL switched gobind to use the "source" importer so go
files using cgo can be type checked. However, CGO_ENABLED=1 also
have to be passed in for such files not be ignored.
Also add -tags ios to the gomobile test output missing from CL
99777.
Fixesgolang/go#24941
Change-Id: I868469af3061b82ab592899e365a8a90a0333e58
Reviewed-on: https://go-review.googlesource.com/108336
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
CL 99316 changed gobind to be platform independent, so
standalone bindings could be generated without having the
Android and Xcode SDKs installed. However, bindings that does
depend on GOOS for its exported API, in particular go source
files that use Cgo now only works if the exported API is
extracted to platform independent files.
By switching to use the source importer, importer.For("source", nil),
gobind can type check the bound packages even in the presence of
Cgo.
The source importer in Go 1.9 and 1.10 has problems with relative
imports and imports from testdata directories (issues 23092 and 24392),
but works from Go 1.10.1 on.
Fixesgolang/go#24856
Change-Id: Icb18dce15325b7d4e58cabc1181051bc6269fc1f
Reviewed-on: https://go-review.googlesource.com/99777
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Instead of using os.Getenv("GOPATH"), use go env GOPATH to determine
the effective GOPATH.
Fixesgolang/go#21658
Change-Id: I03f897969e30fc3256d171aa7b32c101a9342a1a
Reviewed-on: https://go-review.googlesource.com/101117
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
When running gomobile bind, make sure gobind exists. If not, instruct
the user to run gomobile init which will go install gobind.
Change-Id: I2d064ba58874fd5581c17417124561f3d1fb6b83
Reviewed-on: https://go-review.googlesource.com/101055
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The gobind and gomobile bind tools have historically overlapped:
gobind outputs generated bindings, and gomobile bind will generate
bindings before building them. However, the gobind bindings were
never used for building and thus allowed to not be complete.
To simplify version control, debugging, instrumentation and build
system flexibility, this CL upgrades the gobind tool to be the
canonical binding generator and change gomobile bind to use gobind
instead of its own generator code.
This greatly simplifies gomobile bind, but also paves the way to skip
gomobile bind entirely. For example:
$ gobind -outdir=$GOPATH golang.org/x/mobile/example/bind/hello
$ GOOS=android GOARCH=arm64 CC=<ndk-toolchain>/bin/clang go build -buildmode=c-shared -o libgobind.so gobind
$ ls libgobind.*
libgobind.h libgobind.so
The same applies to iOS, although the go build command line is more
involved.
By skipping gomobile it is possible to freely customize the Android
or iOS SDK level or any other flags not supported by gomobile bind.
By checking in the generated source code, the cost of supporting
gomobile in a custom build system is also decreased.
Change-Id: I59c14a77d625ac1377c23b3213672e0d83a48c85
Reviewed-on: https://go-review.googlesource.com/99316
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The extra build can't be required, because it is not run for the
build of the first GOARCH later in the loop. Tests run fine
without it.
Change-Id: Ida27e31ace2417192cce06c2efc93fa0d357012e
Reviewed-on: https://go-review.googlesource.com/98975
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Convert Go documentation to JavaDoc tags (/** ... */).
Since the .aar file format doesn't support source files, gomobile
will create a package-sources.jar along with the main package.aar.
For Objective-C, JavaDoc-style comments seems to work as well,
judging by manual inspection of Xcode quick help.
Change-Id: I47fe5b6804681d459a873be37a44610d392166ef
Reviewed-on: https://go-review.googlesource.com/52330
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Bump the minimum required version of Go to 1.7.
This removes version specific code and makes sure users have the
latest mobile related fixes to Go applied. Also, this change is
necessary when runtime.KeepAlive is introduced in a later CL.
Change-Id: I8441a28aef7f645379fbd8f00edabe3c3fb219de
Reviewed-on: https://go-review.googlesource.com/35953
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Output every Java class, including the support classes, from gobind
-lang=java. In addition, replace Go package export data parsing with
converting from go/ast to go/types. That way, gobind can tolerate
unknown imports as long as the exported Go API doesn't use them.
In a follow-up CL, the gobind gradle plugin will use gobind for a first
pass to expose the generated Java classes to the android plugin.
Change-Id: I8134899ec818c7fee79e4d9df8afcae9dd679add
Reviewed-on: https://go-review.googlesource.com/30093
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Add -bootclasspath and -classpath flags to the gomobile tool. In a
follow-up CL, the gobind gradle plugin will use them to support R and
databinding classes from Go.
Change-Id: Id33acf0c3fe1ec3908740b2a736ed241fa6391c2
Reviewed-on: https://go-review.googlesource.com/30092
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Using the new Java class analyzer API, scan the bound packages
for references to Java classes and interfaces and generate Go
wrappers for them.
This is the second part of the implementation of proposal golang/go#16876.
For golang/go#16876
Change-Id: I59ec0ebdae0081a615dc34d450f344c20c03f871
Reviewed-on: https://go-review.googlesource.com/28596
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Gobind uses strings for passing errors across the language barrier.
However, since Gobind doesn't have a concept of a nil string, it
can't separate an empty native string from a nil string.
In turn, that means that empty errors, exceptions or NSError * with
an empty description are treated as no error. With ObjC, empty errors
are replaced with a default string to workaround the issue, while
with Java empty errors are silently ignored.
Fix this by replacing strings with actual error objects, wrapping
the Go error, Java Throwable or ObjC NSError *, and letting the
existing bind machinery take care of passing the references across.
It's a large change for a small corner case, but I believe objects
are a better fit for exception that strings. Error objects also
naturally leads to future additions, for example accessing the
exception class name or chained exception.
Change-Id: Ie03b47cafcb231ad1e12a80195693fa7459c6265
Reviewed-on: https://go-review.googlesource.com/24100
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Multiple packages are already supported, but only as if each packages
were bound in isolation. This CL lets a bound package refer to other
bound packages in its exported functions, types and fields.
In Java, the JNI class jclass and constructor jmethodID are exported
so other packages can construct proxies of other packages' interfaces.
In ObjC, the class @interface declarations are moved from the package
.m file to its .h file to allow other packages to constructs its
interface proxies.
Add a supporting test package, secondpkg, and add Java and ObjC tests
for the new cross package functionality. Also add simplepkg for
testing corner cases where the generated Go file must not include its
bound package.
While we're here, stop generating Go proxy types for struct types;
only Go interfaces can be implemented in the foreign language.
Change-Id: Icbfa739c893703867d38a9100ed0928fbd7a660d
Reviewed-on: https://go-review.googlesource.com/20575
Reviewed-by: David Crawshaw <crawshaw@golang.org>
The seq serialization machinery is a historic artifact from when Go
mobile code had to run in a separate process. Now that Go code is running
in-process, replace the explicit serialization with direct calls and pass
arguments on the stack.
The benefits are a much smaller bind runtime, much less garbage (and, in
Java, fewer objects with finalizers), less argument copying, and faster
cross-language calls.
The cost is a more complex generator, because some of the work from the
bind runtime is moved to generated code. Generated code now handles
conversion between Go and Java/ObjC types, multiple return values and memory
management of byte slice and string arguments.
To overcome the lack of calling C code between Go packages, all bound
packages now end up in the same (fake) package, "gomobile_bind", instead of
separate packages (go_<pkgname>). To avoid name clashes, the package name is
added as a prefix to generated functions and types.
Also, don't copy byte arrays passed to Go, saving call time and
allowing read([]byte)-style interfaces to foreign callers (#12113).
Finally, add support for nil interfaces and struct pointers to objc.
This is a large CL, but most of the changes stem from changing testdata.
The full benchcmp output on the CL/20095 benchmarks on my Nexus 5 is
reproduced below. Note that the savings for the JavaSlice* benchmarks are
skewed because byte slices are no longer copied before passing them to Go.
benchmark old ns/op new ns/op delta
BenchmarkJavaEmpty 26.0 19.0 -26.92%
BenchmarkJavaEmptyDirect 23.0 22.0 -4.35%
BenchmarkJavaNoargs 7685 2339 -69.56%
BenchmarkJavaNoargsDirect 17405 8041 -53.80%
BenchmarkJavaOnearg 26887 2366 -91.20%
BenchmarkJavaOneargDirect 34266 7910 -76.92%
BenchmarkJavaOneret 38325 2245 -94.14%
BenchmarkJavaOneretDirect 46265 7708 -83.34%
BenchmarkJavaManyargs 41720 2535 -93.92%
BenchmarkJavaManyargsDirect 51026 8373 -83.59%
BenchmarkJavaRefjava 38139 21260 -44.26%
BenchmarkJavaRefjavaDirect 42706 28150 -34.08%
BenchmarkJavaRefgo 34403 6843 -80.11%
BenchmarkJavaRefgoDirect 40193 16582 -58.74%
BenchmarkJavaStringShort 32366 9323 -71.20%
BenchmarkJavaStringShortDirect 41973 19118 -54.45%
BenchmarkJavaStringLong 127879 94420 -26.16%
BenchmarkJavaStringLongDirect 133776 114760 -14.21%
BenchmarkJavaStringShortUnicode 32562 9221 -71.68%
BenchmarkJavaStringShortUnicodeDirect 41464 19094 -53.95%
BenchmarkJavaStringLongUnicode 131015 89401 -31.76%
BenchmarkJavaStringLongUnicodeDirect 134130 90786 -32.31%
BenchmarkJavaSliceShort 42462 7538 -82.25%
BenchmarkJavaSliceShortDirect 52940 17017 -67.86%
BenchmarkJavaSliceLong 138391 8466 -93.88%
BenchmarkJavaSliceLongDirect 205804 15666 -92.39%
BenchmarkGoEmpty 3.00 3.00 +0.00%
BenchmarkGoEmptyDirect 3.00 3.00 +0.00%
BenchmarkGoNoarg 40342 13716 -66.00%
BenchmarkGoNoargDirect 46691 13569 -70.94%
BenchmarkGoOnearg 43529 13757 -68.40%
BenchmarkGoOneargDirect 44867 14078 -68.62%
BenchmarkGoOneret 45456 13559 -70.17%
BenchmarkGoOneretDirect 44694 13442 -69.92%
BenchmarkGoRefjava 55111 28071 -49.06%
BenchmarkGoRefjavaDirect 60883 26872 -55.86%
BenchmarkGoRefgo 57038 29223 -48.77%
BenchmarkGoRefgoDirect 56153 27812 -50.47%
BenchmarkGoManyargs 67967 17398 -74.40%
BenchmarkGoManyargsDirect 60617 16998 -71.96%
BenchmarkGoStringShort 57538 22600 -60.72%
BenchmarkGoStringShortDirect 52627 22704 -56.86%
BenchmarkGoStringLong 128485 52530 -59.12%
BenchmarkGoStringLongDirect 138377 52079 -62.36%
BenchmarkGoStringShortUnicode 57062 22994 -59.70%
BenchmarkGoStringShortUnicodeDirect 62563 22938 -63.34%
BenchmarkGoStringLongUnicode 139913 55553 -60.29%
BenchmarkGoStringLongUnicodeDirect 150863 57791 -61.69%
BenchmarkGoSliceShort 59279 20215 -65.90%
BenchmarkGoSliceShortDirect 60160 21136 -64.87%
BenchmarkGoSliceLong 411225 301870 -26.59%
BenchmarkGoSliceLongDirect 399029 298915 -25.09%
Fixesgolang/go#12619Fixesgolang/go#12113Fixesgolang/go#13033
Change-Id: I2b45e9e98a1248e3c23a5137f775f7364908bec7
Reviewed-on: https://go-review.googlesource.com/19821
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This allows reuse of the code in custom gomobile bind tools.
Change-Id: I4e013ca871d0fa64983e7efb5e1e9dad8ac723c0
Reviewed-on: https://go-review.googlesource.com/18581
Reviewed-by: David Crawshaw <crawshaw@golang.org>
init command installs std for all the architectures supported by the
current go tool version (as listed in androidEnv).
build and bind commands pass the list of architectures to the underlying
functions. The list is currently hard-coded []string{"arm"}. In a
separate CL, the list will be populated from the -target flag value.
Still targets arm devices only.
For golang/go#10743
Change-Id: I62b5899859e76ad78a2dc55111e87aa13a68a1f9
Reviewed-on: https://go-review.googlesource.com/17749
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This does not change the tool's behavior.
The global ndkConfig 'ndk' holds info on all supported architectures
with the latest Go and gomobile tools (tip), and provides Root and
Toolchain methods that returns the current NDK installation directory
and the toolchain info depending on the GOPATH and the current go
version.
The global androidEnv is a map from arch name to the env vars.
ndkccpath is replaced by ndk.Root.
For golang/go#10743
Change-Id: I70d8e7b3e9979836112eb82d50c468df4f4ab43f
Reviewed-on: https://go-review.googlesource.com/17720
Reviewed-by: David Crawshaw <crawshaw@golang.org>
As discussed in golang/go#12245
Usage: gomobile bind [options] a.b.c x.y.z
For java gobind and gomobile will generate go.c.C.java and go.z.Z.java.
If -javapkg=com.example is specified they will generate
com.example.C.java and com.example.Z.java.
Tested on Darwin.
Change-Id: Ia8e57c8fec7967131d55de71cc705d9e736ccca0
Reviewed-on: https://go-review.googlesource.com/17023
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Replace the vendored version of x/tools/go/loader with the standard
library's go/importer package. This reads the export data from
$GOPATH/pkg/pkgname.a instead of parsing and type checking the source
code. The "go install" subcommand is invoked just prior to reading
the export data to make sure the export data is up to date.
Not yet tested on darwin, but working for android builds.
Change-Id: I24aa60aa46b843d30bc5833e3035699900bf3df4
Reviewed-on: https://go-review.googlesource.com/16913
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
New option -javapkg for -target=android, and -prefix for -target=ios.
Fixesgolang/go#9660.
Change-Id: I9143f30672672527876524b38f450629452a3161
Reviewed-on: https://go-review.googlesource.com/14023
Reviewed-by: David Crawshaw <crawshaw@golang.org>
In order to make the artifacts of go build command preserved under WORK
directory, this change modifies TMPDIR (TEMP/TMP for windows)
environment variables to point to gomobile's tmpdir if -work flag is set.
> gomobile init -work
WORK=/gopath/pkg/gomobile/work-276689736
> ls /gopath/pkg/gomobile/work-276689736
README go-build823903592 openal
android-ndk-r10e go-build858075903
go-build365743399 go-build921886344
> gomobile build -work golang.org/x/mobile/example/basic
WORK=/tmp/gomobile-work-863381843
> ls /tmp/gomobile-work-863381843
go-build102034516 libbasic.so
> gomobile bind -work github.com/hyangah/ivy
WORK=/tmp/gomobile-work-355100962
> ls /tmp/gomobile-work-355100962
android go-build284034365 javac-output
androidlib go_ivy
Change-Id: I2f467e0063bc1c8b8c636a8cd6d100e86a99a91a
Reviewed-on: https://go-review.googlesource.com/12720
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Tested:
go test golang.org/x/mobile/bind/java
gomobile bind -target={ios,android} github.com/hyangah/ivy
gobuild build -target={ios,android} golang.org/x/mobile/example/basic
(With various takes on -x and -v.)
Change-Id: I15c8f605490381feb6fefb482110f2a1c210529d
Reviewed-on: https://go-review.googlesource.com/12411
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The goal here is to remove several inconsistencies between
-target=android and -target=ios support, along with making the flow
of the command follow the path you might expect given a certain set
of flags, and preparing for `gomobile bind` support of ios. In
particular, building non-main packages now works with both targets
and the initialization of global build state is clearer.
The reorg also is designed around an nm trick I thought of
yesterday to do better package import scanning without a slow
all-file scan. This will give better detection of x/mobile/app and
x/mobile/exp/audio/al packages. There's a TODO about it, and I'll do
it in a future CL.
Tested with:
go test golang.org/x/mobile/cmd/gomobile
gomobile init
gomobile bind golang.org/x/mobile/asset
go test golang.org/x/mobile/bind/java
gomobile build -target=ios golang.org/x/mobile/example/basic
gomobile build -target=ios golang.org/x/mobile/gl
gomobile build -target=android golang.org/x/mobile/gl
gomobile build -target=android golang.org/x/mobile/example/basic
(Along with manual testing of basic on an android device.)
That might make a pretty good _test.go.
Change-Id: I41230008c3c15db25a11c33b9eaca4abada9f411
Reviewed-on: https://go-review.googlesource.com/12051
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>