1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
| | diff --git a/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/AssemblyResolver.cs b/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/AssemblyResolver.cs
index 5e0ec480956..9daf9d6920b 100644
--- a/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/AssemblyResolver.cs
+++ b/mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/AssemblyResolver.cs
@@ -67,54 +67,56 @@ public void ResetSearchLogger ()
search_log.Clear ();
}
- string GetGacPath ()
+ string[] GetGacPaths ()
{
// NOTE: code from mcs/tools/gacutil/driver.cs
- PropertyInfo gac = typeof (System.Environment).GetProperty ("GacPath", BindingFlags.Static | BindingFlags.NonPublic);
+ PropertyInfo gacs = typeof (System.Environment).GetProperty ("GacPaths", BindingFlags.Static | BindingFlags.NonPublic);
- if (gac == null)
+ if (gacs == null)
return null;
- MethodInfo get_gac = gac.GetGetMethod (true);
- return (string) get_gac.Invoke (null, null);
+ MethodInfo get_gacs = gacs.GetGetMethod (true);
+ return (string[]) get_gacs.Invoke (null, null);
}
void GatherGacAssemblies ()
{
- string gac_path = GetGacPath ();
- if (gac_path == null)
- throw new InvalidOperationException ("XBuild must be run on Mono runtime");
- if (!Directory.Exists (gac_path))
- return; // in case mono isn't "installed".
-
- Version version;
- DirectoryInfo version_info, assembly_info;
-
- foreach (string assembly_name in Directory.GetDirectories (gac_path)) {
- assembly_info = new DirectoryInfo (assembly_name);
- foreach (string version_token in Directory.GetDirectories (assembly_name)) {
- foreach (string file in Directory.GetFiles (version_token, "*.dll")) {
- version_info = new DirectoryInfo (version_token);
- version = new Version (version_info.Name.Split (
- new char [] {'_'}, StringSplitOptions.RemoveEmptyEntries) [0]);
-
- Dictionary<Version, string> assembliesByVersion = new Dictionary <Version, string> ();
- if (!gac.TryGetValue (assembly_info.Name, out assembliesByVersion)) {
- assembliesByVersion = new Dictionary <Version, string> ();
- gac.Add (assembly_info.Name, assembliesByVersion);
- }
-
- string found_file;
- if (assembliesByVersion.TryGetValue (version, out found_file) &&
- File.GetLastWriteTime (file) <= File.GetLastWriteTime (found_file))
- // Duplicate found, take the newer file
- continue;
-
- assembliesByVersion [version] = file;
- }
- }
- }
- }
+ string[] gac_paths = GetGacPaths ();
+ if (gac_paths == null)
+ throw new InvalidOperationException ("XBuild must be run on Mono runtime");
+ if (gac_paths.Length == 0 || !Directory.Exists (gac_paths[0]))
+ return; // in case mono isn't "installed".
+
+ Version version;
+ DirectoryInfo version_info, assembly_info;
+
+ foreach (string gac_path in gac_paths) {
+ foreach (string assembly_name in Directory.GetDirectories (gac_path)) {
+ assembly_info = new DirectoryInfo (assembly_name);
+ foreach (string version_token in Directory.GetDirectories (assembly_name)) {
+ foreach (string file in Directory.GetFiles (version_token, "*.dll")) {
+ version_info = new DirectoryInfo (version_token);
+ version = new Version (version_info.Name.Split (
+ new char [] {'_'}, StringSplitOptions.RemoveEmptyEntries) [0]);
+
+ Dictionary<Version, string> assembliesByVersion = new Dictionary <Version, string> ();
+ if (!gac.TryGetValue (assembly_info.Name, out assembliesByVersion)) {
+ assembliesByVersion = new Dictionary <Version, string> ();
+ gac.Add (assembly_info.Name, assembliesByVersion);
+ }
+
+ string found_file;
+ if (assembliesByVersion.TryGetValue (version, out found_file) &&
+ File.GetLastWriteTime (file) <= File.GetLastWriteTime (found_file))
+ // Duplicate found, take the newer file
+ continue;
+
+ assembliesByVersion [version] = file;
+ }
+ }
+ }
+ }
+ }
public ResolvedReference FindInTargetFramework (ITaskItem reference, string framework_dir, bool specific_version)
{
diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs
index fd936ab21a4..b5a5c77c1a3 100644
--- a/mcs/class/corlib/System/Environment.cs
+++ b/mcs/class/corlib/System/Environment.cs
@@ -984,9 +984,18 @@ private static string GacPath {
return Path.Combine (Path.Combine (internalGetGacPath (), "mono"), "gac");
}
}
+
+ private static string[] GacPaths {
+ get {
+ return internalGetGacPaths ();
+ }
+ }
#pragma warning restore 169
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static string internalGetGacPath ();
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal extern static string [] internalGetGacPaths ();
#endif
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static string [] GetLogicalDrivesInternal ();
diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c
index 8c71ad0eb95..759d5aefbcf 100644
--- a/mono/metadata/assembly.c
+++ b/mono/metadata/assembly.c
@@ -854,6 +854,11 @@ mono_assembly_getrootdir (void)
return default_path [0];
}
+char **mono_assembly_get_extra_gac_paths()
+{
+ return extra_gac_paths;
+}
+
/**
* mono_native_getrootdir:
*
diff --git a/mono/metadata/assembly.h b/mono/metadata/assembly.h
index e9c02ee26f5..e5f060e8238 100644
--- a/mono/metadata/assembly.h
+++ b/mono/metadata/assembly.h
@@ -50,6 +50,7 @@ MONO_API MONO_RT_EXTERNAL_ONLY MonoImage* mono_assembly_load_module (MonoAsse
MONO_API void mono_assembly_close (MonoAssembly *assembly);
MONO_API void mono_assembly_setrootdir (const char *root_dir);
MONO_API MONO_CONST_RETURN char *mono_assembly_getrootdir (void);
+MONO_API char **mono_assembly_get_extra_gac_paths (void);
MONO_API char *mono_native_getrootdir (void);
MONO_API void mono_assembly_foreach (MonoFunc func, void* user_data);
MONO_API void mono_assembly_set_main (MonoAssembly *assembly);
diff --git a/mono/metadata/icall-decl.h b/mono/metadata/icall-decl.h
index a77fcf38598..3f0f1758ec2 100644
--- a/mono/metadata/icall-decl.h
+++ b/mono/metadata/icall-decl.h
@@ -152,6 +152,7 @@ ICALL_EXPORT gint32 ves_icall_System_Environment_get_TickCount (void);
#if ENABLE_NETCORE
ICALL_EXPORT gint64 ves_icall_System_Environment_get_TickCount64 (void);
#endif
+ICALL_EXPORT MonoArray *ves_icall_System_Environment_GetGacPaths (void);
ICALL_EXPORT gint64 ves_icall_System_DateTime_GetSystemTimeAsFileTime (void);
ICALL_EXPORT gint64 ves_icall_System_Diagnostics_Process_GetProcessData (int, gint32, MonoProcessError*);
ICALL_EXPORT gint64 ves_icall_System_Diagnostics_Stopwatch_GetTimestamp (void);
diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h
index 0a44729674b..59c803ba488 100644
--- a/mono/metadata/icall-def.h
+++ b/mono/metadata/icall-def.h
@@ -327,6 +327,7 @@ HANDLES(ENV_16b, "get_bundled_machine_config", ves_icall_System_Environment_get_
HANDLES(ENV_16m, "internalBroadcastSettingChange", ves_icall_System_Environment_BroadcastSettingChange, void, 0, ())
HANDLES(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Environment_GetEnvironmentVariable_native, MonoString, 1, (const_char_ptr))
HANDLES(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath, MonoString, 0, ())
+NOHANDLES(ICALL(ENV_18_1, "internalGetGacPaths", ves_icall_System_Environment_GetGacPaths))
HANDLES(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome, MonoString, 0, ())
NOHANDLES(ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set))
ICALL_TYPE(GC, "System.GC", GC_10)
diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c
index 6d16b9c3540..1e592c30e27 100644
--- a/mono/metadata/icall.c
+++ b/mono/metadata/icall.c
@@ -7781,6 +7781,56 @@ ves_icall_System_Environment_GetGacPath (MonoError *error)
}
#endif
+ICALL_EXPORT MonoArray *
+ves_icall_System_Environment_GetGacPaths ()
+{
+ char **extra_gac_paths = mono_assembly_get_extra_gac_paths();
+ const char *rootdir = mono_assembly_getrootdir ();
+ char **e;
+ int n;
+ MonoDomain *domain;
+ MonoArray *out;
+ MonoString *str;
+ gchar *tmp;
+ MonoError error;
+ n = 0;
+ if (rootdir) n++;
+ if (extra_gac_paths) {
+ for (e = extra_gac_paths; *e != 0; e++);
+ n += (e - extra_gac_paths);
+ }
+
+ domain = mono_domain_get ();
+ out = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
+
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ n = 0;
+ if (rootdir) {
+ tmp = g_build_path (G_DIR_SEPARATOR_S, rootdir, "mono", "gac", NULL);
+ str = mono_string_new_checked (domain, tmp, &error);
+ g_free (tmp);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+ mono_array_setref_internal (out, n, str);
+ n++;
+ }
+ if (extra_gac_paths) {
+ for (e = extra_gac_paths; *e != 0; e++) {
+ tmp = g_build_path (G_DIR_SEPARATOR_S, *e, "lib", "mono", "gac", NULL);
+ str = mono_string_new_checked (domain, tmp, &error);
+ g_free (tmp);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+ mono_array_setref_internal (out, n, str);
+ n++;
+ }
+ }
+
+ return out;
+}
+
#ifndef HOST_WIN32
static inline MonoStringHandle
mono_icall_get_windows_folder_path (int folder, MonoError *error)
|