Fixing Sequence dotProduct(seq). Returned self instead of the dot product
[io/quag.git] / build / AddonBuilder.io
blob73ec152dcb3afa0138341104b300df335cc4e596
1 Sequence prepend := method(s, s .. self)
3 AddonBuilder := Object clone do(
4 platform := System platform split at(0) asLowercase
5 cflags := method(System getenv("CFLAGS") ifNilEval(""))
6 if (platform == "windows",
7 cc := method(System getenv("CC") ifNilEval(return "cl -nologo"))
8 cxx := method(System getenv("CXX") ifNilEval(return "cl -nologo"))
9 ccOutFlag := "-Fo"
10 linkdll := "link -link -nologo"
11 linkDirPathFlag := "-libpath:"
12 linkLibFlag := "lib"
13 linkOutFlag := "-out:"
14 linkLibSuffix := ".lib"
15 ar := "link -lib -nologo"
16 arFlags := "-out:"
17 ranlib := nil
19 cc := method(System getenv("CC") ifNilEval(return "cc"))
20 cxx := method(System getenv("CXX") ifNilEval(return "g++"))
21 ccOutFlag := "-o "
22 linkdll := cc
23 linkDirPathFlag := "-L"
24 linkLibFlag := "-l"
25 linkLibSuffix := ""
26 linkOutFlag := "-o "
27 linkLibSuffix := ""
28 ar := method(System getenv("AR") ifNilEval(return "ar"))
29 arFlags := "rcu "
30 ranlib := method(System getenv("RANLIB") ifNilEval(return "ranlib"))
33 supportedOnPlatform := true
35 frameworkSearchPaths := List clone
36 frameworkSearchPaths append("/System/Library/Frameworks")
37 frameworkSearchPaths append("/Library/Frameworks")
38 frameworkSearchPaths append("/Local/Library/Frameworks")
39 // frameworkSearchPaths append("~/Library/Frameworks")
41 searchPrefixes := List clone
42 searchPrefixes append(System installPrefix)
43 searchPrefixes append("/usr")
44 searchPrefixes append("/mingw")
45 searchPrefixes append("/usr/X11R6")
46 searchPrefixes append("/usr/local")
47 searchPrefixes append("/usr/pkg")
48 searchPrefixes append("/opt/local")
49 searchPrefixes append("/sw")
50 // on windows there is no such thing as a standard place
51 // to look for these things
52 searchPrefixes append("i:/io/addonLibs")
54 headerSearchPaths := List clone
55 appendHeaderSearchPath := method(v, if(File clone setPath(v) exists, headerSearchPaths appendIfAbsent(v)))
56 searchPrefixes foreach(searchPrefix, appendHeaderSearchPath(searchPrefix .. "/include"))
58 libSearchPaths := List clone
59 appendLibSearchPath := method(v, if(File clone setPath(v) exists, libSearchPaths appendIfAbsent(v)))
60 searchPrefixes foreach(searchPrefix, appendLibSearchPath(searchPrefix .. "/lib"))
62 debs := Map clone
63 ebuilds := Map clone
64 pkgs := Map clone
65 rpms := Map clone
67 init := method(
68 self folder := Directory clone
70 self depends := Object clone do(
71 headers := List clone
72 libs := List clone
73 frameworks := List clone
74 syslibs := List clone
75 includes := List clone
76 linkOptions := List clone
77 addons := List clone
81 mkdir := method(path,
82 if (folder path != ".",
83 path := folder path .. "/" .. path
85 writeln("Mkdir " .. path )
86 dir := Directory with(".")
87 path split("/") foreach(x, dir := dir folderNamedCreateIfAbsent(x))
90 pathForFramework := method(name,
91 frameworkname := name .. ".framework"
92 path := frameworkSearchPaths detect(path,
93 Directory with(path .. "/" .. frameworkname) exists
95 path
98 pathForHeader := method(name,
99 path := headerSearchPaths detect(path,
100 File with(path .. "/" .. name) exists
102 path
105 pathForLib := method(name,
106 libname := "lib" .. name
107 path := libSearchPaths detect(path,
108 p1 := File with(path .. "/" .. libname .. "." .. dllSuffix) exists
109 p2 := File with(path .. "/" .. libname .. ".a") exists
110 p3 := File with(path .. "/" .. libname .. ".lib") exists
111 p1 or p2 or p3
113 path
116 dependsOnBinding := method(v, depends addons appendIfAbsent(v))
117 dependsOnHeader := method(v, depends headers appendIfAbsent(v))
118 dependsOnLib := method(v, depends libs appendIfAbsent(v))
119 dependsOnFramework := method(v, depends frameworks appendIfAbsent(v))
120 dependsOnInclude := method(v, depends includes appendIfAbsent(v))
121 dependsOnLinkOption := method(v, depends linkOptions appendIfAbsent(v))
122 dependsOnSysLib := method(v, depends syslibs appendIfAbsent(v))
124 dependsOnFrameworkOrLib := method(v, w,
125 path := pathForFramework(v)
126 if(path != nil, dependsOnFramework(v) ; appendHeaderSearchPath(path .. "/" .. v .. ".framework/Headers"), dependsOnLib(w))
129 optionallyDependsOnLib := method(v, if(pathForLib(v) != nil, dependsOnLib(v)))
130 optionallyDependsOnFramework := method(v, if(pathForFramework(v) != nil, dependsOnFramework(v)))
132 missingFrameworks := method(
133 depends frameworks select(p,
134 if(pathForFramework(p) == nil,
135 error := (self name .. " is missing " .. p .. " framework\n") print
136 File clone openForAppending("errors") write(error) close
137 self isAvailable := false
138 true
143 missingHeaders := method(
144 depends headers select(p,
145 if(pathForHeader(p) == nil,
146 error := (self name .. " is missing " .. p .. " header\n") print
147 File clone openForAppending("errors") write(error) close
148 self isAvailable := false
149 true
154 missingLibs := method(
155 depends libs select(p,
156 //writeln("pathForLib(", p, ") = ", pathForLib(p))
157 if(pathForLib(p) == nil,
158 error := (self name .. " is missing " .. p .. " library\n") print
159 File clone openForAppending("errors") write(error) close
160 self isAvailable := false
161 true
166 hasDepends := method(missingFrameworks size == 0 and missingLibs size == 0 and missingHeaders size == 0)
168 installCommands := method(
169 commands := Map clone
170 missingLibs foreach(p,
171 if(debs at(p), commands atPut("apt-get", "apt-get install " .. debs at(p) .. " && ldconfig"))
172 if(ebuilds at(p), commands atPut("emerge", "emerge -DN1 " .. ebuilds at(p)))
173 if(pkgs at(p), commands atPut("port", "port install " .. pkgs at(p)))
174 if(rpms at(p), commands atPut("urpmi", "urpmi " .. rpms at(p) .. " && ldconfig"))
176 commands
179 with := method(path,
180 module := self clone
181 module folder setPath(path)
182 module
185 systemCall := method(s,
186 if(trySystemCall(s) == 256, System exit(1))
189 trySystemCall := method(s,
190 writeln("running ", s, " in ", folder path, "\n")
191 oldPath := nil
192 if (folder path != ".",
193 oldPath := Directory currentWorkingDirectory
194 Directory setCurrentWorkingDirectory(folder path)
196 result := System system(s)
197 if (oldPath != nil,
198 Directory setCurrentWorkingDirectory(oldPath)
200 result
203 // ------------------------------------
205 name := method(folder name)
206 oldDate := Date clone setYear(1970)
208 libName := method("libIo" .. folder name .. ".a")
210 libFile := method(folder fileNamedOrNil(libName))
211 objsFolder := method(self objsFolder := folder createSubdirectory("_build/objs"))
212 sourceFolder := method(folder folderNamed("source"))
213 cFiles := method(
214 sourceFolder filesWithExtension("cpp") appendSeq(sourceFolder filesWithExtension("c")) appendSeq(sourceFolder filesWithExtension("m"))
217 libsFolder := method(Directory with("libs"))
218 addonsFolder := method(Directory with("addons"))
220 includePaths := method(
221 includePaths := List clone
222 includePaths appendSeq(libsFolder folders map(path) map(p, Path with(p, "_build/headers")))
223 includePaths appendSeq(depends addons map(n, "addons/" .. n .. "/_build/headers"))
224 includePaths
227 build := method(options,
228 writeln("--- ", folder name, " ---")
229 mkdir("_build/headers")
230 if(Directory with(Path with(folder path, "source")) filesWithExtension(".h") size > 0,
231 trySystemCall("cp source/*.h _build/headers")
234 generateInitFile
236 options := options ifNilEval("") .. cflags
237 cFiles foreach(f,
238 obj := f name replaceSeq(".cpp", ".o") replaceSeq(".c", ".o") replaceSeq(".m", ".o")
239 objFile := objsFolder fileNamedOrNil(obj)
240 if((objFile == nil) or(objFile lastDataChangeDate < f lastDataChangeDate),
242 includes := includePaths map(v, "-I" .. Path with("../../", v))
243 includes appendSeq(headerSearchPaths map(v, "-I" .. v))
245 s := cc .. " " .. options .. " " .. depends includes join(" ") .. " " .. includes join(" ") .. " -I. "
246 if(list("cygwin", "mingw", "windows") contains(platform) not,
247 s = s .. "-fPIC "
249 s = s .. "-DBUILDING_"
250 s = s .. name asUppercase
251 s = s .. "_ADDON "
253 s = s .. "-c " .. ccOutFlag .. "_build/objs/" .. obj .. " source/" .. f name
254 systemCall(s)
258 buildLib
259 buildDynLib
262 buildLib := method(
263 mkdir("_build/lib")
264 systemCall(ar .. " " .. arFlags .. "_build/lib/" .. libName .. " _build/objs/*.o")
265 if (ranlib != nil, systemCall(ranlib .. " _build/lib/" .. libName))
268 dllSuffix := method(
269 if(list("cygwin", "mingw", "windows") contains(platform), return "dll")
270 if(platform == "darwin", return "dylib")
271 "so"
274 dllNameFor := method(s, "lib" .. s .. "." .. dllSuffix)
276 dllCommand := method(
277 if(platform == "darwin",
278 "-dynamiclib -single_module -read_only_relocs suppress"
280 if (platform == "windows",
281 "-dll -debug"
283 "-shared"
288 buildDynLib := method(
289 writeln("buildDynLib")
290 mkdir("_build/dll")
292 links := depends addons map(b, linkDirPathFlag .. "../" .. b .. "/_build/dll")
294 links appendSeq(depends addons map(v, linkLibFlag .. "Io" .. v .. linkLibSuffix))
295 if(platform == "windows",
296 links appendSeq(depends syslibs map(v, v .. ".lib"))
298 if(platform != "darwin" and platform != "windows",
299 links appendSeq(depends addons map(v, "-Wl,--rpath -Wl," .. System installPrefix .. "/lib/io/addons/" .. v .. "/_build/dll/"))
301 links appendSeq(libSearchPaths map(v, linkDirPathFlag .. v))
302 links appendSeq(depends libs map(v, linkLibFlag .. v .. linkLibSuffix))
303 links appendSeq(list(linkDirPathFlag .. "../../_build/dll", linkLibFlag .. "iovmall" .. linkLibSuffix))
305 links appendSeq(depends frameworks map(v, "-framework " .. v))
306 links appendSeq(depends linkOptions)
308 libname := dllNameFor("Io" .. self name)
310 s := ""
311 if(platform == "darwin",
312 links append("-flat_namespace")
313 s := " -install_name " .. System installPrefix .. "/lib/io/addons/" .. self name .. "/_build/dll/" .. libname
316 systemCall(linkdll .. " " .. cflags .. " " .. dllCommand .. " " .. s .. " " .. linkOutFlag .. "_build/dll/" .. libname .. " _build/objs/*.o" .. " " .. links join(" "))
319 clean := method(
320 writeln(folder name, " clean")
321 trySystemCall("rm -rf _build")
322 trySystemCall("rm -f source/Io*Init.c")
323 self removeSlot("objsFolder")
326 ioCodeFolder := method(folder folderNamed("io"))
327 ioFiles := method(ioCodeFolder filesWithExtension("io"))
328 initFileName := method("source/Io" .. folder name .. "Init.c")
330 isStatic := false
332 generateInitFile := method(
333 if(folder folderNamed("source") filesWithExtension("m") size != 0, return)
334 initFile := folder createFileNamed(initFileName)
335 initFile remove open
336 initFile write("#include \"IoState.h\"\n")
337 initFile write("#include \"IoObject.h\"\n\n")
339 sourceFiles := folder folderNamed("source") files
340 iocFiles := sourceFiles select(f, f name beginsWithSeq("Io") and(f name endsWithSeq(".c")) and(f name containsSeq("Init") not) and(f name containsSeq("_") not))
342 extraFiles := sourceFiles select(f, f name beginsWithSeq("Io") and(f name endsWithSeq(".c")) and(f name containsSeq("Init") not) and(f name containsSeq("_")))
344 orderedFiles := List clone appendSeq(iocFiles)
346 iocFiles foreach(f,
347 d := f open readLines detect(line, line containsSeq("docDependsOn"))
348 f close
350 if(d,
351 prerequisitName := "Io" .. d afterSeq("(\"") beforeSeq("\")") .. ".c"
352 prerequisit := orderedFiles detect(of, of name == prerequisitName )
353 orderedFiles remove(f)
354 orderedFiles insertAfter(f, prerequisit)
358 iocFiles = orderedFiles
360 iocFiles foreach(f,
361 initFile write("IoObject *" .. f name fileName .. "_proto(void *state);\n")
364 extraFiles foreach(f,
365 initFile write("void " .. f name fileName .. "Init(void *context);\n")
368 if (platform == "windows",
369 initFile write("__declspec(dllexport)\n")
371 initFile write("\nvoid Io" .. folder name .. "Init(IoObject *context)\n")
372 initFile write("{\n")
373 if(iocFiles size > 0,
374 initFile write("\tIoState *self = IoObject_state((IoObject *)context);\n\n")
377 iocFiles foreach(f,
378 initFile write("\tIoObject_setSlot_to_(context, SIOSYMBOL(\"" .. f name fileName asMutable removePrefix("Io") .. "\"), " .. f name fileName .. "_proto(self));\n\n")
381 extraFiles foreach(f,
382 initFile write("\t" .. f name fileName .. "Init(context);\n")
385 if(ioCodeFolder and isStatic,
386 ioFiles foreach(f, initFile write(codeForIoFile(f)))
389 initFile write("}\n")
390 initFile close
393 codeForIoFile := method(f,
394 code := Sequence clone
395 if (f size > 0,
396 code appendSeq("\t{\n\t\tchar *s = ")
397 code appendSeq(f contents splitNoEmpties("\n") map(line, "\"" .. line escape .. "\\n\"") join("\n\t\t"))
398 code appendSeq(";\n\t\tIoState_on_doCString_withLabel_(self, context, s, \"" .. f name .. "\");\n")
399 code appendSeq("\t}\n\n")
401 code
404 generateDocs := method(
405 systemCall("../../_build/binaries/io ../../tools/io/DocsExtractor.io .")
408 cleanDocs := method(
409 systemCall("rm -f io/zzz_docs.io")