1 #include "Builders.h"
2
AdjustLines(const String & file)3 String AdjustLines(const String& file)
4 {
5 String out;
6 const char *p = file;
7 while(*p)
8 {
9 const char *b = p;
10 while(*p && (byte)*p <= ' ' && *p != '\r' && *p != '\n')
11 p++;
12 if(*p == '#')
13 {
14 out.Cat("//");
15 b = p;
16 while(*p && *p != '\n' && *p != '\"')
17 p++;
18 out.Cat(b, (int)(p - b));
19 b = p;
20 if(*p == '\"')
21 {
22 out.Cat('\"');
23 b = ++p;
24 while(*p && *p++ != '\n')
25 ;
26 const char *e = p;
27 while(e > b && (byte)e[-1] <= ' ')
28 e--;
29 if(e[-1] == '\"')
30 e--;
31 out.Cat(UnixPath(String(b, e)));
32 out.Cat("\"\r\n");
33 b = p;
34 continue;
35 }
36 }
37 out.Cat(b, (int)(p - b));
38 while(*p && *p != '\n')
39 {
40 b = p;
41 while(*p && *p != '\n' && *p != '\r')
42 p++;
43 out.Cat(b, (int)(p - b));
44 while(*p == '\r')
45 p++;
46 }
47 if(*p == '\n')
48 {
49 p++;
50 out.Cat("\r\n");
51 }
52 }
53 return out;
54 }
55
JavaLine()56 String JavaBuilder::JavaLine()
57 {
58 return "javac";
59 }
60
JarLine()61 String JavaBuilder::JarLine()
62 {
63 return "jar";
64 }
65
66 enum { MAINCLASS, MAINDIR, MANIFEST, ITEMCOUNT };
67
BuildPackage(const String & package,Vector<String> & linkfile,Vector<String> &,String & linkoptions,const Vector<String> & all_uses,const Vector<String> & all_libraries,int)68 bool JavaBuilder::BuildPackage(const String& package, Vector<String>& linkfile, Vector<String>&, String& linkoptions,
69 const Vector<String>& all_uses, const Vector<String>& all_libraries, int)
70 {
71 int time = msecs();
72 int i;
73 int manifest = -1;
74 String packagepath = PackagePath(package);
75 Package pkg;
76 pkg.Load(packagepath);
77 String packagedir = GetFileFolder(packagepath);
78 ChDir(packagedir);
79 PutVerbose("cd " + packagedir);
80 Vector<String> pkgsfile;
81 Vector<String> sfile;
82 Vector<String> sobjfile;
83 Vector<String> soptions;
84 bool error = false;
85 bool main = HasFlag("MAIN");
86
87 for(i = 0; i < pkg.GetCount(); i++) {
88 if(!IdeIsBuilding())
89 return false;
90 if(!pkg[i].separator) {
91 String gop = Gather(pkg[i].option, config.GetKeys());
92 Vector<String> srcfile = CustomStep(pkg[i], package, error);
93 if(srcfile.GetCount() == 0)
94 error = true;
95 for(int j = 0; j < srcfile.GetCount(); j++)
96 {
97 String fn = srcfile[j];
98 String ext = ToLower(GetFileExt(fn));
99 bool ismf = false;
100 if(ext == ".java" || main && ext == ".mf")
101 {
102 if(ext == ".mf")
103 {
104 ismf = true;
105 if(manifest >= 0)
106 {
107 PutConsole(Format("%s(1): duplicate manifest file", GetHostPath(fn)));
108 PutConsole(Format("%s(1): (previous manifest file)", GetHostPath(sfile[manifest])));
109 }
110 manifest = sfile.GetCount();
111 }
112 String pkgfile = AppendFileName(package, pkg[i]);
113 pkgsfile.Add(pkgfile);
114 sfile.Add(fn);
115 soptions.Add(gop);
116 String objfile = NativePath(CatAnyPath(outdir, ismf ? String("manifest.mf") : pkgfile));
117 sobjfile.Add(objfile);
118 }
119 }
120 }
121 }
122
123 Vector<Host::FileInfo> sobjinfo = host->GetFileInfo(sobjfile);
124 int ccount = 0;
125 for(i = 0; i < sfile.GetCount(); i++) {
126 if(!IdeIsBuilding())
127 return false;
128 if(HdependFileTime(sfile[i]) > sobjinfo[i]) {
129 ccount++;
130 if(!PreprocessJava(sfile[i], sobjfile[i], soptions[i], package, pkg))
131 error = true;
132 }
133 }
134 linkfile.Add(outdir);
135 if(ccount > 0)
136 PutConsole(String().Cat() << ccount << " file(s) preprocessed in " << GetPrintTime(time) <<
137 " " << int(msecs() - time) / ccount << " msec/file");
138 linkoptions << ' ' << Gather(pkg.link, config.GetKeys());
139
140 if(!error && HasFlag("MAIN") && !sfile.IsEmpty())
141 {
142 String mainfile = sfile.Top();
143 String mainobj = sobjfile.Top();
144 String maincls = ForceExt(mainobj, ".class");
145 String libs;
146 int i;
147 for(i = 0; i < libpath.GetCount(); i++)
148 libs << (i ? ";" : " -classpath ") << '\"' << libpath[i] << '\"';
149 String linkcmd;
150 linkcmd << "javac";
151 linkcmd << (HasFlag("DEBUG") ? " -g" : " -g:none");
152 if(!HasFlag("DEBUG")) {
153 if(!IsNull(release_options))
154 linkcmd << ' ' << release_options;
155 else
156 linkcmd << " -O";
157 }
158 linkcmd << " -deprecation" << linkoptions << " -sourcepath ";
159 bool win32 = HasFlag("WIN32");
160 for(i = 0; i < linkfile.GetCount(); i++) {
161 linkcmd << (i ? (win32 ? ";" : ":") : "");
162 if(linkfile[i].Find(' ') >= 0)
163 linkcmd << '\"' << linkfile[i] << '\"';
164 else
165 linkcmd << linkfile[i];
166 }
167 linkfile.InsertN(0, ITEMCOUNT);
168 linkfile[MAINCLASS] = maincls;
169 linkfile[MAINDIR] = outdir;
170 linkfile[MANIFEST] = (manifest >= 0 ? sobjfile[manifest] : String());
171 linkcmd << ' ' << mainobj;
172 linkoptions = linkcmd;
173 }
174 return !error;
175 }
176
Preprocess(const String & package,const String & file,const String & target,bool)177 bool JavaBuilder::Preprocess(const String& package, const String& file, const String& target, bool)
178 {
179 return Builder::Preprocess(file, target, Null, false);
180 }
181
PreprocessJava(String file,String target,String options,String package,const Package & pkg)182 bool JavaBuilder::PreprocessJava(String file, String target, String options,
183 String package, const Package& pkg)
184 {
185 String mscpp = GetVar("MSCPP_JDK");
186 String cc;
187 if(!IsNull(mscpp))
188 cc = mscpp + " /C /TP /P /nologo ";
189 else
190 cc = "cpp -C ";
191 cc << IncludesDefinesTargetTime(package, pkg);
192 int time = msecs();
193 RealizePath(target);
194 String execpath;
195 execpath << cc << ' ' << options << ' ';
196 String prepfile;
197 bool error = false;
198 if(!IsNull(mscpp))
199 {
200 prepfile = ForceExt(file, ".i");
201 host->ChDir(GetFileFolder(prepfile));
202 execpath << GetHostPath(file);
203 }
204 else
205 {
206 PutConsole(file);
207 execpath << GetHostPath(file) << " " << GetHostPath(target);
208 prepfile = target;
209 }
210 if(Execute(execpath) != 0)
211 {
212 DeleteFile(target);
213 error = true;
214 }
215 String prep = LoadFile(prepfile);
216 if(prep.IsEmpty())
217 {
218 PutConsole(Format("Error loading preprocessed file %s", prepfile));
219 error = true;
220 }
221 DeleteFile(prepfile);
222 if(!prep.IsEmpty() && !::SaveFile(target, AdjustLines(prep)))
223 {
224 DeleteFile(target);
225 error = true;
226 PutConsole(Format("%s: error saving file.", target));
227 }
228 PutVerbose("preprocessed in " + GetPrintTime(time));
229 return !error;
230 }
231
AddClassDeep(String & link,String dir,String reldir)232 Time JavaBuilder::AddClassDeep(String& link, String dir, String reldir)
233 {
234 Time time = Time::Low();
235 Vector<String> folders;
236 for(FindFile ff(AppendFileName(dir, AppendFileName(reldir, "*"))); ff; ff.Next()) {
237 if(ff.IsFolder())
238 folders.Add(ff.GetName());
239 else if(!stricmp(GetFileExtPos(ff.GetName()), ".class"))
240 {
241 link << " -C \"" << dir << "\" \"" << UnixPath(CatAnyPath(reldir, ff.GetName())) << '\"';
242 time = max(time, Time(ff.GetLastWriteTime()));
243 }
244 }
245 for(int f = 0; f < folders.GetCount(); f++)
246 time = max(time, AddClassDeep(link, dir, AppendFileName(reldir, folders[f])));
247 return time;
248 }
249
Link(const Vector<String> & linkfile,const String & linkoptions,bool)250 bool JavaBuilder::Link(const Vector<String>& linkfile, const String& linkoptions, bool)
251 {
252 if(linkfile.GetCount() < ITEMCOUNT)
253 return false;
254 int time = msecs();
255 String mainclass = linkfile[MAINCLASS];
256 String maindir = linkfile[MAINDIR];
257 String manifest = linkfile[MANIFEST];
258 PutConsole("Compiling...");
259 if(Execute(linkoptions) != 0) {
260 DeleteFile(mainclass);
261 return false;
262 }
263 PutVerbose("compiled in " + GetPrintTime(time));
264 host->ChDir(maindir);
265
266 PutConsole("Archiving...");
267 String cmdline;
268 cmdline << "cf";
269 if(!manifest.IsEmpty())
270 cmdline << 'm';
271 cmdline << ' ' << GetHostPath(target);
272 if(!manifest.IsEmpty())
273 cmdline << ' ' << GetHostPath(manifest);
274 Time tm = Time::Low();
275 for(int i = ITEMCOUNT; i < linkfile.GetCount(); i++)
276 tm = max(tm, AddClassDeep(cmdline, linkfile[i], Null));
277 bool error = false;
278 if(tm > targettime) {
279 CustomStep(".pre-link", Null, error);
280 String link, response;
281 link << "jar ";
282 if(cmdline.GetLength() < 32000)
283 link << cmdline;
284 else {
285 response = GetTempFileName("jar");
286 link << '@' << response;
287 if(!UPP::SaveFile(response, cmdline)) {
288 PutConsole(String().Cat() << "Error writing JAR response file '" << response << "'");
289 return false;
290 }
291 }
292 bool ok = (Execute(link) == 0);
293 if(!IsNull(response))
294 FileDelete(response);
295 if(!ok) {
296 DeleteFile(target);
297 return false;
298 }
299 CustomStep(".post-link", Null, error);
300 PutConsole(String().Cat() << target << " (" << GetFileInfo(target).length
301 << " B) archived in " << GetPrintTime(time));
302 }
303 else
304 PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
305 << " B) is up to date.");
306 return true;
307 }
308
CreateJavaBuilder()309 static Builder *CreateJavaBuilder()
310 {
311 return new JavaBuilder;
312 }
313
INITIALIZER(JavaBuilder)314 INITIALIZER(JavaBuilder)
315 {
316 RegisterBuilder("JDK", &CreateJavaBuilder);
317 }
318