# A script to help generate build files on different platforms # The Makefile generator (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- $ "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) (defn- generate-make "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`) "\nCFLAGS:=" (string.join make-cflags " ") "\nLDFLAGS:=" (string.join make-ldflags " ") "\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}") (emit-rule out "${TARGET}" "${OBJECTS}" "${CC} ${CFLAGS} -o $@ $^ ${LDFLAGS}") (emit-rule out "clean" "" "rm ${OBJECTS}") (emit-rule out "clean" "" @["rm ${OBJECTS}" "rm @{TARGET}"]) # Phony targets (emit-rule out ".PHONY" @["all" "clean"]) nil) # 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))