xamarin-macios/runtime/launcher.m

700 строки
20 KiB
Mathematica
Исходник Обычный вид История

2016-04-21 15:19:32 +03:00
// vim: set filetype=objc :
#include <dlfcn.h> // dlsym
#import <Cocoa/Cocoa.h>
#include "shared.h"
#include "product.h"
#include "xamarin/xamarin.h"
#include "xamarin/launch.h"
#include "launcher.h"
#include "runtime-internal.h"
#include "main-internal.h"
2016-04-21 15:19:32 +03:00
#ifdef DYNAMIC_MONO_RUNTIME
#define DEFAULT_MONO_RUNTIME "/Library/Frameworks/Mono.framework/Versions/Current"
static const char *mono_runtime_prefix = NULL;
bool xamarin_enable_debug = 0;
#endif
static char original_working_directory_path [MAXPATHLEN];
extern "C" const char * const
xamarin_get_original_working_directory_path ()
{
return original_working_directory_path;
}
static int
redirect_io (int from_fd, const char *to_path)
{
int err;
int fd;
if ((fd = open (to_path, O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1)
return -1;
if (dup2 (fd, from_fd) == -1) {
err = errno;
close (fd);
errno = err;
return -1;
}
return fd;
2016-04-21 15:19:32 +03:00
}
static void
init_logdir (void)
{
// If redirected we will not be closing the returned file descriptors anywhere.
// That's "by design" so they will keep logging as long as the app is alive.
static int redirected_stdout = -1;
static int redirected_stderr = -1;
2016-04-21 15:19:32 +03:00
const char *env;
size_t dirlen;
char *path;
if ((env = getenv ("MONOMAC_LOGDIR")) != NULL && *env) {
// Redirect stdout/err to log files...
NSError *error = nil;
if (![[NSFileManager defaultManager]
createDirectoryAtPath: [NSString stringWithUTF8String: env]
withIntermediateDirectories: YES
attributes: @{ NSFilePosixPermissions: [NSNumber numberWithInt: 0755] }
error: &error]) {
fprintf (stderr, PRODUCT ": Could not create log directory: %s\n", [[error description] UTF8String]);
return;
}
dirlen = strlen (env);
path = (char *) malloc (dirlen + 12);
strcpy (path, env);
if (path[dirlen - 1] != '/')
path[dirlen++] = '/';
strcpy (path + dirlen, "stdout.log");
redirected_stdout = redirect_io (STDOUT_FILENO, path);
if (redirected_stdout == -1)
fprintf (stderr, PRODUCT ": Could not redirect %s to `%s': %s\n", "stdout", path, strerror (errno));
2016-04-21 15:19:32 +03:00
strcpy (path + dirlen, "stderr.log");
redirected_stderr = redirect_io (STDERR_FILENO, path);
if (redirected_stderr == -1)
fprintf (stderr, PRODUCT ": Could not redirect %s to `%s': %s\n", "stderr", path, strerror (errno));
2016-04-21 15:19:32 +03:00
free (path);
}
}
static char *
decode_qstring (unsigned char **in, unsigned char qchar)
{
unsigned char *inptr = *in;
unsigned char *start = *in;
char *value, *v;
size_t len = 0;
while (*inptr) {
if (*inptr == qchar)
break;
if (*inptr == '\\') {
if (inptr[1] == '\0')
break;
inptr++;
}
inptr++;
len++;
}
v = value = (char *) malloc (len + 1);
while (start < inptr) {
if (*start == '\\')
start++;
*v++ = (char) *start++;
}
*v = '\0';
if (*inptr)
inptr++;
*in = inptr;
return value;
}
typedef struct _ListNode {
struct _ListNode *next;
char *value;
} ListNode;
static char **
get_mono_env_options (int *count)
{
const char *env = getenv ("MONO_ENV_OPTIONS");
ListNode *list = NULL, *node, *tail = NULL;
unsigned char *start, *inptr;
char *value, **argv;
int i, n = 0;
size_t size;
if (env == NULL) {
*count = 0;
return NULL;
}
inptr = (unsigned char *) env;
while (*inptr) {
while (isblank ((int) *inptr & 0xff))
2016-04-21 15:19:32 +03:00
inptr++;
if (*inptr == '\0')
break;
start = inptr++;
switch (*start) {
case '\'':
case '"':
value = decode_qstring (&inptr, *start);
break;
default:
while (*inptr && !isblank ((int) *inptr & 0xff))
2016-04-21 15:19:32 +03:00
inptr++;
// Note: Mac OS X <= 10.6.8 do not have strndup()
//value = strndup ((char *) start, (size_t) (inptr - start));
size = (size_t) (inptr - start);
value = (char *) malloc (size + 1);
memcpy (value, start, size);
value[size] = '\0';
break;
}
node = (ListNode *) malloc (sizeof (ListNode));
node->value = value;
node->next = NULL;
n++;
if (tail != NULL)
tail->next = node;
else
list = node;
tail = node;
}
// Note: we do not want child processes to inherit this environment variable,
// so now that we've parsed it (and each value is strdup'd), we can safely
// unset it.
unsetenv ("MONO_ENV_OPTIONS");
*count = n;
if (n == 0)
return NULL;
argv = (char **) malloc (sizeof (char *) * (n + 1));
i = 0;
while (list != NULL) {
node = list->next;
argv[i++] = list->value;
free (list);
list = node;
}
argv[i] = NULL;
return argv;
}
static void
exit_with_message (const char *reason, const char *argv0, bool request_mono)
{
NSString *appName = nil;
NSDictionary *plist = [[NSBundle mainBundle] infoDictionary];
if (plist) {
appName = (NSString *) [plist objectForKey:(NSString *)kCFBundleNameKey];
}
if (!appName) {
appName = [[NSString stringWithUTF8String: argv0] lastPathComponent];
}
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:[NSString stringWithFormat:@"Could not launch %@", appName]];
NSString *fmt = request_mono ? @"%s\n\nPlease download and install the latest version of Mono." : @"%s\n";
NSString *msg = [NSString stringWithFormat:fmt, reason];
[alert setInformativeText:msg];
NSLog (@"%@", msg);
2016-04-21 15:19:32 +03:00
if (request_mono) {
[alert addButtonWithTitle:@"Download Mono Framework"];
[alert addButtonWithTitle:@"Cancel"];
} else {
[alert addButtonWithTitle:@"OK"];
}
NSInteger answer = [alert runModal];
[alert release];
if (request_mono && answer == NSAlertFirstButtonReturn) {
2018-03-07 16:46:59 +03:00
NSString *mono_download_url = @"http://www.mono-project.com/download/stable/";
2016-04-21 15:19:32 +03:00
CFURLRef url = CFURLCreateWithString (NULL, (CFStringRef) mono_download_url, NULL);
LSOpenCFURLRef (url, NULL);
CFRelease (url);
}
exit (1);
}
Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. (#4695) * Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. I've verified that we fail at launch of running on 5.12, while 5.14 works fine (to launch at least), so the minimum system mono version is _at least_ 5.14. Fixes https://github.com/xamarin/xamarin-macios/issues/4120. * [mmp] Load mono's version file instead of using pkg-config to get mono's version. pkg-config will only get three parts of the version, while the version file has all four parts. This is important, since we're now verifying the four parts of the version file, and without loading those four from the system, we'll fail builds like this: error MM0001: This version of Xamarin.Mac requires Mono 5.14.0.136 (the current Mono version is 5.14.0). because the three part version's fourth number is assumed to be 0. * Only verify mono runtime version when running with system/dynamic mono. There should be no need to verify the mono runtime version when embedding mono: * If it's a mono we're shipping, something very bad happened in our build/package for it to be an invalid mono. * If it's a system mono that's being embedded, then we verify in mmp at build time. In the first scenario (a mono we're shipping), the problem is that the mono we've built does not report back the full version number (with four parts) [1], which means we'll fail any check whose requirements are identical for the first three parts, and non-zero for the last. [1] The fourth part of the version number is created/calculated when packaging mono, and we're not packaging it.
2018-08-29 15:28:56 +03:00
#ifdef DYNAMIC_MONO_RUNTIME
2016-04-21 15:19:32 +03:00
static int
check_mono_version (const char *version, const char *req_version)
{
char *req_end, *end;
long req_val, val;
while (*req_version) {
req_val = strtol (req_version, &req_end, 10);
if (req_version == req_end || (*req_end && *req_end != '.')) {
fprintf (stderr, "Bad version requirement string '%s'\n", req_end);
return FALSE;
}
req_version = req_end;
if (*req_version)
req_version++;
val = strtol (version, &end, 10);
if (version == end || val < req_val)
return FALSE;
if (val > req_val)
return TRUE;
if (*req_version == '.' && *end != '.')
return FALSE;
version = end + 1;
}
return TRUE;
}
static int
push_env (const char *variable, NSString *str_value)
{
const char *value = [str_value UTF8String];
size_t len = strlen (value);
const char *current;
int rv;
if ((current = getenv (variable)) && *current) {
char *buf = (char *) malloc (len + strlen (current) + 2);
memcpy (buf, value, len);
buf[len] = ':';
strcpy (buf + len + 1, current);
rv = setenv (variable, buf, 1);
free (buf);
} else {
rv = setenv (variable, value, 1);
}
return rv;
}
#endif
static void
update_environment (xamarin_initialize_data *data)
{
if (xamarin_get_is_mkbundle ())
return;
// 3) Ensure the following environment variables are set: [...]
NSString *res_dir;
NSString *monobundle_dir;
if (data->launch_mode == XamarinLaunchModeEmbedded) {
monobundle_dir = [data->app_dir stringByAppendingPathComponent: @"Versions/Current/MonoBundle"];
res_dir = [data->app_dir stringByAppendingPathComponent: @"Versions/Current/Resources"];
} else {
monobundle_dir = [data->app_dir stringByAppendingPathComponent: @"Contents/MonoBundle"];
res_dir = [data->app_dir stringByAppendingPathComponent: @"Contents/Resources"];
}
2016-04-21 15:19:32 +03:00
#ifdef DYNAMIC_MONO_RUNTIME
NSString *bin_dir = [data->app_dir stringByAppendingPathComponent: @"Contents/MacOS"];
push_env ("DYLD_FALLBACK_LIBRARY_PATH", [NSString stringWithFormat: @"%s/lib:/usr/local/lib:/lib:/usr/lib", getenv ("HOME")]);
push_env ("DYLD_FALLBACK_LIBRARY_PATH", [res_dir stringByAppendingPathComponent: @"/lib"]);
push_env ("DYLD_FALLBACK_LIBRARY_PATH", [[NSString stringWithUTF8String: mono_runtime_prefix] stringByAppendingPathComponent: @"/lib"]);
/* Mono "External" directory */
push_env ("PKG_CONFIG_PATH", @"/Library/Frameworks/Mono.framework/External/pkgconfig");
/* Enable the use of stuff bundled into the app bundle */
push_env ("PKG_CONFIG_PATH", [res_dir stringByAppendingPathComponent: @"/lib/pkgconfig"]);
push_env ("PKG_CONFIG_PATH", [res_dir stringByAppendingPathComponent: @"/share/pkgconfig"]);
push_env ("MONO_GAC_PREFIX", res_dir);
push_env ("PATH", bin_dir);
data->requires_relaunch = true;
#else
// disable /dev/shm since Apple refuse applications that uses it in the Mac App Store
setenv ("MONO_DISABLE_SHARED_AREA", "", 1);
unsetenv ("MONO_PATH");
mono_set_assemblies_path (xamarin_get_bundle_path ());
// 3b) (If embedding Mono) Change the current directory to $appdir/Contents/Resources
chdir ([res_dir UTF8String]);
// Set up environment variables that need to point to ~/Library/Application Support (registry path)
NSFileManager *mgr = [NSFileManager defaultManager];
NSArray *appSupportDirectories = [mgr URLsForDirectory:NSApplicationSupportDirectory inDomains:NSSystemDomainMask];
if ([appSupportDirectories count] > 0) {
NSString *appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSURL *appSupport = [appSupportDirectories objectAtIndex: 0];
if (appSupport != nil && appBundleID != nil) {
NSURL *appDirectory = [appSupport URLByAppendingPathComponent:appBundleID isDirectory: YES];
2016-04-21 15:19:32 +03:00
setenv ("MONO_REGISTRY_PATH", [[appDirectory path] UTF8String], 1);
}
}
#endif
const char *mono_debug = NULL;
// Unfortunately the only place to set debug_options.no_gdb_backtrace is in mini_parse_debug_option
// So route through MONO_DEBUG
if (xamarin_disable_lldb_attach && xamarin_disable_omit_fp) {
mono_debug = "no-gdb-backtrace,disable-omit-fp";
} else if (xamarin_disable_lldb_attach) {
mono_debug = "no-gdb-backtrace";
} else if (xamarin_disable_omit_fp) {
mono_debug = "disable_omit_fp";
}
if (mono_debug != NULL)
setenv ("MONO_DEBUG", mono_debug, 0);
#ifndef DYNAMIC_MONO_RUNTIME
setenv ("MONO_CFG_DIR", [monobundle_dir UTF8String], 0);
#endif
2016-04-21 15:19:32 +03:00
}
static void
app_initialize (xamarin_initialize_data *data)
2016-04-21 15:19:32 +03:00
{
// The launch code here is publicly documented in xamarin/launch.h
// The numbers in the comments refer to numbers in xamarin/launch.h.
xamarin_launch_mode = data->launch_mode;
2016-04-21 15:19:32 +03:00
#ifndef SYSTEM_LAUNCHER
if (xammac_setup ()) {
data->exit_code = -1;
return;
}
#endif
bool mkbundle = xamarin_get_is_mkbundle ();
NSBundle *bundle;
if (data->launch_mode == XamarinLaunchModeEmbedded) {
bundle = [NSBundle bundleForClass: [XamarinAssociatedObject class]];
} else {
bundle = [NSBundle mainBundle];
}
data->app_dir = [bundle bundlePath]; // this is good until the autorelease pool releases the bundlePath string.
2016-04-21 15:19:32 +03:00
// 1) If found, call the custom initialization function (xamarin_custom_initialize)
xamarin_custom_initialize_func init = (xamarin_custom_initialize_func) dlsym (RTLD_MAIN_ONLY, "xamarin_app_initialize");
if (init != NULL)
init (data);
#ifdef DYNAMIC_MONO_RUNTIME
// 2) (If not embedding Mono) Search for the system Mono in the following directories:
if (!(mono_runtime_prefix = getenv ("MONO_RUNTIME")))
mono_runtime_prefix = DEFAULT_MONO_RUNTIME;
#endif
// 3) Ensure the following environment variables are set: [...]
if (!data->is_relaunch) {
update_environment (data);
if (data->requires_relaunch)
return;
}
data->app_dir = NULL; // Make sure nobody ends up using this.
// 4) Ensure that the maximum number of open files is least 1024.
struct rlimit limit;
if (getrlimit (RLIMIT_NOFILE, &limit) == 0 && limit.rlim_cur < 1024) {
limit.rlim_cur = MIN (limit.rlim_max, 1024);
setrlimit (RLIMIT_NOFILE, &limit);
}
NSDictionary *plist = [[NSBundle mainBundle] infoDictionary];
Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. (#4695) * Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. I've verified that we fail at launch of running on 5.12, while 5.14 works fine (to launch at least), so the minimum system mono version is _at least_ 5.14. Fixes https://github.com/xamarin/xamarin-macios/issues/4120. * [mmp] Load mono's version file instead of using pkg-config to get mono's version. pkg-config will only get three parts of the version, while the version file has all four parts. This is important, since we're now verifying the four parts of the version file, and without loading those four from the system, we'll fail builds like this: error MM0001: This version of Xamarin.Mac requires Mono 5.14.0.136 (the current Mono version is 5.14.0). because the three part version's fourth number is assumed to be 0. * Only verify mono runtime version when running with system/dynamic mono. There should be no need to verify the mono runtime version when embedding mono: * If it's a mono we're shipping, something very bad happened in our build/package for it to be an invalid mono. * If it's a system mono that's being embedded, then we verify in mmp at build time. In the first scenario (a mono we're shipping), the problem is that the mono we've built does not report back the full version number (with four parts) [1], which means we'll fail any check whose requirements are identical for the first three parts, and non-zero for the last. [1] The fourth part of the version number is created/calculated when packaging mono, and we're not packaging it.
2018-08-29 15:28:56 +03:00
#ifdef DYNAMIC_MONO_RUNTIME
// 5) Verify the minimum Mono version. The minimum mono version is specified in: [...]
2016-04-21 15:19:32 +03:00
NSString *minVersion = NULL;
if (plist != NULL) {
minVersion = (NSString *) [plist objectForKey:@"MonoMinimumVersion"];
if (minVersion == NULL)
minVersion = (NSString *) [plist objectForKey:@"MonoMinVersion"];
} else {
fprintf (stderr, PRODUCT ": Could not load Info.plist from the bundle.");
}
if (!minVersion) {
// This must be kept in sync with mmp's minimum mono version (in driver.cs)
Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. (#4695) * Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. I've verified that we fail at launch of running on 5.12, while 5.14 works fine (to launch at least), so the minimum system mono version is _at least_ 5.14. Fixes https://github.com/xamarin/xamarin-macios/issues/4120. * [mmp] Load mono's version file instead of using pkg-config to get mono's version. pkg-config will only get three parts of the version, while the version file has all four parts. This is important, since we're now verifying the four parts of the version file, and without loading those four from the system, we'll fail builds like this: error MM0001: This version of Xamarin.Mac requires Mono 5.14.0.136 (the current Mono version is 5.14.0). because the three part version's fourth number is assumed to be 0. * Only verify mono runtime version when running with system/dynamic mono. There should be no need to verify the mono runtime version when embedding mono: * If it's a mono we're shipping, something very bad happened in our build/package for it to be an invalid mono. * If it's a system mono that's being embedded, then we verify in mmp at build time. In the first scenario (a mono we're shipping), the problem is that the mono we've built does not report back the full version number (with four parts) [1], which means we'll fail any check whose requirements are identical for the first three parts, and non-zero for the last. [1] The fourth part of the version number is created/calculated when packaging mono, and we're not packaging it.
2018-08-29 15:28:56 +03:00
minVersion = @MIN_XM_MONO_VERSION;
2016-04-21 15:19:32 +03:00
}
char *mono_version;
const char *err = xamarin_initialize_dynamic_runtime (mono_runtime_prefix);
if (err) {
mono_version = xamarin_get_mono_runtime_build_info ();
if (mono_version && !check_mono_version (mono_version, [minVersion UTF8String])) {
exit_with_message ([[NSString stringWithFormat:@"This application requires the Mono framework version %@ or newer.", minVersion] UTF8String], data->basename, true);
} else {
exit_with_message (err, data->basename, true);
}
}
mono_version = mono_get_runtime_build_info ();
if (!check_mono_version (mono_version, [minVersion UTF8String]))
exit_with_message ([[NSString stringWithFormat:@"This application requires the Mono framework version %@ or newer.", minVersion] UTF8String], data->basename, true);
Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. (#4695) * Store the minimum mono version for Xamarin.Mac in one place only (Make.config) and bump it to 5.14. Fixes #4120. I've verified that we fail at launch of running on 5.12, while 5.14 works fine (to launch at least), so the minimum system mono version is _at least_ 5.14. Fixes https://github.com/xamarin/xamarin-macios/issues/4120. * [mmp] Load mono's version file instead of using pkg-config to get mono's version. pkg-config will only get three parts of the version, while the version file has all four parts. This is important, since we're now verifying the four parts of the version file, and without loading those four from the system, we'll fail builds like this: error MM0001: This version of Xamarin.Mac requires Mono 5.14.0.136 (the current Mono version is 5.14.0). because the three part version's fourth number is assumed to be 0. * Only verify mono runtime version when running with system/dynamic mono. There should be no need to verify the mono runtime version when embedding mono: * If it's a mono we're shipping, something very bad happened in our build/package for it to be an invalid mono. * If it's a system mono that's being embedded, then we verify in mmp at build time. In the first scenario (a mono we're shipping), the problem is that the mono we've built does not report back the full version number (with four parts) [1], which means we'll fail any check whose requirements are identical for the first three parts, and non-zero for the last. [1] The fourth part of the version number is created/calculated when packaging mono, and we're not packaging it.
2018-08-29 15:28:56 +03:00
#endif
2016-04-21 15:19:32 +03:00
// 6) Find the executable. The name is: [...]
if (data->launch_mode == XamarinLaunchModeApp) {
NSString *exeName = NULL;
NSString *exePath;
if (plist != NULL)
exeName = (NSString *) [plist objectForKey:@"MonoBundleExecutable"];
else
fprintf (stderr, PRODUCT ": Could not find Info.plist in the bundle.\n");
2016-04-21 15:19:32 +03:00
if (exeName == NULL)
exeName = [[NSString stringWithUTF8String: data->basename] stringByAppendingString: @".exe"];
if (mkbundle) {
exePath = exeName;
} else {
exePath = [[[NSString stringWithUTF8String: xamarin_get_bundle_path ()] stringByAppendingString: @"/"] stringByAppendingString: exeName];
if (!xamarin_file_exists ([exePath UTF8String]))
exit_with_message ([[NSString stringWithFormat:@"Could not find the executable '%@'\n\nFull path: %@", exeName, exePath] UTF8String], data->basename, false);
}
xamarin_entry_assembly_path = strdup ([exePath UTF8String]);
} else {
NSString *dllName = [[NSString stringWithUTF8String: data->basename] stringByAppendingString: @".dll"];
NSString *dllPath = [[[NSString stringWithUTF8String: xamarin_get_bundle_path ()] stringByAppendingString: @"/"] stringByAppendingString: dllName];
if (!xamarin_file_exists ([dllPath UTF8String]))
exit_with_message ([[NSString stringWithFormat:@"Could not find the extension library '%@'\n\nFull path: %@", dllName, dllPath] UTF8String], data->basename, false);
xamarin_entry_assembly_path = strdup ([dllPath UTF8String]);
}
2016-04-21 15:19:32 +03:00
// 7a) [If not embedding] Don't parse any config files, leave it to the Mono runtime to load the defaults.
2016-04-21 15:19:32 +03:00
// 7b) [If embedding] Parse $appdir/Contents/MonoBundle/machine.config and $appdir/Contents/MonoBundle/config
if (!mkbundle) {
NSString *config_path = nil;
NSString *machine_config_path = nil;
NSError *error = nil;
#ifndef DYNAMIC_MONO_RUNTIME
2016-04-21 15:19:32 +03:00
config_path = [[NSString stringWithUTF8String: xamarin_get_bundle_path ()] stringByAppendingPathComponent: @"config"];
machine_config_path = [[NSString stringWithUTF8String: xamarin_get_bundle_path ()] stringByAppendingPathComponent: @"machine.config"];
mono_set_dirs (xamarin_get_bundle_path (), xamarin_get_bundle_path ());
#else
mono_set_dirs (NULL, NULL);
#endif
if (machine_config_path != nil) {
NSString *config = [NSString stringWithContentsOfFile: machine_config_path encoding: NSUTF8StringEncoding error: &error];
if (config != nil) {
mono_register_machine_config (strdup ([config UTF8String]));
} else {
// fprintf (stderr, PRODUCT ": Could not load machine.config: %s\n", [machine_config_path UTF8String]);
}
}
if (config_path != nil) {
NSString *config = [NSString stringWithContentsOfFile: config_path encoding: NSUTF8StringEncoding error: &error];
if (config != nil) {
mono_config_parse_memory ((char *) [config UTF8String]);
} else {
// fprintf (stderr, PRODUCT ": Could not load config: %s\n", [config_path UTF8String]);
}
}
}
/* other non-documented stuff... */
xamarin_initialize_cocoa_threads (NULL);
2016-04-21 15:19:32 +03:00
init_logdir ();
mono_set_signal_chaining (TRUE);
mono_set_crash_chaining (TRUE);
2016-04-21 15:19:32 +03:00
}
#define __XAMARIN_MAC_RELAUNCH_APP__ "__XAMARIN_MAC_RELAUNCH_APP__"
static void
run_application_init (xamarin_initialize_data *data)
{
if (!xamarin_file_exists (xamarin_entry_assembly_path))
exit_with_message ([[NSString stringWithFormat:@"Could not find the assembly '%s'", xamarin_entry_assembly_path] UTF8String], data->basename, false);
// Make sure any output from mono isn't lost when launching extensions,
// etc, by installing the log callbacks early (xamarin_initialize will
// also do this, but if something goes wrong before we reach
// xamarin_initialize when running as an extension, the output will be
// lost).
xamarin_install_log_callbacks ();
mono_jit_init (xamarin_entry_assembly_path);
MonoAssembly *assembly = xamarin_open_assembly ("Xamarin.Mac.dll");
if (!assembly)
xamarin_assertion_message ("Failed to load %s.", "Xamarin.Mac.dll");
MonoImage *image = mono_assembly_get_image (assembly);
MonoClass *app_class = mono_class_from_name (image, "AppKit", "NSApplication");
if (!app_class)
xamarin_assertion_message ("Fatal error: failed to load the NSApplication class");
MonoMethod *initialize = mono_class_get_method_from_name (app_class, "Init", 0);
if (!initialize)
xamarin_assertion_message ("Fatal error: failed to load the NSApplication.Init method");
mono_runtime_invoke (initialize, NULL, NULL, NULL);
}
int xamarin_main (int argc, char **argv, enum XamarinLaunchMode launch_mode)
2016-04-21 15:19:32 +03:00
{
xamarin_initialize_data data = { 0 };
if (getcwd (original_working_directory_path, sizeof (original_working_directory_path)) == NULL)
original_working_directory_path [0] = '\0';
@autoreleasepool {
data.size = sizeof (data);
data.argc = argc;
data.argv = argv;
data.launch_mode = launch_mode;
2016-04-21 15:19:32 +03:00
// basename = Path.GetFileName (argv [0])
if (!(data.basename = strrchr (argv [0], '/'))) {
data.basename = argv [0];
} else {
data.basename++;
}
data.is_relaunch = getenv (__XAMARIN_MAC_RELAUNCH_APP__) != NULL;
if (data.is_relaunch)
unsetenv (__XAMARIN_MAC_RELAUNCH_APP__);
app_initialize (&data);
2016-04-21 15:19:32 +03:00
if (data.exit)
return data.exit_code;
if (data.requires_relaunch) {
setenv (__XAMARIN_MAC_RELAUNCH_APP__, "1", 1);
return execv (argv [0], argv);
}
}
int rv = 0;
@autoreleasepool {
int env_argc = 0;
char **env_argv = get_mono_env_options (&env_argc);
int new_argc = env_argc + 2 /* --debug executable */ + argc ;
if (xamarin_mac_hybrid_aot)
new_argc += 1;
[Do not merge yet] Update to mono 2017-04 branch (#1960) * Update to mono 2017-04 branch * Patch from Zoltan to fix build error with CppSharp.CppParser.dll * Include new linker files in Makefile, based on mareks commit * [msbuild] Fix running bgen for Xamarin.Mac. bgen must be executed with the system mono, not bmac-mobile-mono, and without the MONO_PATH variable set. * System.Data tests should act as if they are running on mobile profile * Add --runtime=mobile to mono flags in Modern * Move runtime launcher options up * System.Data tests should use Mobile profile (mac fix) * Bump 2017-04 to pick up AOT and assembly resolution fixes * Build fixes for netstandard.dll and System.Drawing.Primitives.dll The new handling went in with https://github.com/mono/mono/pull/4501. I also noticed that WatchOS was missing a target for System.Drawing.Primitives.dll, so I added that. * Add netstandard.dll to 2.1/Facades and System.Drawing.Primitives.dll to WatchOS * Fix 2.1/Facades/netstandard.dll build * Fix the netstandard targets * Bump mono to latest 2017-04 commit * [xharness] Fix adding defines to csproj by correctly detecting existing defines. * Bump mono to latest 2017-04 commit * [mtouch] Update csproj with new files. * [mtouch] Improve reporting for MarkExceptions from the linker. * Bump mono to latest 2017-04 commit * Bump mono to pick up latest 2017-04 branch commit (Fixes #55436) Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=55436 * Add a missing Makefile dependency * Chris Hamons patch to apply --runtime=mobile as necessary at AOT time (It is currently being applied for some configurations at runtime only) * Bump system mono * Bump mono for assembly loader changes * Bump system mono * Update assemblies list as some where moved to facades https://github.com/mono/mono/commit/6ca5ec442b494bed8cfb44258c1c73c091ba3122 https://github.com/mono/mono/commit/c38e4d9220b16488e6f8f9e1f05aed4a8af16e62 * Bump mono to latest 2017-04 commit * Add another new facade * Bump mono to tip of 2017-04. * Bump mono to tip of 2017-04. * [tests][mtouch] Adjust tests to cope with fewer assemblies being included in linked apps. Fixes #56307 and #56308. System.dll is now completely linked away unless the app actually uses any System.dll API. This is the change that caused this to change: https://github.com/mono/mono/commit/4960d5d2a28a08476ee4239e1746f04afce41c13 Previously the following types would always be kept by the linker: ``` $ monodis --typedef System.dll Typedef Table 1: (null) (flist=1, mlist=1, flags=0x0, extends=0x0) 2: ObjCRuntime.INativeObject (flist=1, mlist=1, flags=0xa0, extends=0x0) 3: Mono.Net.CFObject (flist=1, mlist=2, flags=0x100000, extends=0x5) 4: Mono.Net.CFArray (flist=4, mlist=19, flags=0x100, extends=0xc) 5: Mono.Net.CFNumber (flist=5, mlist=32, flags=0x100100, extends=0xc) 6: Mono.Net.CFRange (flist=5, mlist=41, flags=0x100108, extends=0x25) 7: Mono.Net.CFString (flist=7, mlist=42, flags=0x100100, extends=0xc) 8: Mono.Net.CFData (flist=8, mlist=53, flags=0x100100, extends=0xc) 9: Mono.Net.CFDictionary (flist=8, mlist=63, flags=0x0, extends=0xc) 10: Mono.Net.CFMutableDictionary (flist=10, mlist=75, flags=0x100100, extends=0x24) 11: Mono.Net.CFUrl (flist=10, mlist=80, flags=0x100100, extends=0xc) 12: Mono.Net.CFRunLoop (flist=10, mlist=83, flags=0x100100, extends=0xc) 13: Mono.Net.CFBoolean (flist=10, mlist=94, flags=0x100, extends=0x5) 14: Mono.AppleTls.SecCertificate (flist=13, mlist=106, flags=0x100100, extends=0x5) 15: Mono.AppleTls.SecIdentity (flist=14, mlist=122, flags=0x100, extends=0x5) 16: Mono.AppleTls.SecIdentity/ImportOptions (flist=19, mlist=134, flags=0x100105, extends=0x5) 17: Mono.AppleTls.SecKey (flist=19, mlist=134, flags=0x100100, extends=0x5) 18: Mono.AppleTls.SecStatusCode (flist=21, mlist=141, flags=0x100, extends=0x69) 19: Mono.AppleTls.SecTrustResult (flist=395, mlist=141, flags=0x100, extends=0x69) 20: Mono.AppleTls.SecImportExport (flist=404, mlist=141, flags=0x100100, extends=0x5) 21: Mono.AppleTls.SecImportExport/<>c (flist=404, mlist=144, flags=0x102103, extends=0x5) 22: Mono.AppleTls.SecPolicy (flist=406, mlist=147, flags=0x100100, extends=0x5) 23: Mono.AppleTls.SecTrust (flist=407, mlist=154, flags=0x100100, extends=0x5) 24: System.Security.Cryptography.OidGroup (flist=408, mlist=174, flags=0x101, extends=0x69) 25: System.Security.Cryptography.Oid (flist=420, mlist=174, flags=0x100101, extends=0x5) 26: System.Security.Cryptography.CAPI (flist=423, mlist=176, flags=0x100180, extends=0x5) 27: System.Security.Cryptography.AsnEncodedData (flist=423, mlist=178, flags=0x100101, extends=0x5) 28: System.Security.Cryptography.X509Certificates.X509Utils (flist=424, mlist=179, flags=0x100100, extends=0x5) 29: System.Security.Cryptography.X509Certificates.PublicKey (flist=424, mlist=181, flags=0x100101, extends=0x5) 30: System.Security.Cryptography.X509Certificates.X509Certificate2 (flist=429, mlist=188, flags=0x102101, extends=0x51) 31: System.Security.Cryptography.X509Certificates.X509Certificate2Impl (flist=431, mlist=204, flags=0x100080, extends=0x55) 32: System.Security.Cryptography.X509Certificates.X509CertificateCollection (flist=431, mlist=209, flags=0x102101, extends=0x6d) 33: System.Security.Cryptography.X509Certificates.X509CertificateCollection/X509CertificateEnumerator (flist=431, mlist=212, flags=0x100102, extends=0x5) 34: System.Security.Cryptography.X509Certificates.X509Helper2 (flist=432, mlist=217, flags=0x100180, extends=0x5) 35: <PrivateImplementationDetails> (flist=432, mlist=218, flags=0x100, extends=0x5) 36: <PrivateImplementationDetails>/__StaticArrayInitTypeSize=9 (flist=433, mlist=219, flags=0x113, extends=0x25) ``` Some of the above types from System.dll implemented ObjCRuntime.INativeObject (from System.dll), which our linker detected as implementing ObjCRuntime.INativeObject (from Xamarin.iOS.dll), so these types were treated as custom NSObject subclasses, and the MarkNSObjects linker step would mark them (which would in turn cause all the other types in the list to be marked). With that change, these types now implement ObjCRuntimeInternal.INativeObject, and the linker does not treat them as custom NSObject subclasses anymore. I think the new behavior is correct: these types do not actually inherit from the real NSObject/INativeObject, so the linker should not treat them as such. This may run into different bugs because the linker might now remove more stuff than before, but that would be a different issue. This means that the fix is to modify these tests accordingly. https://bugzilla.xamarin.com/show_bug.cgi?id=56307 https://bugzilla.xamarin.com/show_bug.cgi?id=56308 * Bump mono to latest. * Fix merge conflict that was missed * [mtouch] Renumber new error which clashes with an existing error number in master.
2017-05-29 19:39:29 +03:00
if (xamarin_mac_modern)
new_argc += 1;
2016-04-21 15:19:32 +03:00
char **new_argv = (char **) malloc (sizeof (char *) * (new_argc + 1 /* null terminated */));
const char **ptr = (const char **) new_argv;
// binary
*ptr++ = argv [0];
// inject MONO_ENV_OPTIONS
for (int i = 0; i < env_argc; i++)
*ptr++ = env_argv [i];
if (xamarin_debug_mode) {
*ptr++ = "--debug";
} else {
new_argc--;
}
if (xamarin_mac_hybrid_aot)
*ptr++ = "--hybrid-aot";
[Do not merge yet] Update to mono 2017-04 branch (#1960) * Update to mono 2017-04 branch * Patch from Zoltan to fix build error with CppSharp.CppParser.dll * Include new linker files in Makefile, based on mareks commit * [msbuild] Fix running bgen for Xamarin.Mac. bgen must be executed with the system mono, not bmac-mobile-mono, and without the MONO_PATH variable set. * System.Data tests should act as if they are running on mobile profile * Add --runtime=mobile to mono flags in Modern * Move runtime launcher options up * System.Data tests should use Mobile profile (mac fix) * Bump 2017-04 to pick up AOT and assembly resolution fixes * Build fixes for netstandard.dll and System.Drawing.Primitives.dll The new handling went in with https://github.com/mono/mono/pull/4501. I also noticed that WatchOS was missing a target for System.Drawing.Primitives.dll, so I added that. * Add netstandard.dll to 2.1/Facades and System.Drawing.Primitives.dll to WatchOS * Fix 2.1/Facades/netstandard.dll build * Fix the netstandard targets * Bump mono to latest 2017-04 commit * [xharness] Fix adding defines to csproj by correctly detecting existing defines. * Bump mono to latest 2017-04 commit * [mtouch] Update csproj with new files. * [mtouch] Improve reporting for MarkExceptions from the linker. * Bump mono to latest 2017-04 commit * Bump mono to pick up latest 2017-04 branch commit (Fixes #55436) Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=55436 * Add a missing Makefile dependency * Chris Hamons patch to apply --runtime=mobile as necessary at AOT time (It is currently being applied for some configurations at runtime only) * Bump system mono * Bump mono for assembly loader changes * Bump system mono * Update assemblies list as some where moved to facades https://github.com/mono/mono/commit/6ca5ec442b494bed8cfb44258c1c73c091ba3122 https://github.com/mono/mono/commit/c38e4d9220b16488e6f8f9e1f05aed4a8af16e62 * Bump mono to latest 2017-04 commit * Add another new facade * Bump mono to tip of 2017-04. * Bump mono to tip of 2017-04. * [tests][mtouch] Adjust tests to cope with fewer assemblies being included in linked apps. Fixes #56307 and #56308. System.dll is now completely linked away unless the app actually uses any System.dll API. This is the change that caused this to change: https://github.com/mono/mono/commit/4960d5d2a28a08476ee4239e1746f04afce41c13 Previously the following types would always be kept by the linker: ``` $ monodis --typedef System.dll Typedef Table 1: (null) (flist=1, mlist=1, flags=0x0, extends=0x0) 2: ObjCRuntime.INativeObject (flist=1, mlist=1, flags=0xa0, extends=0x0) 3: Mono.Net.CFObject (flist=1, mlist=2, flags=0x100000, extends=0x5) 4: Mono.Net.CFArray (flist=4, mlist=19, flags=0x100, extends=0xc) 5: Mono.Net.CFNumber (flist=5, mlist=32, flags=0x100100, extends=0xc) 6: Mono.Net.CFRange (flist=5, mlist=41, flags=0x100108, extends=0x25) 7: Mono.Net.CFString (flist=7, mlist=42, flags=0x100100, extends=0xc) 8: Mono.Net.CFData (flist=8, mlist=53, flags=0x100100, extends=0xc) 9: Mono.Net.CFDictionary (flist=8, mlist=63, flags=0x0, extends=0xc) 10: Mono.Net.CFMutableDictionary (flist=10, mlist=75, flags=0x100100, extends=0x24) 11: Mono.Net.CFUrl (flist=10, mlist=80, flags=0x100100, extends=0xc) 12: Mono.Net.CFRunLoop (flist=10, mlist=83, flags=0x100100, extends=0xc) 13: Mono.Net.CFBoolean (flist=10, mlist=94, flags=0x100, extends=0x5) 14: Mono.AppleTls.SecCertificate (flist=13, mlist=106, flags=0x100100, extends=0x5) 15: Mono.AppleTls.SecIdentity (flist=14, mlist=122, flags=0x100, extends=0x5) 16: Mono.AppleTls.SecIdentity/ImportOptions (flist=19, mlist=134, flags=0x100105, extends=0x5) 17: Mono.AppleTls.SecKey (flist=19, mlist=134, flags=0x100100, extends=0x5) 18: Mono.AppleTls.SecStatusCode (flist=21, mlist=141, flags=0x100, extends=0x69) 19: Mono.AppleTls.SecTrustResult (flist=395, mlist=141, flags=0x100, extends=0x69) 20: Mono.AppleTls.SecImportExport (flist=404, mlist=141, flags=0x100100, extends=0x5) 21: Mono.AppleTls.SecImportExport/<>c (flist=404, mlist=144, flags=0x102103, extends=0x5) 22: Mono.AppleTls.SecPolicy (flist=406, mlist=147, flags=0x100100, extends=0x5) 23: Mono.AppleTls.SecTrust (flist=407, mlist=154, flags=0x100100, extends=0x5) 24: System.Security.Cryptography.OidGroup (flist=408, mlist=174, flags=0x101, extends=0x69) 25: System.Security.Cryptography.Oid (flist=420, mlist=174, flags=0x100101, extends=0x5) 26: System.Security.Cryptography.CAPI (flist=423, mlist=176, flags=0x100180, extends=0x5) 27: System.Security.Cryptography.AsnEncodedData (flist=423, mlist=178, flags=0x100101, extends=0x5) 28: System.Security.Cryptography.X509Certificates.X509Utils (flist=424, mlist=179, flags=0x100100, extends=0x5) 29: System.Security.Cryptography.X509Certificates.PublicKey (flist=424, mlist=181, flags=0x100101, extends=0x5) 30: System.Security.Cryptography.X509Certificates.X509Certificate2 (flist=429, mlist=188, flags=0x102101, extends=0x51) 31: System.Security.Cryptography.X509Certificates.X509Certificate2Impl (flist=431, mlist=204, flags=0x100080, extends=0x55) 32: System.Security.Cryptography.X509Certificates.X509CertificateCollection (flist=431, mlist=209, flags=0x102101, extends=0x6d) 33: System.Security.Cryptography.X509Certificates.X509CertificateCollection/X509CertificateEnumerator (flist=431, mlist=212, flags=0x100102, extends=0x5) 34: System.Security.Cryptography.X509Certificates.X509Helper2 (flist=432, mlist=217, flags=0x100180, extends=0x5) 35: <PrivateImplementationDetails> (flist=432, mlist=218, flags=0x100, extends=0x5) 36: <PrivateImplementationDetails>/__StaticArrayInitTypeSize=9 (flist=433, mlist=219, flags=0x113, extends=0x25) ``` Some of the above types from System.dll implemented ObjCRuntime.INativeObject (from System.dll), which our linker detected as implementing ObjCRuntime.INativeObject (from Xamarin.iOS.dll), so these types were treated as custom NSObject subclasses, and the MarkNSObjects linker step would mark them (which would in turn cause all the other types in the list to be marked). With that change, these types now implement ObjCRuntimeInternal.INativeObject, and the linker does not treat them as custom NSObject subclasses anymore. I think the new behavior is correct: these types do not actually inherit from the real NSObject/INativeObject, so the linker should not treat them as such. This may run into different bugs because the linker might now remove more stuff than before, but that would be a different issue. This means that the fix is to modify these tests accordingly. https://bugzilla.xamarin.com/show_bug.cgi?id=56307 https://bugzilla.xamarin.com/show_bug.cgi?id=56308 * Bump mono to latest. * Fix merge conflict that was missed * [mtouch] Renumber new error which clashes with an existing error number in master.
2017-05-29 19:39:29 +03:00
if (xamarin_mac_modern)
*ptr++ = "--runtime=mobile";
// executable assembly
*ptr++ = xamarin_entry_assembly_path;
2016-04-21 15:19:32 +03:00
// the rest
for (int i = 1; i < argc; i++)
*ptr++ = argv [i];
*ptr = NULL;
switch (launch_mode) {
case XamarinLaunchModeExtension: {
run_application_init (&data);
void * libExtensionHandle = dlopen ("/usr/lib/libextension.dylib", RTLD_LAZY);
if (libExtensionHandle == nil)
exit_with_message ("Unable to load libextension.dylib", data.basename, false);
typedef int (*extension_main)(int argc, char * argv[]);
extension_main extensionMain = (extension_main) dlsym (libExtensionHandle, "NSExtensionMain");
if (extensionMain == nil)
exit_with_message ("Unable to load NSExtensionMain", data.basename, false);
rv = (*extensionMain) (new_argc, new_argv);
dlclose (libExtensionHandle);
break;
}
case XamarinLaunchModeApp:
rv = mono_main (new_argc, new_argv);
break;
case XamarinLaunchModeEmbedded:
run_application_init (&data);
break;
default:
xamarin_assertion_message ("Invalid launch mode: %i.", launch_mode);
break;
}
2016-04-21 15:19:32 +03:00
free (new_argv);
free (env_argv);
2016-04-21 15:19:32 +03:00
}
return rv;
}
int main (int argc, char **argv)
{
return xamarin_main (argc, argv, XamarinLaunchModeApp);
}
int xamarin_mac_extension_main (int argc, char **argv)
{
return xamarin_main (argc, argv, XamarinLaunchModeExtension);
}