MSBuild integration for Clojure CLR projects. Build, test, and run Clojure code using standard dotnet commands, with full REPL support.
- Build Clojure projects with
dotnet build - Run Clojure applications with
dotnet run - Test with
clojure.testusingdotnet test - REPL support (socket REPL and nREPL via MSBuild targets)
- C# Interop - seamlessly use C# classes from Clojure
- Automatic entry point generation via source generators
- .NET 9.0 SDK or later
- Clojure CLR 1.12.2 or later
- For testing: Microsoft.NET.Test.Sdk (automatically included)
# From NuGet (when published)
dotnet new install Clojure.MSBuild.Templates
# Or install from local source during development
dotnet new install /path/to/clojure-msbuild/templates/clojure-app# Create a new Clojure CLR app with default settings
dotnet new clojure-app -n MyClojureApp
cd MyClojureApp
# Run your app
dotnet run
# Run tests
dotnet testThe template creates a complete project structure:
- src/main.cljr - Main application entry point with JSON and .NET interop examples
- test/main_test.cljr - Sample test file using clojure.test
- .csproj - Pre-configured with all required packages
- README.md - Project-specific documentation
- .gitignore - Common build artifacts excluded
dotnet new console -n MyClojureApp
cd MyClojureApp<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ClojureMainNamespace>main</ClojureMainNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Clojure.MSBuild" Version="0.3.0" />
<PackageReference Include="Clojure" Version="1.12.2" />
</ItemGroup>
<ItemGroup>
<Content Include="src/**/*.cljr">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>Create src/main.cljr:
(ns main)
(defn -main
[& args]
(println "Hello from Clojure CLR!")
(when (seq args)
(println "Arguments:" (vec args))))# Using dotnet run
dotnet run
dotnet run -- arg1 arg2
# Or build and run the DLL directly
dotnet build
dotnet bin/Debug/net9.0/MyClojureApp.dll
dotnet bin/Debug/net9.0/MyClojureApp.dll arg1 arg2Clojure.MSBuild uses a source generator to automatically create the .NET entry point for your Clojure application. You just need to:
- Set
ClojureMainNamespaceto your main namespace - Define a
-mainfunction in that namespace - Build and run like any .NET application
No manual Program.cs needed - the source generator handles everything behind the scenes.
Start an interactive REPL with all project dependencies:
dotnet msbuild /t:clj-replStart an nREPL server for editor integration (port 1667):
# First, add the nREPL package to your project
dotnet add package clojure.tools.nrepl --version 0.1.0-alpha1
# Then start the nREPL server
dotnet msbuild /t:clj-nreplConnect from your editor:
- VS Code with Calva: Connect to Generic -> localhost:1667
- Emacs/Vim: Connect to localhost:1667
Run a Clojure script file:
dotnet msbuild /t:clj-run -p:File=src/script.cljClojure.MSBuild includes a VSTest adapter that integrates seamlessly with dotnet test:
# Run all tests
dotnet test
# Run with detailed output
dotnet test --logger:"console;verbosity=detailed"
# Run specific test files
dotnet test --filter "FullyQualifiedName~main_test"The test adapter automatically discovers and runs all Clojure tests in *_test.clj files that use clojure.test.
Compile Clojure namespaces to .NET DLLs:
dotnet msbuild /t:clj-build| Property | Description | Default |
|---|---|---|
ClojureMainNamespace |
Namespace containing your -main function | Required for executables |
ClojureAutoLoadAssemblies |
Auto-load NuGet assemblies | true |
ClojureCompileOnBuild |
Compile namespaces during build | false |
ClojureNamespacesToCompile |
Namespaces to compile (semicolon-separated) | main namespace |
You can create Clojure libraries that can be referenced by other .NET projects:
- Create a new project with
OutputTypeset toLibrary:
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net9.0</TargetFramework>
<!-- No ClojureMainNamespace for libraries -->
<!-- Optional: AOT compile namespaces -->
<ClojureCompileOnBuild>true</ClojureCompileOnBuild>
<ClojureNamespacesToCompile>my-lib;my-utils</ClojureNamespacesToCompile>
</PropertyGroup>- Add your Clojure namespaces in the
src/directory - Build with
dotnet buildto create a DLL and optionally AOT-compiled namespaces
Reference the library from another project:
<ItemGroup>
<ProjectReference Include="../MyLibrary/MyLibrary.csproj" />
</ItemGroup>Or as a NuGet package:
<ItemGroup>
<PackageReference Include="MyClojureLibrary" Version="1.0.0" />
</ItemGroup>- Library projects don't need
ClojureMainNamespacesince they don't have an entry point - The source generator won't create a Program.cs for library projects
- Consumer projects must ensure Clojure runtime is initialized before using library code
- When
ClojureCompileOnBuildis true, namespaces are AOT-compiled to.cljr.dllfiles - Compiled DLLs are automatically copied to consuming projects via ProjectReference
- Both source files (*.cljr) and compiled DLLs can be used for runtime loading
See the /examples folder for working examples:
/examples/simple- Basic executable application demonstrating:- Integration with
dotnet test - C# interop capabilities
- JSON handling with clojure.data.json
- Integration with
/examples/simple_library- Library project demonstrating:- Creating reusable Clojure libraries with AOT compilation
- Math and string utility functions
- Automatic DLL generation and distribution
- Library testing with clojure.test
Create test files with the _test.clj suffix in your project:
(ns my-namespace-test
(:require [clojure.test :refer :all]
[my-namespace :refer [my-function]]))
(deftest test-my-function
(testing "My function works correctly"
(is (= expected (my-function input)))))You can test C# classes from your Clojure tests:
(ns csharp-interop-test
(:require [clojure.test :refer :all])
(:import [MyApp.Services MyService]))
(deftest test-csharp-service
(testing "C# service integration"
(let [service (MyService.)]
(is (= "expected" (.ProcessData service "input"))))))The project includes a dotnet new template for quick project scaffolding:
# Install from the local template directory
dotnet new install ./templates/clojure-app
# Uninstall if needed
dotnet new uninstall clojure-appOnce installed, create new Clojure CLR projects easily:
# Basic project
dotnet new clojure-app -n MyProject
# With options
dotnet new clojure-app -n MyProject \
--framework net8.0 \
--clojureVersion 1.12.0 \
--enableTests trueTo package the template for distribution:
# Package as NuGet (when nuget CLI is available)
cd templates
nuget pack Clojure.MSBuild.Templates.nuspec
# Or create a template package manually
cd templates/clojure-app
dotnet packMIT