diff --git a/vlib/sokol/f/f.v b/vlib/sokol/f/f.v index d322f02ef4..525a6343cc 100644 --- a/vlib/sokol/f/f.v +++ b/vlib/sokol/f/f.v @@ -17,7 +17,10 @@ pub const ( #flag freebsd -I/usr/local/include/freetype2 #flag freebsd -Wl -L/usr/local/lib -#flag -lfreetype +#flag windows -lfreetype +#flag linux -lfreetype +#flag darwin -lfreetype + #flag darwin -lpng -lbz2 -lz #flag linux -I. diff --git a/vlib/v/builder/c.v b/vlib/v/builder/c.v index 1c6590cbae..36713a4d13 100644 --- a/vlib/v/builder/c.v +++ b/vlib/v/builder/c.v @@ -78,5 +78,12 @@ pub fn (mut b Builder) compile_c() { out_name_c = get_vtmp_filename(b.pref.out_name, '.tmp.so.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() } diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index 7696447d4c..550626f166 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -137,7 +137,11 @@ fn (mut v Builder) cc() { } } 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 // TODO : activate -Werror once no warnings remain @@ -146,6 +150,14 @@ fn (mut v Builder) cc() { // warnings are totally fixed/removed 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'] + 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{} // TCC on Linux by default, unless -cc was provided // TODO if -cc = cc, TCC is still used, default compiler should be @@ -335,12 +347,17 @@ fn (mut v Builder) cc() { // Cross compiling windows // // 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) { verror("'$v.pref.out_name' is a directory") } // 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' } // The C file we are compiling @@ -546,12 +563,12 @@ fn (mut v Builder) cc() { } } } - if v.pref.os == .ios { - ret := os.system('ldid2 -S $v.pref.out_name') - if ret != 0 { - eprintln('failed to run ldid2, try: brew install ldid') - } - } + // if v.pref.os == .ios { + // ret := os.system('ldid2 -S $v.pref.out_name') + // if ret != 0 { + // eprintln('failed to run ldid2, try: brew install ldid') + // } + // } } fn (mut b Builder) cc_linux_cross() { diff --git a/vlib/v/builder/compile.v b/vlib/v/builder/compile.v index de4f6c79e8..ac63f449c7 100644 --- a/vlib/v/builder/compile.v +++ b/vlib/v/builder/compile.v @@ -65,36 +65,49 @@ fn (mut b Builder) run_compiled_executable_and_exit() { if b.pref.skip_running { 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 { println('============ running $b.pref.out_name ============') } - 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 { - // Determine if there are spaces in the parameters - if arg.index_byte(` `) > 0 { - cmd += ' "' + arg + '"' - } else { - cmd += ' ' + arg + if b.pref.os == .ios { + device := '"iPhone SE (2nd generation)"' + os.exec('xcrun simctl boot $device') + bundle_name := b.pref.out_name.split('/').last() + display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name } + os.exec('xcrun simctl install $device $display_name\.app') + bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' } + os.exec('xcrun simctl launch $device $bundle_id') + } else { + mut cmd := '"$b.pref.out_name"' + if b.pref.backend == .js { + cmd = 'node "${b.pref.out_name}.js"' } - } - 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) + for arg in b.pref.run_args { + // Determine if there are spaces in the parameters + if arg.index_byte(` `) > 0 { + cmd += ' "' + arg + '"' + } else { + cmd += ' ' + arg + } + } + 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) } diff --git a/vlib/v/builder/iosplist.v b/vlib/v/builder/iosplist.v new file mode 100644 index 0000000000..08d5ee8735 --- /dev/null +++ b/vlib/v/builder/iosplist.v @@ -0,0 +1,39 @@ +module builder + +fn make_ios_plist(display_name string, bundle_id string, bundle_name string, bundle_version int) string { + return ' + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + $display_name + CFBundleExecutable + $bundle_name + CFBundleIdentifier + $bundle_id + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $bundle_name + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + VIOS + CFBundleVersion + $bundle_version + LSRequiresIPhoneOS + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + +' +} \ No newline at end of file diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index 2556127ba3..f7df88b82c 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -102,6 +102,8 @@ pub mut: prealloc bool vroot string out_name string + display_name string + bundle_id string 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 }` 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 experimental bool // enable experimental features show_timings bool // show how much time each compiler stage took + is_ios_simulator bool } pub fn parse_args(args []string) (&Preferences, string) { @@ -183,6 +186,9 @@ pub fn parse_args(args []string) (&Preferences, string) { '-prod' { res.is_prod = true } + '-simulator' { + res.is_ios_simulator = true + } '-stats' { res.is_stats = true } @@ -285,6 +291,14 @@ pub fn parse_args(args []string) (&Preferences, string) { res.custom_prelude = prelude i++ } + '-name' { + res.display_name = cmdline.option(current_args, '-name', '') + i++ + } + '-bundle' { + res.bundle_id = cmdline.option(current_args, '-bundle', '') + i++ + } else { mut should_continue := false for flag_with_param in list_of_flags_with_param {