Skip to content

Commit 777457d

Browse files
authoredAug 15, 2018
Merge pull request #18 from NHDaly/split_pkgs
julia 1.0 support: Merge "build-time" and "run-time" modules BuildApp and App into ApplicationBuilder
2 parents 4ef1dc2 + f28bd2a commit 777457d

19 files changed

+435
-481
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ There is both a native julia interface, in the `BuildApp` module, and a command-
1515

1616
To compile and bundle your julia program into a distributable app, use `BuildApp.build_app_bundle`:
1717
```julia
18-
julia> using ApplicationBuilder; using BuildApp
18+
julia> using ApplicationBuilder
1919
help?> build_app_bundle()
2020
# 1 method for generic function "build_app_bundle":
2121
build_app_bundle(juliaprog_main; appname, builddir, resources, libraries, verbose, bundle_identifier, app_version, icns_file, certificate, entitlements_file)

‎build_app.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using ArgParse, ApplicationBuilder; using BuildApp
1+
using ArgParse, ApplicationBuilder
22

33
const julia_v07 = VERSION > v"0.7-"
44

@@ -89,4 +89,4 @@ else
8989
filter!((k, v) -> v (nothing, false), parsed_args)
9090
end
9191

92-
BuildApp.build_app_bundle(juliaprog_main; parsed_args...)
92+
ApplicationBuilder.build_app_bundle(juliaprog_main; parsed_args...)

‎examples/blink.jl

-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# examples/blink.jl "HelloBlink"
1515

1616
using Blink
17-
using ApplicationBuilder
1817

1918
# In order to distribute this Application, we've copied all its dependencies
2019
# into the .app bundle via the -R and -L build flags.
@@ -84,10 +83,6 @@ function helloFromBlink()
8483
end
8584

8685
Base.@ccallable function julia_main(args::Vector{String})::Cint
87-
# Note that we must call this function in order for Blink to find the
88-
# resources we've copied into the Application bundle.
89-
ApplicationBuilder.App.change_dir_if_bundle()
90-
9186
# Apparently starting Electron too quickly means the OS doesn't get a
9287
# chance to find the name of the application...
9388
sleep(2)

‎examples/commandline_hello.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# A super-simple command line program that just prints hello.
2-
# Build this with the `commandline_app=true` flag in `BuildApp.build_app_bundle`.
2+
# Build this with the `commandline_app=true` flag in `ApplicationBuilder.build_app_bundle`.
33

44
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
55
println("Hi what's your name?")
66
name = readline()
7-
println("Oh hi, $name\! It's a pleasure to meet you.")
7+
println("Oh hi, $name. It's a pleasure to meet you.")
88
println("By the way, here's the current working directory:\n'$(pwd())'")
99

1010
println("\nGoodbye! (Press enter to exit)")

‎examples/hello.jl

-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
using ApplicationBuilder
2-
31
# Create a temporary .html file, and open it to share the greetings.
42
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
5-
ApplicationBuilder.App.change_dir_if_bundle()
6-
73
tmpdir = mktempdir()
84
filename = joinpath(tmpdir, "hello.html")
95
open(filename, "w") do io

‎examples/libui.jl

-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using ApplicationBuilder
2-
31
using Libui
42

53

@@ -173,8 +171,6 @@ end
173171

174172

175173
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
176-
ApplicationBuilder.App.change_dir_if_bundle()
177-
178174
global progressbar = uiNewProgressBar()
179175
global spinbox = uiNewSpinbox(0, 100)
180176
global slider = uiNewSlider(0, 100)

‎examples/sdl.jl

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
# test/build_examples/sdl.jl
77
# https://github.com/NHDaly/ApplicationBuilder.jl/tree/master/test/build_examples/sdl.jl
88

9-
using ApplicationBuilder
10-
119
using SimpleDirectMediaLayer
1210
SDL2 = SimpleDirectMediaLayer
1311

12+
using Compat.Pkg
13+
1414
fontFile = joinpath(Pkg.dir("SimpleDirectMediaLayer"),
1515
"assets","fonts","FiraCode","ttf","FiraCode-Regular.ttf")
1616

@@ -80,7 +80,6 @@ function helloFromSDL()
8080
end
8181

8282
Base.@ccallable function julia_main(args::Vector{String})::Cint
83-
ApplicationBuilder.App.change_dir_if_bundle()
8483
helloFromSDL()
8584
return 0
8685
end

‎src/ApplicationBuilder.jl

+294-57
Large diffs are not rendered by default.

‎src/BuildApp.jl

-280
This file was deleted.

‎src/program.c

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
JULIA_DEFINE_FAST_TLS()
1313
#endif
1414

15+
// `cd_to_bundle_resources` is injected by ApplicaionBuilder.jl
16+
extern void cd_to_bundle_resources();
17+
1518
// Declare C prototype of a function defined in Julia
1619
extern int julia_main(jl_array_t*);
1720

@@ -45,6 +48,9 @@ int main(int argc, char *argv[])
4548
jl_arrayset(ARGS, s, i - 1);
4649
}
4750

51+
// Navigate to inside the Appication Bundle before running julia_main
52+
cd_to_bundle_resources();
53+
4854
// call the work function, and get back a value
4955
retcode = julia_main(ARGS);
5056

‎test/ApplicationBuilder.jl

+93-31
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,93 @@
1-
using Base.Test
2-
3-
# Test that change_dir_if_bundle actually changes behavior based on ENV variable
4-
# set up fake .App
5-
tmpdir = mktempdir()
6-
tmpAppResources = joinpath(tmpdir, "Tmp.app/Contents/Resources")
7-
tmpAppMacOS = joinpath(tmpdir, "Tmp.app/Contents/MacOS")
8-
tmpAppExe = joinpath(tmpdir, "Tmp.app/Contents/MacOS/tmp")
9-
mkpath(tmpAppMacOS)
10-
mkpath(tmpAppResources)
11-
12-
# Set up test script. (Must be run as a separate process to allow the ENV
13-
# variable to generate different code at compile-time.)
14-
testScript = joinpath(tmpdir, "test.jl")
15-
write(testScript, """
16-
# ApplicationBuilder expects to be inside an App structure.
17-
eval(Base, :(PROGRAM_FILE = "$tmpAppExe"))
18-
# change_dir_if_bundle() will be differently based on the ENV variable.
19-
using ApplicationBuilder; ApplicationBuilder.App.change_dir_if_bundle(); println(pwd());
20-
""")
21-
22-
# Without ENV variable set, it should do nothing.
23-
@test pwd() == readlines(`julia $testScript`)[end]
24-
# With the ENV variable false, it should do nothing.
25-
@test pwd() == withenv(()->(readlines(`julia $testScript`)[end]),
26-
"COMPILING_APPLE_BUNDLE"=>"false") # Code is not being compiled.
27-
28-
# With COMPILING_APPLE_BUNDLE == true, the dir should change since it thinks the
29-
# code is being compiled as an app.
30-
@test pwd() != withenv(()->(readlines(`julia $testScript`)[end]),
31-
"COMPILING_APPLE_BUNDLE"=>"true") # Code is not being compiled.
1+
using Compat
2+
3+
using Compat.Test
4+
using Compat.Pkg
5+
using ApplicationBuilder
6+
7+
const julia_v07 = VERSION > v"0.7-"
8+
9+
builddir = mktempdir()
10+
@assert isdir(builddir)
11+
12+
@testset "make_bundle_identifier Utils" begin
13+
@test occursin(r"""^com.[a-z0-9]+.myappnamedthisapp22$""",
14+
ApplicationBuilder.make_bundle_identifier("My app named this_app22")
15+
)
16+
end
17+
18+
@testset "HelloWorld.app" begin
19+
@test 0 == include("build_examples/hello.jl")
20+
@test isdir("$builddir/HelloWorld.app")
21+
@test success(`$builddir/HelloWorld.app/Contents/MacOS/hello`)
22+
23+
# There shouldn't be a Libraries dir since none specified.
24+
@test !isdir("$builddir/HelloWorld.app/Contents/Libraries")
25+
26+
# Ensure all dependencies on Julia libs are internal, so the app is portable.
27+
@testset "No external Dependencies" begin
28+
@test !success(pipeline(
29+
`otool -l "$builddir/HelloWorld.app/Contents/MacOS/hello"`,
30+
`grep 'julia'`, # Get all julia deps
31+
`grep -v '@rpath'`)) # make sure all are relative.
32+
end
33+
end
34+
35+
@testset "commandline_app" begin
36+
@test 0 == include("build_examples/commandline_hello.jl")
37+
@test success(`open $builddir/hello.app`)
38+
end
39+
40+
41+
function testRunAndKillProgramSucceeds(cmd, timeout=10)
42+
out, _, p = readandwrite(cmd) # Make sure it runs correctly
43+
sleep(1)
44+
process_exited(p) && (println("Test Failed: failed to launch: \n", readstring(out)); return false)
45+
sleep(timeout)
46+
process_exited(p) && (println("Test Failed: Process died: \n", readstring(out)); return false)
47+
# Manually kill program after it's been running for a bit.
48+
kill(p); sleep(1)
49+
process_exited(p) || (println("Test Failed: Process failed to exit: \n", readstring(out)); return false)
50+
return true
51+
end
52+
53+
# Test that it can run without .julia directory (Dangerous!)
54+
function testBundledSuccessfully_macro(cmd_expr, timeout=10)
55+
quote
56+
val = false
57+
mv(Pkg.dir(), Pkg.dir()*".bak") # NOTE: MUST mv() THIS BACK
58+
try
59+
val = testRunAndKillProgramSucceeds($cmd_expr, $timeout)
60+
catch
61+
end
62+
mv(Pkg.dir()*".bak", Pkg.dir()) # NOTE: MUST RUN THIS LINE IF ABOVE IS RUN
63+
val
64+
end
65+
end
66+
macro testBundledSuccessfully(expr...)
67+
testBundledSuccessfully_macro(expr...)
68+
end
69+
70+
if !julia_v07 # Blink and SDL don't yet work on julia v0.7.
71+
72+
# Disabling the SDL tests since Cairo is currently broken in METADATA.
73+
#@testset "sdl: simple example of binary dependencies" begin
74+
#@test 0 == include("build_examples/sdl.jl")
75+
## Test that it runs correctly
76+
#@test testRunAndKillProgramSucceeds(`$builddir/HelloSDL2.app/Contents/MacOS/sdl`)
77+
## Test that it can run without .julia directory
78+
#@test @testBundledSuccessfully(`$builddir/HelloSDL2.app/Contents/MacOS/sdl`, 3)
79+
#end
80+
81+
@testset "HelloBlink.app" begin
82+
@test 0 == include("build_examples/blink.jl")
83+
84+
@test isdir("$builddir/HelloBlink.app")
85+
# Test that it copied the correct files
86+
@test isdir("$builddir/HelloBlink.app/Contents/Libraries")
87+
@test isfile("$builddir/HelloBlink.app/Contents/Resources/main.js")
88+
# Test that it runs correctly
89+
@test testRunAndKillProgramSucceeds(`$builddir/HelloBlink.app/Contents/MacOS/blink`)
90+
# Test that it can run without .julia directory
91+
@test @testBundledSuccessfully(`$builddir/HelloBlink.app/Contents/MacOS/blink`, 10)
92+
end
93+
end

‎test/BuildApp.jl

-70
This file was deleted.

‎test/REQUIRE

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
Blink
3+
# SimpleDirectMediaLayer # disabled since Cairo is currently broken in METADATA.

‎test/build_examples/blink.jl

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
using ApplicationBuilder; using BuildApp
1+
using ApplicationBuilder
2+
3+
using Compat
4+
using Compat.Pkg
25

36
examples_blink = joinpath(@__DIR__, "..", "..", "examples", "blink.jl")
47

58
# Allow this file to be called either as a standalone file to build the above
69
# example, or from runtests.jl using a provided builddir.
7-
isdefined(:builddir) || (builddir="builddir")
10+
Compat.isdefined(:builddir) || (builddir="builddir")
811

912
blinkPkg = Pkg.dir("Blink")
1013
httpParserPkg = Pkg.dir("HttpParser")
@@ -14,7 +17,7 @@ mbedTLSPkg = Pkg.dir("MbedTLS")
1417

1518
using Blink
1619

17-
BuildApp.build_app_bundle(examples_blink;
20+
ApplicationBuilder.build_app_bundle(examples_blink;
1821
verbose = true,
1922
resources = [joinpath(blinkPkg, "deps","Julia.app"),
2023
joinpath(blinkPkg, "src","AtomShell","main.js"),

‎test/build_examples/commandline_hello.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
using ApplicationBuilder; using BuildApp
1+
using ApplicationBuilder
2+
3+
using Compat
24

35
# Allow this file to be called either as a standalone file to build the above
46
# example, or from runtests.jl using a provided builddir.
5-
isdefined(:builddir) || (builddir="builddir")
7+
Compat.isdefined(:builddir) || (builddir="builddir")
68

79
build_app_bundle(joinpath(@__DIR__,"..","..","examples","commandline_hello.jl"),
810
appname="hello",

‎test/build_examples/hello.jl

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
using ApplicationBuilder; using BuildApp
1+
using ApplicationBuilder
2+
3+
using Compat
24

35
examples_hello = joinpath(@__DIR__, "..", "..", "examples", "hello.jl")
46

57
# Allow this file to be called either as a standalone file to build the above
68
# example, or from runtests.jl using a provided builddir.
7-
isdefined(:builddir) || (builddir="builddir")
9+
Compat.isdefined(:builddir) || (builddir="builddir")
810

9-
BuildApp.build_app_bundle(examples_hello;
11+
ApplicationBuilder.build_app_bundle(examples_hello;
1012
verbose=true, appname="HelloWorld", builddir=builddir)

‎test/build_examples/libui.jl

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
using ApplicationBuilder; using BuildApp
1+
using ApplicationBuilder
2+
3+
using Compat
4+
using Compat.Pkg
25

36
# Allow this file to be called either as a standalone file to build the above
47
# example, or from runtests.jl using a provided builddir.
5-
isdefined(:builddir) || (builddir="builddir")
8+
Compat.isdefined(:builddir) || (builddir="builddir")
69

710
libUIPkg = Pkg.dir("Libui")
811

912
@assert libUIPkg != nothing "LibUI is not installed!"
1013

1114
using Libui
1215

13-
BuildApp.build_app_bundle(joinpath(@__DIR__, "..", "..", "examples", "libui.jl");
16+
ApplicationBuilder.build_app_bundle(joinpath(@__DIR__, "..", "..", "examples", "libui.jl");
1417
verbose = true,
1518
resources = [],
1619
libraries = [ Libui.libui ],

‎test/build_examples/sdl.jl

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
using ApplicationBuilder; using BuildApp
1+
using ApplicationBuilder
2+
using Compat
3+
using Compat.Pkg
24

35
examples_blink = joinpath(@__DIR__, "..", "..", "examples", "sdl.jl")
46

57
# Allow this file to be called either as a standalone file to build the above
68
# example, or from runtests.jl using a globally-defined builddir.
7-
isdefined(:builddir) || (builddir="builddir")
9+
Compat.isdefined(:builddir) || (builddir="builddir")
810

911
using SimpleDirectMediaLayer
1012
SDL2 = SimpleDirectMediaLayer
@@ -21,7 +23,7 @@ libs = joinpath(builddir, "sdl_libs")
2123
mkpath(libs)
2224
function cp_lib(l)
2325
name = basename(l)
24-
cp(l, joinpath(libs, name), follow_symlinks=true)
26+
Compat.cp(l, joinpath(libs, name), follow_symlinks=true, force=true)
2527
l = joinpath(libs, name)
2628
run(`install_name_tool -id "$name" $l`)
2729
try
@@ -36,6 +38,7 @@ function cp_lib(l)
3638
println(cmd)
3739
run(cmd)
3840
end
41+
catch
3942
end
4043
end
4144
cp_lib(SDL2.libSDL2)
@@ -49,10 +52,10 @@ cp_lib(joinpath(homebrew, "deps/usr/lib/libogg.dylib"))
4952
cp_lib(joinpath(homebrew, "deps/usr/lib/libpng16.dylib"))
5053

5154

52-
BuildApp.build_app_bundle(examples_blink;
55+
build_app_bundle(examples_blink;
5356
verbose = true,
5457
resources = [joinpath(sdlPkg,
5558
"assets","fonts","FiraCode","ttf","FiraCode-Regular.ttf"),
5659
],
57-
libraries = ["libs/*"],
60+
libraries = ["$libs/*"],
5861
appname="HelloSDL2", builddir=builddir)

‎test/runtests.jl

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
using Base.Test
1+
using Compat.Test
22

3-
@testset "ApplicationBuilder tests" begin
4-
Base.invokelatest(include, "ApplicationBuilder.jl")
5-
end
6-
@testset "Test BuildApp (by compiling examples/*.jl)" begin
7-
include("BuildApp.jl")
3+
@testset "Test ApplicationBuilder (by compiling examples/*.jl)" begin
4+
include("ApplicationBuilder.jl")
85
end
96
@testset "Command-line interface (compiling examples/*.jl)" begin
107
include("build_app-cli.jl")

0 commit comments

Comments
 (0)
Please sign in to comment.