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