schani/clojurec
{ "createdAt": "2012-06-06T13:24:19Z", "defaultBranch": "master", "description": "A Clojure implementation on top of C", "fullName": "schani/clojurec", "homepage": null, "language": "Clojure", "name": "clojurec", "pushedAt": "2018-04-25T22:28:20Z", "stargazersCount": 919, "topics": [], "updatedAt": "2025-10-27T19:07:20Z", "url": "https://github.com/schani/clojurec"}ClojureC
Section titled “ClojureC”This is compiler for the Clojure programming language that targets C as a backend. It is based on ClojureScript and was started off ClojureScript’s commit 0e0aa7fdd379649bf87f8fff5c6a64e37fe616a4.
Status
Section titled “Status”This project is no longer actively maintained, though PRs and such are still welcome.
Background, Features, and Limitations
Section titled “Background, Features, and Limitations”Forked off of a version of ClojureScript circa 2012 (prior to Clojure and ClojureScript being refactored to use the same compiler or front end), ClojureC provides:
-
Generation of C or Objective-C code, enabling faster startup than JVM-based executables
Objective-C message sending uses the section character (§) in place of the at-sign (@), as the latter is already used by Clojure.
-
Ability to statically expose any C function to ClojureC (dynamic loading might be possible but is not currently implemented)
See clojurec/binder/.
-
An implementation of the Boehm Garbage Collector (GC)
-
Incomplete support for native threads
Exception handling currently uses two global variables (could be replaced with thread-local vars?).
Extending protocols might also not be threadsafe.
-
No support for “modern” Clojure language features such as transducers
-
No eval
-
Limited optimization, really only as demanded by the language
For example, loop/recur is turned into a real loop.
-
Exception support
Implemented via setjmp/longjmp.
Alternatives to ClojureC
Section titled “Alternatives to ClojureC”If native threads are not important, but fast startup is, consider using ClojureScript instead of ClojureC, as the startup time for the v8 engine is reportedly much faster than for the JVM.
Future Plans
Section titled “Future Plans”As there seem to be few known use cases for programs that need to both start up quickly and use native threading, it is perhaps not surprising that there’s little apparent interest in making the necessary changes to “productize” ClojureC. Such changes could include:
-
Full support for native threads
-
Supporting the latest version of the Clojure language
-
Supporting a C++ back end
-
Retargeting the GCC compiler back end
-
Implementing a proper optimizer
-
Providing improved debugger support
Other than (perhaps) full native-thread support, each of the above item would represent a substantial investment of resources that are not, at present, available.
Historical Info
Section titled “Historical Info”Community and Organization
Section titled “Community and Organization”We use a Trello board to keep track of ideas, proposals, TODOs, bugs and who’s doing what. If you plan to contribute, please do join the board.
Additional documentation for the project can be found at the wiki.
Preparations
Section titled “Preparations”Submodules
Section titled “Submodules”ClojureC includes a submodule. To fetch it, do
git submodule initgit submodule updateDependencies
Section titled “Dependencies”Before you can run anything make sure you have GLib 2 and the Boehm-Demers-Weiser garbage collector installed. If
pkg-config --cflags glib-2.0pkg-config --cflags bdw-gcdon’t report errors you should be good.
Make sure you’re using Leiningen 2 - older versions of Leiningen won’t work. Run the testsuite:
lein testAll tests should pass.
Using ClojureC
Section titled “Using ClojureC”Note that ClojureC is still in its experimental phase, so please don’t expect a polished experience, yet.
From the command line
Section titled “From the command line”ClojureC provides a very simple command line compiler interface. Let’s say we want to compile samples/echo.cljc:
(ns cljc.user)(defn -main [& args] (apply println args))If you do the following in the clojurec directory
lein run -c src/cljc/cljc/core.cljc cljc.core run runlein run -c samples/echo.cljc cljc.user run runlein run -d cljc.user/-main runcd runmake -f c/Makefileyou should have a cljc executable in the run directory that acts mostly like echo.
Objective-C bridge
Section titled “Objective-C bridge”ClojureC features a very rudimentary Objective-C bridge. Here’s an example:
(ns cljc.user (:require [cljc.objc :as objc]))
(extend-type (§ NSString) ICounted (-count [self] (§ self length)))
(defn -main [& args] (let [app (§ (§ NSApplication) sharedApplication) date (§ (§ NSDate) :dateWithTimeIntervalSinceNow 3600) locale (§ (§ NSLocale) currentLocale) desc (§ date :descriptionWithLocale locale)] (println "Hello, NSApplication: `" desc "` has count " (count desc))))If you have that code in /tmp/nsdate.cljc, then this will build and run it:
lein run -c src/cljc/cljc/core.cljc cljc.core run runlein run -c src/cljc/cljc/objc.cljc cljc.objc run run -mlein run -c /tmp/nsdate.cljc cljc.user run run -mlein run -d cljc.user/-main run -mcd runmakeFor a more involved example, see samples/ios.cljc.
iOS sample app
Section titled “iOS sample app”To build the iOS sample app, do
cd samples./build-ios.shThe last step will open an XCode project that will build and run the iOS app that build-ios.sh compiled from samples/ios.cljc.
From the REPL
Section titled “From the REPL”The easiest way to play around with ClojureC interactively is in the namespace clojurec.core-test. For example:
(core-run '(pr (+ 1 2)))=> [3]Mobile Platform Notes
Section titled “Mobile Platform Notes”Android
Section titled “Android”See the README.md file in “clojurec/run/android”.