1 Sequence prepend
:= method(s
, s
.. self)
3 AddonBuilder
:= Object clone do(
5 disable
:= method(isDisabled
= true
)
7 platform
:= System platform split
at(0) asLowercase
8 cflags
:= method(System
getenv("CFLAGS") ifNilEval(""))
9 if (platform
== "windows",
10 cc
:= method(System
getenv("CC") ifNilEval(return "cl -nologo"))
11 cxx
:= method(System
getenv("CXX") ifNilEval(return "cl -nologo"))
13 linkdll
:= "link -link -nologo"
14 linkDirPathFlag
:= "-libpath:"
16 linkOutFlag
:= "-out:"
17 linkLibSuffix
:= ".lib"
18 ar
:= "link -lib -nologo"
22 cc
:= method(System
getenv("CC") ifNilEval(return "cc"))
23 cxx
:= method(System
getenv("CXX") ifNilEval(return "g++"))
26 linkDirPathFlag
:= "-L"
31 ar
:= method(System
getenv("AR") ifNilEval(return "ar"))
33 ranlib
:= method(System
getenv("RANLIB") ifNilEval(return "ranlib"))
36 supportedOnPlatform
:= true
38 frameworkSearchPaths
:= List clone
39 frameworkSearchPaths
append("/System/Library/Frameworks")
40 frameworkSearchPaths
append("/Library/Frameworks")
41 frameworkSearchPaths
append("/Local/Library/Frameworks")
42 // frameworkSearchPaths
append("~/Library/Frameworks")
44 searchPrefixes
:= List clone
45 searchPrefixes
append(System installPrefix
)
46 searchPrefixes
append("/usr")
47 searchPrefixes
append("/mingw")
48 searchPrefixes
append("/usr/X11R6")
49 searchPrefixes
append("/usr/local")
50 searchPrefixes
append("/usr/pkg")
51 searchPrefixes
append("/opt/local")
52 searchPrefixes
append("/sw")
53 // on windows there is no such thing as a standard place
54 // to look
for these things
55 searchPrefixes
append("i:/io/addonLibs")
57 headerSearchPaths
:= List clone
58 appendHeaderSearchPath
:= method(v
, if(File clone setPath(v
) exists
, headerSearchPaths
appendIfAbsent(v
)))
59 searchPrefixes
foreach(searchPrefix
, appendHeaderSearchPath(searchPrefix
.. "/include"))
61 libSearchPaths
:= List clone
62 appendLibSearchPath
:= method(v
, if(File clone setPath(v
) exists
, libSearchPaths
appendIfAbsent(v
)))
63 searchPrefixes
foreach(searchPrefix
, appendLibSearchPath(searchPrefix
.. "/lib"))
71 self folder
:= Directory clone
73 self depends
:= Object clone do(
76 frameworks
:= List clone
78 includes
:= List clone
79 linkOptions
:= List clone
84 mkdir
:= method(relativePath
,
85 if (folder path
!= ".",
86 path
:= folder path
.. "/" .. relativePath
88 if(Directory exists(path
) not
,
89 writeln("mkdir -p ", relativePath
)
90 dir
:= Directory with(".")
91 path
split("/") foreach(x
, dir
:= dir
folderNamedCreateIfAbsent(x
))
95 pathForFramework
:= method(name
,
96 frameworkname
:= name
.. ".framework"
97 path
:= frameworkSearchPaths
detect(path
,
98 Directory with(path
.. "/" .. frameworkname
) exists
103 pathForHeader
:= method(name
,
104 path
:= headerSearchPaths
detect(path
,
105 File with(path
.. "/" .. name
) exists
110 pathForLib
:= method(name
,
111 libname
:= "lib" .. name
112 path
:= libSearchPaths
detect(path
,
113 p1
:= File with(path
.. "/" .. libname
.. "." .. dllSuffix
) exists
114 p2
:= File with(path
.. "/" .. libname
.. ".a") exists
115 p3
:= File with(path
.. "/" .. libname
.. ".lib") exists
121 dependsOnBinding
:= method(v
, depends addons
appendIfAbsent(v
))
122 dependsOnHeader
:= method(v
, depends headers
appendIfAbsent(v
))
123 dependsOnLib
:= method(v
, depends libs
appendIfAbsent(v
))
124 dependsOnFramework
:= method(v
, depends frameworks
appendIfAbsent(v
))
125 dependsOnInclude
:= method(v
, depends includes
appendIfAbsent(v
))
126 dependsOnLinkOption
:= method(v
, depends linkOptions
appendIfAbsent(v
))
127 dependsOnSysLib
:= method(v
, depends syslibs
appendIfAbsent(v
))
129 dependsOnFrameworkOrLib
:= method(v
, w
,
130 path
:= pathForFramework(v
)
131 if(path
!= nil
, dependsOnFramework(v
) ; appendHeaderSearchPath(path
.. "/" .. v
.. ".framework/Headers"), dependsOnLib(w
))
134 optionallyDependsOnLib
:= method(v
, if(pathForLib(v
) != nil
, dependsOnLib(v
)))
135 optionallyDependsOnFramework
:= method(v
, if(pathForFramework(v
) != nil
, dependsOnFramework(v
)))
137 missingFrameworks
:= method(
138 depends frameworks
select(p
,
139 if(pathForFramework(p
) == nil
,
140 error
:= (self name
.. " is missing " .. p
.. " framework\n") print
141 File clone openForAppending("errors") write(error
) close
142 self isAvailable
:= false
148 missingHeaders
:= method(
149 depends headers
select(p
,
150 if(pathForHeader(p
) == nil
,
151 error
:= (self name
.. " is missing " .. p
.. " header\n") print
152 File clone openForAppending("errors") write(error
) close
153 self isAvailable
:= false
159 missingLibs
:= method(
160 depends libs
select(p
,
161 //writeln("pathForLib(", p
, ") = ", pathForLib(p
))
162 if(pathForLib(p
) == nil
,
163 error
:= (self name
.. " is missing " .. p
.. " library\n") print
164 File clone openForAppending("errors") write(error
) close
165 self isAvailable
:= false
171 hasDepends
:= method(missingFrameworks size
== 0 and missingLibs size
== 0 and missingHeaders size
== 0)
173 installCommands
:= method(
174 commands
:= Map clone
175 missingLibs
foreach(p
,
176 if(debs
at(p
), commands
atPut("apt-get", "apt-get install " .. debs
at(p
) .. " && ldconfig"))
177 if(ebuilds
at(p
), commands
atPut("emerge", "emerge -DN1 " .. ebuilds
at(p
)))
178 if(pkgs
at(p
), commands
atPut("port", "port install " .. pkgs
at(p
)))
179 if(rpms
at(p
), commands
atPut("urpmi", "urpmi " .. rpms
at(p
) .. " && ldconfig"))
186 module folder
setPath(path
)
190 systemCall
:= method(s
,
191 if(trySystemCall(s
) == 256, System
exit(1))
194 trySystemCall
:= method(s
,
197 if (folder path
!= ".",
198 oldPath
:= Directory currentWorkingDirectory
199 Directory setCurrentWorkingDirectory(folder path
)
201 result
:= System
system(s
)
203 Directory setCurrentWorkingDirectory(oldPath
)
208 // ------------------------------------
210 name
:= method(folder name
)
211 oldDate
:= Date clone setYear(1970)
213 libName
:= method("libIo" .. folder name
.. ".a")
215 libFile
:= method(folder
fileNamedOrNil(libName
))
216 objsFolder
:= method(self objsFolder
:= folder
createSubdirectory("_build/objs"))
217 sourceFolder
:= method(folder
folderNamed("source"))
219 sourceFolder
filesWithExtension("cpp") appendSeq(sourceFolder
filesWithExtension("c")) appendSeq(sourceFolder
filesWithExtension("m"))
222 libsFolder
:= method(Directory with("libs"))
223 addonsFolder
:= method(Directory with("addons"))
225 includePaths
:= method(
226 includePaths
:= List clone
227 includePaths
appendSeq(libsFolder folders
map(path
) map(p
, Path
with(p
, "_build/headers")))
228 includePaths
appendSeq(depends addons
map(n
, "addons/" .. n
.. "/_build/headers"))
232 build
:= method(options
,
233 writeln(("--- " .. folder name
.. " ") alignLeft(79, "-"))
234 writeln("build.io: Entering directory `", folder path
, "'")
235 mkdir("_build/headers")
236 if(Directory with(Path
with(folder path
, "source")) filesWithExtension(".h") size
> 0,
237 trySystemCall("cp source/*.h _build/headers")
242 options
:= options
ifNilEval("") .. cflags
244 obj
:= f name
replaceSeq(".cpp", ".o") replaceSeq(".c", ".o") replaceSeq(".m", ".o")
245 objFile
:= objsFolder
fileNamedOrNil(obj
)
246 if((objFile
== nil
) or(objFile lastDataChangeDate
< f lastDataChangeDate
),
248 includes
:= includePaths
map(v
, "-I" .. Path
with("../../", v
))
249 includes
appendSeq(headerSearchPaths
map(v
, "-I" .. v
))
251 s
:= cc
.. " " .. options
.. " " .. depends includes
join(" ") .. " " .. includes
join(" ") .. " -I. "
252 if(list("cygwin", "mingw", "windows") contains(platform
) not
,
255 s
= s
.. "-DBUILDING_"
256 s
= s
.. name asUppercase
259 s
= s
.. "-c " .. ccOutFlag
.. "_build/objs/" .. obj
.. " source/" .. f name
266 if(platform
== "windows", embedManifest
)
267 writeln("build.io: Leaving directory `", folder path
, "'")
273 systemCall(ar
.. " " .. arFlags
.. "_build/lib/" .. libName
.. " _build/objs/*.o")
274 if (ranlib
!= nil
, systemCall(ranlib
.. " _build/lib/" .. libName
))
278 if(list("cygwin", "mingw", "windows") contains(platform
), return "dll")
279 if(platform
== "darwin", return "dylib")
283 dllNameFor
:= method(s
, "lib" .. s
.. "." .. dllSuffix
)
285 dllCommand
:= method(
286 if(platform
== "darwin",
287 "-dynamiclib -single_module -read_only_relocs suppress"
289 if (platform
== "windows",
297 buildDynLib
:= method(
300 links
:= depends addons
map(b
, linkDirPathFlag
.. "../" .. b
.. "/_build/dll")
302 links
appendSeq(depends addons
map(v
, linkLibFlag
.. "Io" .. v
.. linkLibSuffix
))
303 if(platform
== "windows",
304 links
appendSeq(depends syslibs
map(v
, v
.. ".lib"))
306 if(platform
!= "darwin" and platform
!= "windows",
307 links
appendSeq(depends addons
map(v
, "-Wl,--rpath -Wl," .. System installPrefix
.. "/lib/io/addons/" .. v
.. "/_build/dll/"))
309 links
appendSeq(libSearchPaths
map(v
, linkDirPathFlag
.. v
))
310 links
appendSeq(depends libs
map(v
, linkLibFlag
.. v
.. linkLibSuffix
))
311 links
appendSeq(list(linkDirPathFlag
.. "../../_build/dll", linkLibFlag
.. "iovmall" .. linkLibSuffix
))
313 links
appendSeq(depends frameworks
map(v
, "-framework " .. v
))
314 links
appendSeq(depends linkOptions
)
316 libname
:= dllNameFor("Io" .. self name
)
319 if(platform
== "darwin",
320 links
append("-flat_namespace")
321 s
:= " -install_name " .. System installPrefix
.. "/lib/io/addons/" .. self name
.. "/_build/dll/" .. libname
324 systemCall(linkdll
.. " " .. cflags
.. " " .. dllCommand
.. " " .. s
.. " " .. linkOutFlag
.. "_build/dll/" .. libname
.. " _build/objs/*.o" .. " " .. links
join(" "))
327 embedManifest
:= method(
328 dllFilePath
:= "_build/dll/" .. dllNameFor("Io" .. name
)
329 manifestFilePath
:= dllFilePath
.. ".manifest"
330 systemCall("mt.exe -manifest " .. manifestFilePath
.. " -outputresource:" .. dllFilePath
.. ";2")
331 writeln("Removing manifest file: " .. manifestFilePath
)
332 File with(folder path
.. "/" .. manifestFilePath
) remove
336 writeln(folder name
, " clean")
337 trySystemCall("rm -rf _build")
338 trySystemCall("rm -f source/Io*Init.c")
339 self removeSlot("objsFolder")
342 ioCodeFolder
:= method(folder
folderNamed("io"))
343 ioFiles
:= method(ioCodeFolder
filesWithExtension("io"))
344 initFileName
:= method("source/Io" .. folder name
.. "Init.c")
348 generateInitFile
:= method(
349 if(folder
folderNamed("source") filesWithExtension("m") size
!= 0, return)
350 initFile
:= folder
createFileNamed(initFileName
)
352 initFile
write("#include \"IoState.h\"\n")
353 initFile
write("#include \"IoObject.h\"\n\n")
355 sourceFiles
:= folder
folderNamed("source") files
356 iocFiles
:= sourceFiles
select(f
, f name
beginsWithSeq("Io") and(f name
endsWithSeq(".c")) and(f name
containsSeq("Init") not
) and(f name
containsSeq("_") not
))
357 iocppFiles
:= sourceFiles
select(f
, f name
beginsWithSeq("Io") and(f name
endsWithSeq(".cpp")) and(f name
containsSeq("Init") not
) and(f name
containsSeq("_") not
))
359 iocFiles
appendSeq(iocppFiles
)
360 extraFiles
:= sourceFiles
select(f
, f name
beginsWithSeq("Io") and(f name
endsWithSeq(".c")) and(f name
containsSeq("Init") not
) and(f name
containsSeq("_")))
362 orderedFiles
:= List clone appendSeq(iocFiles
)
365 d
:= f open readLines
detect(line
, line
containsSeq("docDependsOn"))
369 prerequisitName
:= "Io" .. d
afterSeq("(\"") beforeSeq("\")") .. ".c"
370 prerequisit
:= orderedFiles
detect(of
, of name
== prerequisitName
)
371 orderedFiles
remove(f
)
372 orderedFiles
insertAfter(f
, prerequisit
)
376 iocFiles
= orderedFiles
379 initFile
write("IoObject *" .. f name fileName
.. "_proto(void *state);\n")
382 extraFiles
foreach(f
,
383 initFile
write("void " .. f name fileName
.. "Init(void *context);\n")
386 if (platform
== "windows",
387 initFile
write("__declspec(dllexport)\n")
389 initFile
write("\nvoid Io" .. folder name
.. "Init(IoObject *context)\n")
390 initFile
write("{\n")
391 if(iocFiles size
> 0,
392 initFile
write("\tIoState *self = IoObject_state((IoObject *)context);\n\n")
396 initFile
write("\tIoObject_setSlot_to_(context, SIOSYMBOL(\"" .. f name fileName asMutable
removePrefix("Io") .. "\"), " .. f name fileName
.. "_proto(self));\n\n")
399 extraFiles
foreach(f
,
400 initFile
write("\t" .. f name fileName
.. "Init(context);\n")
403 if(ioCodeFolder
and isStatic
,
404 ioFiles
foreach(f
, initFile
write(codeForIoFile(f
)))
407 initFile
write("}\n")
411 codeForIoFile
:= method(f
,
412 code
:= Sequence
clone
414 code
appendSeq("\t{\n\t\tchar *s = ")
415 code
appendSeq(f contents
splitNoEmpties("\n") map(line
, "\"" .. line escape
.. "\\n\"") join("\n\t\t"))
416 code
appendSeq(";\n\t\tIoState_on_doCString_withLabel_(self, context, s, \"" .. f name
.. "\");\n")
417 code
appendSeq("\t}\n\n")
422 generateDocs
:= method(
423 systemCall("../../_build/binaries/io ../../tools/io/DocsExtractor.io .")
427 systemCall("rm -f io/zzz_docs.io")