2018-08-04 01:50:32 +00:00
|
|
|
# A script to help generate build files on different platforms
|
|
|
|
|
2018-08-13 21:40:55 +00:00
|
|
|
# The Makefile generator
|
2018-08-04 01:50:32 +00:00
|
|
|
|
2018-08-13 21:40:55 +00:00
|
|
|
(def- make-cflags @["-std=c99" "-Wall" "-Wextra" "-O2" "-shared" "-fpic"])
|
|
|
|
(def- make-ldflags @[])
|
|
|
|
|
|
|
|
(if (= :macos (os.which))
|
|
|
|
(array.push make-cflags "undefined -dynamic_lookup"))
|
|
|
|
|
|
|
|
(defn- $
|
2018-08-04 01:50:32 +00:00
|
|
|
"Do and get the value of a subshell command"
|
|
|
|
[command]
|
|
|
|
(def f (file.popen command))
|
|
|
|
(def ret (file.read f :all))
|
|
|
|
(file.close f)
|
|
|
|
ret)
|
|
|
|
|
|
|
|
(defn- emit-rule
|
|
|
|
"Emit a rule in a makefile"
|
|
|
|
@[out target deps recipe]
|
|
|
|
(default recipe "@echo '-----'")
|
|
|
|
(file.write
|
|
|
|
out
|
|
|
|
target
|
|
|
|
": "
|
|
|
|
(if (indexed? deps) (string.join deps " ") deps)
|
|
|
|
"\n\t"
|
|
|
|
(if (indexed? recipe) (string.join recipe "\n\t") recipe)
|
|
|
|
"\n\n")
|
|
|
|
out)
|
|
|
|
|
2018-08-13 21:40:55 +00:00
|
|
|
(defn- generate-make
|
2018-08-04 01:50:32 +00:00
|
|
|
"Generate a makefile"
|
|
|
|
[out-path sources target]
|
|
|
|
(def out (file.open out-path :w))
|
|
|
|
(def csources (filter (fn [x] (= ".c" (string.slice x -2))) sources))
|
|
|
|
(def hsources (filter (fn [x] (= ".h" (string.slice x -2))) sources))
|
|
|
|
(file.write
|
|
|
|
out
|
|
|
|
"# Autogenerated Makefile, do not edit\n"
|
|
|
|
"# Generated at " ($ `date`)
|
2018-08-13 21:40:55 +00:00
|
|
|
"\nCFLAGS:=" (string.join make-cflags " ")
|
|
|
|
"\nLDFLAGS:=" (string.join make-ldflags " ")
|
2018-08-04 01:50:32 +00:00
|
|
|
"\nSOURCES:=" (string.join csources " ")
|
|
|
|
"\nHEADERS:=" (string.join hsources " ")
|
|
|
|
"\nOBJECTS:=$(patsubst %.c,%.o,${SOURCES})"
|
|
|
|
"\nTARGET:=" target ".so"
|
|
|
|
"\n\n")
|
|
|
|
(emit-rule out "all" "${TARGET}")
|
|
|
|
(emit-rule out "%.o" @["%.c" "${HEADERS}"] "${CC} ${CFLAGS} -o $@ $< ${LDFLAGS}")
|
2018-08-07 04:54:47 +00:00
|
|
|
(emit-rule out "${TARGET}" "${OBJECTS}" "${CC} ${CFLAGS} -o $@ $^ ${LDFLAGS}")
|
2018-08-04 01:50:32 +00:00
|
|
|
(emit-rule out "clean" "" "rm ${OBJECTS}")
|
2018-08-07 00:46:26 +00:00
|
|
|
(emit-rule out "clean" "" @["rm ${OBJECTS}" "rm @{TARGET}"])
|
2018-08-04 01:50:32 +00:00
|
|
|
# Phony targets
|
|
|
|
(emit-rule out ".PHONY" @["all" "clean"])
|
|
|
|
nil)
|
2018-08-13 21:40:55 +00:00
|
|
|
|
|
|
|
# The batch script generator (windows)
|
|
|
|
|
|
|
|
(defn- batch-crule
|
|
|
|
"Create a snippet to compile a single C file to an .obj file"
|
|
|
|
[file-path]
|
|
|
|
(string
|
|
|
|
`cl /nologo /I..\..\src\include /c /O2 /W3 `
|
|
|
|
file-path
|
|
|
|
"\n@if errorlevel 1 goto :BUILDFAIL"))
|
|
|
|
|
|
|
|
(defn- generate-batch
|
|
|
|
"Generate a batch file for windows"
|
|
|
|
[out-path sources target]
|
|
|
|
(def out (file.open out-path :w))
|
|
|
|
(def csources (filter (fn [x] (= ".c" (string.slice x -2))) sources))
|
|
|
|
(file.write
|
|
|
|
out
|
|
|
|
"@rem Generated batch script, run in 'Visual Studio Developer Prompt'\n"
|
|
|
|
"\n@rem \n\n"
|
|
|
|
"@echo off\n\n"
|
|
|
|
(string.join (map batch-crule csources) "\n\n")
|
|
|
|
"\n\n"
|
|
|
|
`link /nologo /dll ..\..\dst.lib /out:` target `.dll *.obj`
|
|
|
|
"\nif errorlevel 1 goto :BUILDFAIL"
|
|
|
|
"\n\n@echo .\n@echo ======\n@echo Build Succeeded.\n@echo =====\n"
|
|
|
|
"exit /b 0\n\n"
|
|
|
|
":BUILDFAIL\n"
|
|
|
|
"@echo .\n"
|
|
|
|
"@echo =====\n"
|
|
|
|
"@echo BUILD FAILED. See Output For Details.\n"
|
|
|
|
"@echo =====\n"
|
|
|
|
"@echo .\n"
|
|
|
|
"exit /b 1\n")
|
|
|
|
(file.flush out)
|
|
|
|
(file.close out)
|
|
|
|
nil)
|
|
|
|
|
|
|
|
(defn generate
|
|
|
|
"Generate the build files for a given library."
|
|
|
|
[out-path sources target]
|
|
|
|
((if (= :windows (os.which)) generate-batch generate-make)
|
|
|
|
out-path
|
|
|
|
sources
|
|
|
|
target))
|
|
|
|
|