1 module Build;
2 
3 import core.stdc.stdlib: exit;
4 
5 import std.algorithm;
6 import std.array;
7 import std.conv;
8 import std.file;
9 import std.getopt;
10 import std.path;
11 import std.process;
12 import std.range;
13 import std.stdio;
14 import std.string;
15 
16 string dcflags;
17 string ldflags;
18 
19 version(DigitalMars)
20 {
21 	string DC = "dmd";
22 	string OUTPUT = "-of";
23 
24 	version(Win32) version = DMD32;
25 }
26 else version(LDC)
27 {
28 	string DC = "ldc2";
29 	string OUTPUT = "-od=objects -oq -of";
30 }
31 else version(GNU)
32 {
33 	string DC = "gdc";
34 	string OUTPUT = "-o ";
35 }
36 else
37 {
38 	static assert(false, "Unsupported compiler");
39 }
40 
41 int main(string[] args)
42 {
43 	version(Posix)
44 	{
45 		writeln("This build script is currently Windows only.");
46 		return(1);
47 	}
48 
49 	getopt(args, "dcflags", &dcflags, "ldflags", &ldflags);
50 	args.popFront();
51 	
52 	foreach ( arg; args )
53 	{
54 		if ( !["gtkd", "gtkdgl", "sv", "gstreamer", "vte", "peas", "all"].canFind(arg) )
55 		{
56 			writefln("Unknown option: %s", arg);
57 			return 1;
58 		}
59 	}
60 	
61 	if ( args.length == 0 )
62 		args = ["gtkd", "sv"];
63 		
64 	if ( args.canFind("all") )
65 		args = ["gtkd", "sv", "gstreamer", "peas"];
66 	
67 	foreach ( arg; args )
68 	{
69 		switch ( arg )
70 		{
71 			case "gtkd":
72 				build("generated\\gtkd", "gtkd");
73 				break;
74 			case "gtkdgl":
75 				build("generated\\gtkdgl", "gtkdgl");
76 				break;
77 			case "sv":
78 				build("generated\\sourceview", "gtkdsv");
79 				break;
80 			case "gstreamer":
81 				build("generated\\gstreamer", "gstreamerd");
82 				break;
83 			case "peas":
84 				build("generated\\peas", "peasd");
85 				break;
86 			default:
87 				assert(false);
88 				break;
89 		}
90 	}
91 	
92 	return(0);
93 }
94 
95 void build(string dir, string lib)
96 {
97 	version(DMD32)
98 	{
99 		if (lib == "gtkd")
100 		{
101 			string[] subDirs = ["atk", "cairo", "gdk", "gdkpixbuf", "gio", "glib", "gobject", "gthread", "gtkc", "gtkd", "pango", "rsvg"];
102 
103 			foreach(directory; subDirs)
104 				buildObj(dFiles("generated\\gtkd\\"~ directory), directory);
105 
106 			string[] files = dFiles("generated\\gtkd\\gtk").split();
107 			files.chunks((files.length / 4) + 1).enumerate(1).each!((index, value){buildObj(value.join(' '), "gtk"~to!string(index));});
108 
109 			string objects;
110 			foreach(directory; subDirs)
111 				objects ~= directory ~".obj ";
112 			objects ~= "gtk1.obj gtk2.obj gtk3.obj gtk4.obj";
113 
114 			executeShell(format("%s -lib %s %s%s.lib %s", DC, ldflags, OUTPUT, lib, objects));
115 
116 			foreach(string obj; objects.split())
117 				std.file.remove(obj);
118 		}
119 		else
120 		{
121 			buildObj(dFiles(dir), lib);
122 			executeShell(format("%s -lib %s %s%s.lib %s.obj", DC, ldflags, OUTPUT, lib, lib));
123 			std.file.remove(lib ~".obj");
124 		}
125 	}
126 	else
127 	{
128 		std.file.write("build.rf", format("-m64 -c -lib %s %s -Igenerated/gtkd %s%s.lib %s", dcflags, ldflags, OUTPUT ,lib, dFiles(dir)));
129 		auto pid = spawnProcess([DC, "@build.rf"]);
130 
131 		if ( wait(pid) != 0 )
132 			exit(1);
133 	}
134 	
135 	version(LDC)std.file.rmdirRecurse("objects");
136 	std.file.remove("build.rf");
137 }
138 
139 void buildObj(string files, string objName)
140 {
141 	std.file.write("build.rf", format("-c %s -Igenerated/gtkd %s%s.obj %s", dcflags, OUTPUT, objName, files));
142 	auto pid = spawnProcess(["dmd", "@build.rf"]);
143 	if ( wait(pid) != 0 )
144 		exit(1);
145 }
146 
147 string dFiles(string sourceDir)
148 {
149 	string files;
150 	auto entries = dirEntries(sourceDir, SpanMode.breadth);
151 	
152 	foreach ( DirEntry entry; entries )
153 	{
154 		if ( entry.isDir == false && entry.name.extension == ".d" )
155 		{
156 			files ~= entry.name ~ " ";
157 		}
158 	}
159 	
160 	return files;
161 }