diff --git a/mkapp.pike b/mkapp.pike --- a/mkapp.pike +++ b/mkapp.pike @@ -1,383 +1,380 @@ #!/bin/sh string OLDDIR; string BASEDIR; string identifier; string app_name; string version; string framework_bundle = "Pike.framework"; array sdk_locs = ({"/Developer/SDKs", "/SDKs", "/Developer", "/Library/Developer/CommandLineTools/SDKs"}); int no_embedded_pike = 0; string gcc = "clang"; -string sdk = "MacOSX10.14.sdk"; -string cc_args = "-m64 -mmacosx-version-min=10.10 -isysroot ${SDK} -F. -I/usr/local/include"; +string sdk = "MacOSX11.sdk"; +string cc_args = "-mmacosx-version-min=10.15 -isysroot ${SDK} -I/Users/hww3/pd/devel-11.0/include -F. -I/usr/local/include"; string ld_args = "-lobjc -lpthread -framework AppKit -framework Pike -framework System -framework Foundation"; int main(int argc, array(string) argv) { int err; OLDDIR = getcwd(); BASEDIR = dirname(argv[0]); if(err = parse_args(argv)) return err; argv -= ({0}); make_app(); return 0; } int parse_args(array(string) argv) { foreach(Getopt.find_all_options(argv,aggregate( ({"help",Getopt.NO_ARG,({"--help"}) }), ({"no_embedded_pike",Getopt.NO_ARG,({"--no-embedding"}) }), ({"identifier",Getopt.HAS_ARG,({"--identifier"}) }), ({"gcc",Getopt.HAS_ARG,({"--with-gcc"}) }), ({"sdk",Getopt.HAS_ARG,({"--with-sdk"}) }), ({"framework",Getopt.HAS_ARG,({"--framework"}) }), ({"version",Getopt.HAS_ARG,({"--version"}) }), )),array opt) { switch(opt[0]) { case "no_embedded_pike": no_embedded_pike = 1; break; case "identifier": identifier = opt[1]; break; case "gcc": gcc = opt[1]; break; case "sdk": sdk = opt[1]; break; case "framework": framework_bundle = opt[1]; break; case "version": version = opt[1]; break; case "help": write(help_text); exit(0); default: break; } } argv-=({0}); if(sizeof(argv) < 2) { werror("mkapp: no application name specified.\n"); return 1; } else { app_name = argv[1]; if(!is_valid_appname(app_name)) { werror("mkapp: application name %O contains invalid characters. aborting.\n", app_name); return 2; } } return 0; } int is_valid_appname(string appname) { if(sizeof((upper_case(appname)/"") - (" ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.!?$"/""))) return 0; return 1; } void make_file(string filename, string content) { Stdio.write_file(filename, replace(content, ({"${VERSION}", "${IDENTIFIER}", "${APPNAME}"}), ({version||"1.0, test", identifier||"org.gotpike." + app_name, app_name}) )); } void make_app() { write("mkapp: generating application bundle for %s\n", app_name); if(!no_embedded_pike && !file_stat(framework_bundle)) { werror("mkapp: Pike framework %O does not exist. aborting.\n", framework_bundle); exit(2); } if(file_stat(app_name + ".app")) { werror("mkapp: Error: application bundle directory " + app_name + ".app already exists.\n"); exit(2); } write("mkapp: creating app bundle..."); Stdio.mkdirhier(app_name + ".app/Contents/MacOS"); Stdio.mkdirhier(app_name + ".app/Contents/Resources"); Stdio.mkdirhier(app_name + ".app/Contents/Frameworks"); if(!no_embedded_pike) make_file(app_name + ".m", app_stub); make_file(app_name + ".app/Contents/Resources/" + app_name + ".pike", pike_stub); make_file(app_name + ".app/Contents/PkgInfo", pkg_info); make_file(app_name + ".app/Contents/Info.plist", info_plist); if(!no_embedded_pike) { Process.system("cp -Rf \"" + framework_bundle + "\" \"" + app_name + ".app/Contents/Frameworks\""); string my_cc_args = find_sdk(cc_args); string my_ld_args = find_sdk(ld_args); my_system(gcc + " " + my_cc_args + " -c '" + app_name + ".m' -o '" + app_name + ".o'"); // my_system(gcc + " " + my_cc_args + " -c method_getArgInfo.m -o '" + app_name + "_getArgInfo.o'"); my_system(gcc + " " + my_cc_args + " '" + app_name + ".o' -o '" + app_name + ".app/Contents/MacOS/" + app_name + "' " + ld_args); rm(app_name + ".o"); } write("mkapp: Build complete.\n"); } int my_system(string cmd, mixed ... io) { int rv; werror("mkapp: %s\n", cmd); if(rv = Process.system(cmd, @io)) { exit(rv); } return rv; } string find_sdk(string args) { string fqsdk; foreach(sdk_locs + ({""});; string loc) { // werror("looking for %s in %s\n", sdk, loc); string candidate = combine_path(loc, sdk); if(file_stat(candidate)) { fqsdk = candidate; break; } } if(!fqsdk) { werror("SDK " + sdk + " not found in (" + sdk_locs*", " + ").\n"); exit(1);} write("mkapp: found SDK at %s\n", fqsdk); return replace(args, "${SDK}", fqsdk); } string pkg_info = #"gInfo APPL???? "; string info_plist = #" CFBundleDevelopmentRegion English CFBundleExecutable ${APPNAME} CFBundleGetInfoString ${VERSION} CFBundleIdentifier ${IDENTIFIER} CFBundlePackageType APPL CFBundleSignature WvTx NSMainNibFile MainMenu.nib NSPrincipalClass NSApplication "; string app_stub = #" #import #import #import #import #import #import int main(int argc, char ** argv) { struct object * m; id i; struct svalue * sv; struct svalue * sv2; char * ecs; JMP_BUF back; int num; int x; -// required for console mode objective c applications - objc_startCollectorThread(); - // these 2 lines set up and start the interpreter. i = [OCPikeInterpreter sharedInterpreter]; [i startInterpreter]; [NSApplication sharedApplication]; if(SETJMP(back)) { if(throw_severity == THROW_EXIT || throw_severity == THROW_THREAD_EXIT) { num=throw_value.u.integer; }else{ if (TYPEOF(throw_value) == T_OBJECT && throw_value.u.object->prog == master_load_error_program && !get_master()) { /* Report this specific error in a nice way. Since there's no * master it'd be reported with a raw error dump otherwise. */ struct generic_error_struct *err; dynamic_buffer buf; dynbuf_string s; struct svalue t; move_svalue (Pike_sp++, &throw_value); mark_free_svalue (&throw_value); err = (struct generic_error_struct *) get_storage (Pike_sp[-1].u.object, generic_error_program); SET_SVAL(t, PIKE_T_STRING, 0, string, err->error_message); init_buf(&buf); describe_svalue(&t,0,0); s=complex_free_buf(&buf); fputs(s.str, stderr); free(s.str); } else call_handle_error(); num=10; } }else{ struct object *m; back.severity=THROW_EXIT; // ok, now that we have things set up, let's use it. // first, an example of calling pike c level apis directly. f_version(0); printf(\"%s\\n\", Pike_sp[-1].u.string->str); pop_stack(); ecs = malloc(256); snprintf(ecs, 256, \"dirname(\\\"%s\\\")\", argv[0]); sv = [i evalString: [NSString stringWithCString: ecs]]; printf(\"running from: %s\\n\", sv->u.string->str); snprintf(ecs, 256, \"cd(\\\"%s\\\")\", sv->u.string->str); sv2 = [i evalString: [NSString stringWithCString: ecs]]; chdir(\"../Resources/\"); free_svalue(sv); free_svalue(sv2); sv = [i evalString: @\"add_program_path(\\\".\\\")\"]; free_svalue(sv); sv = [i evalString: @\"add_module_path(\\\"modules\\\")\"]; free_svalue(sv); sv2 = [i evalString: @\"master()->resolv(\\\"Public.ObjectiveC.Cocoa\\\")\"]; free_svalue(sv2); push_text(\"__APPPATH\"); push_text(argv[0]); f_add_constant(2); m = get_master(); push_text(argv[0]); push_text(\"${APPNAME}.pike\"); for(x = 1; x < argc; x++) push_text(argv[x]); f_aggregate(argc + 1); apply(m, \"_main\", 1); } UNSETJMP(back); // finally, we clean up. [i stopInterpreter]; //[innerPool release]; return 0; } "; constant pike_stub = #"import Public.ObjectiveC; object NSApp; int main(int argc, array argv) { NSApp = Cocoa.NSApplication.sharedApplication(); add_constant(\"NSApp\", NSApp); NSApp->activateIgnoringOtherApps_(1); add_backend_to_runloop(Pike.DefaultBackend, 0.3); return AppKit()->NSApplicationMain(argc, argv); } "; constant help_text = #"pike -x mkapp Options: --help --no-embedding don't build stub binary --version=bundle_version --identifier=bundle_identifier --framework=path_to_pike_framework "; /* echo "building stub..." if [ ! -d "./$$_${APPNAME}.app" ] ; then tar cf - Pike.framework | tar xf - -C "$$_${APPNAME}.app/Contents/Frameworks" fi mv "$$_${APPNAME}" "$$_${APPNAME}.app/Contents/MacOS/${APPNAME}" rm "$$_${APPNAME}.m" "$$_${APPNAME}.o" if [ -d ${OLDDIR}/${APPNAME}.app ] ; then echo "${OLDDIR}/${APPNAME}.app already exists, not replacing." rm -rf $$_${APPNAME}.app exit 1; fi mv $$_${APPNAME}.app ${OLDDIR}/${APPNAME}.app */