iOS: basic building and running (#5999)
parent
1d59d35129
commit
51c9b49d3f
|
@ -17,7 +17,10 @@ pub const (
|
||||||
#flag freebsd -I/usr/local/include/freetype2
|
#flag freebsd -I/usr/local/include/freetype2
|
||||||
#flag freebsd -Wl -L/usr/local/lib
|
#flag freebsd -Wl -L/usr/local/lib
|
||||||
|
|
||||||
#flag -lfreetype
|
#flag windows -lfreetype
|
||||||
|
#flag linux -lfreetype
|
||||||
|
#flag darwin -lfreetype
|
||||||
|
|
||||||
#flag darwin -lpng -lbz2 -lz
|
#flag darwin -lpng -lbz2 -lz
|
||||||
|
|
||||||
#flag linux -I.
|
#flag linux -I.
|
||||||
|
|
|
@ -78,5 +78,12 @@ pub fn (mut b Builder) compile_c() {
|
||||||
out_name_c = get_vtmp_filename(b.pref.out_name, '.tmp.so.c')
|
out_name_c = get_vtmp_filename(b.pref.out_name, '.tmp.so.c')
|
||||||
}
|
}
|
||||||
b.build_c(files, out_name_c)
|
b.build_c(files, out_name_c)
|
||||||
|
if b.pref.os == .ios {
|
||||||
|
bundle_name := b.pref.out_name.split('/').last()
|
||||||
|
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
||||||
|
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
||||||
|
os.mkdir('$display_name\.app')
|
||||||
|
os.write_file('$display_name\.app/Info.plist', make_ios_plist(display_name, bundle_id, bundle_name, 1))
|
||||||
|
}
|
||||||
b.cc()
|
b.cc()
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,11 @@ fn (mut v Builder) cc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.pref.os == .ios {
|
if v.pref.os == .ios {
|
||||||
ccompiler = 'xcrun --sdk iphoneos gcc -arch arm64'
|
ios_sdk := if v.pref.is_ios_simulator { 'iphonesimulator' } else { 'iphoneos' }
|
||||||
|
ios_sdk_path_res := os.exec('xcrun --sdk $ios_sdk --show-sdk-path') or { panic('Couldn\'t find iphonesimulator') }
|
||||||
|
mut isysroot := ios_sdk_path_res.output.replace('\n', '')
|
||||||
|
|
||||||
|
ccompiler = 'xcrun --sdk iphoneos clang -isysroot $isysroot'
|
||||||
}
|
}
|
||||||
// arguments for the C compiler
|
// arguments for the C compiler
|
||||||
// TODO : activate -Werror once no warnings remain
|
// TODO : activate -Werror once no warnings remain
|
||||||
|
@ -146,6 +150,14 @@ fn (mut v Builder) cc() {
|
||||||
// warnings are totally fixed/removed
|
// warnings are totally fixed/removed
|
||||||
mut a := [v.pref.cflags, '-std=gnu11', '-Wall', '-Wextra', '-Wno-unused-variable', '-Wno-unused-parameter',
|
mut a := [v.pref.cflags, '-std=gnu11', '-Wall', '-Wextra', '-Wno-unused-variable', '-Wno-unused-parameter',
|
||||||
'-Wno-unused-result', '-Wno-unused-function', '-Wno-missing-braces', '-Wno-unused-label']
|
'-Wno-unused-result', '-Wno-unused-function', '-Wno-missing-braces', '-Wno-unused-label']
|
||||||
|
if v.pref.os == .ios {
|
||||||
|
a << '-framework Foundation'
|
||||||
|
a << '-framework UIKit'
|
||||||
|
a << '-framework Metal'
|
||||||
|
a << '-framework MetalKit'
|
||||||
|
a << '-DSOKOL_METAL'
|
||||||
|
a << '-fobjc-arc'
|
||||||
|
}
|
||||||
mut linker_flags := []string{}
|
mut linker_flags := []string{}
|
||||||
// TCC on Linux by default, unless -cc was provided
|
// TCC on Linux by default, unless -cc was provided
|
||||||
// TODO if -cc = cc, TCC is still used, default compiler should be
|
// TODO if -cc = cc, TCC is still used, default compiler should be
|
||||||
|
@ -335,12 +347,17 @@ fn (mut v Builder) cc() {
|
||||||
// Cross compiling windows
|
// Cross compiling windows
|
||||||
//
|
//
|
||||||
// Output executable name
|
// Output executable name
|
||||||
a << '-o "$v.pref.out_name"'
|
if v.pref.os == .ios {
|
||||||
|
bundle_name := v.pref.out_name.split('/').last()
|
||||||
|
a << '-o "$v.pref.out_name\.app/$bundle_name"'
|
||||||
|
} else {
|
||||||
|
a << '-o "$v.pref.out_name"'
|
||||||
|
}
|
||||||
if os.is_dir(v.pref.out_name) {
|
if os.is_dir(v.pref.out_name) {
|
||||||
verror("'$v.pref.out_name' is a directory")
|
verror("'$v.pref.out_name' is a directory")
|
||||||
}
|
}
|
||||||
// macOS code can include objective C TODO remove once objective C is replaced with C
|
// macOS code can include objective C TODO remove once objective C is replaced with C
|
||||||
if v.pref.os == .mac {
|
if v.pref.os == .mac || v.pref.os == .ios {
|
||||||
a << '-x objective-c'
|
a << '-x objective-c'
|
||||||
}
|
}
|
||||||
// The C file we are compiling
|
// The C file we are compiling
|
||||||
|
@ -546,12 +563,12 @@ fn (mut v Builder) cc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.pref.os == .ios {
|
// if v.pref.os == .ios {
|
||||||
ret := os.system('ldid2 -S $v.pref.out_name')
|
// ret := os.system('ldid2 -S $v.pref.out_name')
|
||||||
if ret != 0 {
|
// if ret != 0 {
|
||||||
eprintln('failed to run ldid2, try: brew install ldid')
|
// eprintln('failed to run ldid2, try: brew install ldid')
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut b Builder) cc_linux_cross() {
|
fn (mut b Builder) cc_linux_cross() {
|
||||||
|
|
|
@ -65,36 +65,49 @@ fn (mut b Builder) run_compiled_executable_and_exit() {
|
||||||
if b.pref.skip_running {
|
if b.pref.skip_running {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if b.pref.os == .ios && b.pref.is_ios_simulator == false {
|
||||||
|
panic('Running iOS apps on physical devices is not yet supported. Please run in the simulator using the -simulator flag.')
|
||||||
|
}
|
||||||
if b.pref.is_verbose {
|
if b.pref.is_verbose {
|
||||||
println('============ running $b.pref.out_name ============')
|
println('============ running $b.pref.out_name ============')
|
||||||
}
|
}
|
||||||
mut cmd := '"$b.pref.out_name"'
|
if b.pref.os == .ios {
|
||||||
if b.pref.backend == .js {
|
device := '"iPhone SE (2nd generation)"'
|
||||||
cmd = 'node "${b.pref.out_name}.js"'
|
os.exec('xcrun simctl boot $device')
|
||||||
}
|
bundle_name := b.pref.out_name.split('/').last()
|
||||||
for arg in b.pref.run_args {
|
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
||||||
// Determine if there are spaces in the parameters
|
os.exec('xcrun simctl install $device $display_name\.app')
|
||||||
if arg.index_byte(` `) > 0 {
|
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
||||||
cmd += ' "' + arg + '"'
|
os.exec('xcrun simctl launch $device $bundle_id')
|
||||||
} else {
|
} else {
|
||||||
cmd += ' ' + arg
|
mut cmd := '"$b.pref.out_name"'
|
||||||
|
if b.pref.backend == .js {
|
||||||
|
cmd = 'node "${b.pref.out_name}.js"'
|
||||||
}
|
}
|
||||||
}
|
for arg in b.pref.run_args {
|
||||||
if b.pref.is_verbose {
|
// Determine if there are spaces in the parameters
|
||||||
println('command to run executable: $cmd')
|
if arg.index_byte(` `) > 0 {
|
||||||
}
|
cmd += ' "' + arg + '"'
|
||||||
if b.pref.is_test {
|
} else {
|
||||||
ret := os.system(cmd)
|
cmd += ' ' + arg
|
||||||
if ret != 0 {
|
}
|
||||||
exit(1)
|
}
|
||||||
|
if b.pref.is_verbose {
|
||||||
|
println('command to run executable: $cmd')
|
||||||
|
}
|
||||||
|
if b.pref.is_test {
|
||||||
|
ret := os.system(cmd)
|
||||||
|
if ret != 0 {
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b.pref.is_run {
|
||||||
|
ret := os.system(cmd)
|
||||||
|
// TODO: make the runner wrapping as transparent as possible
|
||||||
|
// (i.e. use execve when implemented). For now though, the runner
|
||||||
|
// just returns the same exit code as the child process.
|
||||||
|
exit(ret)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if b.pref.is_run {
|
|
||||||
ret := os.system(cmd)
|
|
||||||
// TODO: make the runner wrapping as transparent as possible
|
|
||||||
// (i.e. use execve when implemented). For now though, the runner
|
|
||||||
// just returns the same exit code as the child process.
|
|
||||||
exit(ret)
|
|
||||||
}
|
}
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
module builder
|
||||||
|
|
||||||
|
fn make_ios_plist(display_name string, bundle_id string, bundle_name string, bundle_version int) string {
|
||||||
|
return '<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>$display_name</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$bundle_name</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$bundle_id</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$bundle_name</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>VIOS</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$bundle_version</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>'
|
||||||
|
}
|
|
@ -102,6 +102,8 @@ pub mut:
|
||||||
prealloc bool
|
prealloc bool
|
||||||
vroot string
|
vroot string
|
||||||
out_name string
|
out_name string
|
||||||
|
display_name string
|
||||||
|
bundle_id string
|
||||||
path string // Path to file/folder to compile
|
path string // Path to file/folder to compile
|
||||||
// -d vfmt and -d another=0 for `$if vfmt { will execute }` and `$if another { will NOT get here }`
|
// -d vfmt and -d another=0 for `$if vfmt { will execute }` and `$if another { will NOT get here }`
|
||||||
compile_defines []string // just ['vfmt']
|
compile_defines []string // just ['vfmt']
|
||||||
|
@ -118,6 +120,7 @@ pub mut:
|
||||||
only_check_syntax bool // when true, just parse the files, then stop, before running checker
|
only_check_syntax bool // when true, just parse the files, then stop, before running checker
|
||||||
experimental bool // enable experimental features
|
experimental bool // enable experimental features
|
||||||
show_timings bool // show how much time each compiler stage took
|
show_timings bool // show how much time each compiler stage took
|
||||||
|
is_ios_simulator bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_args(args []string) (&Preferences, string) {
|
pub fn parse_args(args []string) (&Preferences, string) {
|
||||||
|
@ -183,6 +186,9 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
||||||
'-prod' {
|
'-prod' {
|
||||||
res.is_prod = true
|
res.is_prod = true
|
||||||
}
|
}
|
||||||
|
'-simulator' {
|
||||||
|
res.is_ios_simulator = true
|
||||||
|
}
|
||||||
'-stats' {
|
'-stats' {
|
||||||
res.is_stats = true
|
res.is_stats = true
|
||||||
}
|
}
|
||||||
|
@ -285,6 +291,14 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
||||||
res.custom_prelude = prelude
|
res.custom_prelude = prelude
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
'-name' {
|
||||||
|
res.display_name = cmdline.option(current_args, '-name', '')
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
'-bundle' {
|
||||||
|
res.bundle_id = cmdline.option(current_args, '-bundle', '')
|
||||||
|
i++
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
mut should_continue := false
|
mut should_continue := false
|
||||||
for flag_with_param in list_of_flags_with_param {
|
for flag_with_param in list_of_flags_with_param {
|
||||||
|
|
Loading…
Reference in New Issue