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 -Wl -L/usr/local/lib | ||||
| 
 | ||||
| #flag -lfreetype | ||||
| #flag windows -lfreetype | ||||
| #flag linux -lfreetype | ||||
| #flag darwin -lfreetype | ||||
| 
 | ||||
| #flag darwin -lpng -lbz2 -lz | ||||
| 
 | ||||
| #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') | ||||
| 	} | ||||
| 	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() | ||||
| } | ||||
|  |  | |||
|  | @ -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() { | ||||
|  |  | |||
|  | @ -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) | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
| 	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 { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue