Imported Upstream version 4.4.0.182

Former-commit-id: ea38b2115ac3af9a394fe6cddf2be2acd11bc002
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-06-14 09:39:34 +00:00
parent ee13743634
commit 180e8b1935
125 changed files with 1658 additions and 521 deletions

View File

@ -7,6 +7,11 @@
// Miguel de Icaza
//
// (C) Novell, Inc 2004
// (C) 2016 Xamarin Inc
//
// Missing features:
// * Add support for packaging native libraries, extracting at runtime and setting the library path.
// * Implement --list-targets lists all the available remote targets
//
using System;
using System.Diagnostics;
@ -17,8 +22,9 @@ using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text;
using IKVM.Reflection;
using System.Linq;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
class MakeBundle {
@ -40,6 +46,12 @@ class MakeBundle {
static bool skip_scan;
static string ctor_func;
static bool quiet;
static string cross_target = null;
static string fetch_target = null;
static bool custom_mode = true;
static string embedded_options = null;
static string runtime = null;
static string target_server = "https://download.mono-project.com/runtimes/raw/";
static int Main (string [] args)
{
@ -55,10 +67,56 @@ class MakeBundle {
Help ();
return 1;
case "--simple":
custom_mode = false;
autodeps = true;
break;
case "--custom":
custom_mode = true;
break;
case "-c":
compile_only = true;
break;
case "--local-targets":
CommandLocalTargets ();
return 0;
case "--cross":
if (i+1 == top){
Help ();
return 1;
}
custom_mode = false;
autodeps = true;
cross_target = args [++i];
break;
case "--fetch-target":
if (i+1 == top){
Help ();
return 1;
}
fetch_target = args [++i];
break;
case "--list-targets":
var wc = new WebClient ();
var s = wc.DownloadString (new Uri (target_server + "target-list.txt"));
Console.WriteLine ("Cross-compilation targets available:\n" + s);
return 0;
case "--target-server":
if (i+1 == top){
Help ();
return 1;
}
target_server = args [++i];
break;
case "-o":
if (i+1 == top){
Help ();
@ -67,6 +125,20 @@ class MakeBundle {
output = args [++i];
break;
case "--options":
if (i+1 == top){
Help ();
return 1;
}
embedded_options = args [++i];
break;
case "--runtime":
if (i+1 == top){
Help ();
return 1;
}
runtime = args [++i];
break;
case "-oo":
if (i+1 == top){
Help ();
@ -94,6 +166,7 @@ class MakeBundle {
case "--keeptemp":
keeptemp = true;
break;
case "--static":
static_link = true;
if (!quiet) {
@ -193,13 +266,60 @@ class MakeBundle {
foreach (string file in assemblies)
if (!QueueAssembly (files, file))
return 1;
GenerateBundles (files);
//GenerateJitWrapper ();
if (fetch_target != null){
var truntime = Path.Combine (targets_dir, fetch_target, "mono");
Directory.CreateDirectory (Path.GetDirectoryName (truntime));
var wc = new WebClient ();
var uri = new Uri ($"{target_server}{fetch_target}");
try {
wc.DownloadFile (uri, truntime);
} catch {
Console.Error.WriteLine ($"Failure to download the specified runtime from {uri}");
File.Delete (truntime);
return 1;
}
return 0;
}
if (custom_mode)
GenerateBundles (files);
else {
if (cross_target == "default")
runtime = null;
else {
var truntime = Path.Combine (targets_dir, cross_target, "mono");
if (!File.Exists (truntime)){
Console.Error.WriteLine ($"The runtime for the {cross_target} does not exist, use --fetch-target {cross_target} to download first");
return 1;
}
}
GeneratePackage (files);
}
return 0;
}
static string targets_dir = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), ".mono", "targets");
static void CommandLocalTargets ()
{
string [] targets;
Console.WriteLine ("Available targets:");
Console.WriteLine ("\tdefault\t- Current System Mono");
try {
targets = Directory.GetDirectories (targets_dir);
} catch {
return;
}
foreach (var target in targets){
var p = Path.Combine (target, "mono");
if (File.Exists (p))
Console.WriteLine ("\t{0}", Path.GetFileName (target));
}
}
static void WriteSymbol (StreamWriter sw, string name, long size)
{
switch (style){
@ -260,6 +380,138 @@ class MakeBundle {
ts.WriteLine ();
}
class PackageMaker {
Dictionary<string, Tuple<long,int>> locations = new Dictionary<string, Tuple<long,int>> ();
const int align = 4096;
Stream package;
public PackageMaker (string output)
{
package = File.Create (output, 128*1024);
if (IsUnix){
File.SetAttributes (output, unchecked ((FileAttributes) 0x80000000));
}
}
public int AddFile (string fname)
{
using (Stream fileStream = File.OpenRead (fname)){
var ret = fileStream.Length;
Console.WriteLine ("At {0:x} with input {1}", package.Position, fileStream.Length);
fileStream.CopyTo (package);
package.Position = package.Position + (align - (package.Position % align));
return (int) ret;
}
}
public void Add (string entry, string fname)
{
var p = package.Position;
var size = AddFile (fname);
locations [entry] = Tuple.Create(p, size);
}
public void AddString (string entry, string text)
{
var bytes = Encoding.UTF8.GetBytes (text);
locations [entry] = Tuple.Create (package.Position, bytes.Length);
package.Write (bytes, 0, bytes.Length);
package.Position = package.Position + (align - (package.Position % align));
}
public void Dump ()
{
foreach (var floc in locations.Keys){
Console.WriteLine ($"{floc} at {locations[floc]:x}");
}
}
public void WriteIndex ()
{
var indexStart = package.Position;
var binary = new BinaryWriter (package);
binary.Write (locations.Count);
foreach (var entry in from entry in locations orderby entry.Value.Item1 ascending select entry){
var bytes = Encoding.UTF8.GetBytes (entry.Key);
binary.Write (bytes.Length+1);
binary.Write (bytes);
binary.Write ((byte) 0);
binary.Write (entry.Value.Item1);
binary.Write (entry.Value.Item2);
}
binary.Write (indexStart);
binary.Write (Encoding.UTF8.GetBytes ("xmonkeysloveplay"));
binary.Flush ();
}
public void Close ()
{
WriteIndex ();
package.Close ();
package = null;
}
}
static bool MaybeAddFile (PackageMaker maker, string code, string file)
{
if (file == null)
return true;
if (!File.Exists (file)){
Console.Error.WriteLine ("The file {0} does not exist", file);
return false;
}
maker.Add (code, file);
return true;
}
static bool GeneratePackage (List<string> files)
{
if (runtime == null){
if (IsUnix)
runtime = Process.GetCurrentProcess().MainModule.FileName;
else {
Console.Error.WriteLine ("You must specify at least one runtime with --runtime or --cross");
Environment.Exit (1);
}
}
if (!File.Exists (runtime)){
Console.Error.WriteLine ($"The specified runtime at {runtime} does not exist");
Environment.Exit (1);
}
if (ctor_func != null){
Console.Error.WriteLine ("--static-ctor not supported with package bundling, you must use native compilation for this");
return false;
}
var maker = new PackageMaker (output);
maker.AddFile (runtime);
foreach (var url in files){
string fname = LocateFile (new Uri (url).LocalPath);
string aname = Path.GetFileName (fname);
maker.Add ("assembly:" + aname, fname);
if (File.Exists (fname + ".config"))
maker.Add ("config:" + aname, fname + ".config");
}
if (!MaybeAddFile (maker, "systemconfig:", config_file) || !MaybeAddFile (maker, "machineconfig:", machine_config_file))
return false;
if (config_dir != null)
maker.Add ("config_dir:", config_dir);
if (embedded_options != null)
maker.AddString ("options:", embedded_options);
maker.Dump ();
maker.Close ();
return true;
}
static void GenerateBundles (List<string> files)
{
@ -710,24 +962,34 @@ void mono_register_config_for_assembly (const char* assembly_name, cons
{
Console.WriteLine ("Usage is: mkbundle [options] assembly1 [assembly2...]\n\n" +
"Options:\n" +
" -c Produce stub only, do not compile\n" +
" -o out Specifies output filename\n" +
" -oo obj Specifies output filename for helper object file\n" +
" --config F Bundle system config file `F'\n" +
" --config-dir D Set MONO_CFG_DIR to `D'\n" +
" --deps Turns on automatic dependency embedding (default on simple)\n" +
" -L path Adds `path' to the search path for assemblies\n" +
" --nodeps Turns off automatic dependency embedding (default)\n" +
" --deps Turns on automatic dependency embedding\n" +
" --machine-config F Use the given file as the machine.config for the application.\n" +
" -o out Specifies output filename\n" +
" --nodeps Turns off automatic dependency embedding (default on custom)\n" +
" --skip-scan Skip scanning assemblies that could not be loaded (but still embed them).\n" +
"\n" +
"--simple Simple mode does not require a C toolchain and can cross compile\n" +
" --cross TARGET Generates a binary for the given TARGET\n"+
" --local-targets Lists locally available targets\n" +
" --list-targets Lists available targets on the remote server\n" +
" --options OPTIONS Embed the specified Mono command line options on target\n" +
" --runtime RUNTIME Manually specifies the Mono runtime to use\n" +
" --target-server URL Specified a server to download targets from, default is " + target_server + "\n" +
"\n" +
"--custom Builds a custom launcher, options for --custom\n" +
" -c Produce stub only, do not compile\n" +
" -oo obj Specifies output filename for helper object file\n" +
" --dos2unix[=true|false]\n" +
" When no value provided, or when `true` specified\n" +
" `dos2unix` will be invoked to convert paths on Windows.\n" +
" When `--dos2unix=false` used, dos2unix is NEVER used.\n" +
" --keeptemp Keeps the temporary files\n" +
" --config F Bundle system config file `F'\n" +
" --config-dir D Set MONO_CFG_DIR to `D'\n" +
" --machine-config F Use the given file as the machine.config for the application.\n" +
" --static Statically link to mono libs\n" +
" --nomain Don't include a main() function, for libraries\n" +
" -z Compress the assemblies before embedding.\n" +
" --skip-scan Skip scanning assemblies that could not be loaded (but still embed them).\n" +
" --static-ctor ctor Add a constructor call to the supplied function.\n" +
" You need zlib development headers and libraries.\n");
}