private static void GenerateAssemblyInfo(ProjectConfig projectConfig, string compileDirPath)
		{
			using(var file = File.CreateText(Path.Combine(compileDirPath, "src/אAssemblyInfo.cs")))
			{
				var version = projectConfig.Version;
				if(version.Contains("-"))
					version = version.Substring(0, version.IndexOf("-", StringComparison.Ordinal));
				file.WriteLine("using System.Reflection;");
				file.WriteLine();
				file.WriteLine($"[assembly: AssemblyTitle(\"{projectConfig.Name}\")]");
				file.WriteLine($"[assembly: AssemblyVersion(\"{version}.0\")]");
				file.WriteLine($"[assembly: AssemblyFileVersion(\"{version}.0\")]");
			}
		}
		private static string BuildProject(string projectDirPath, ProjectConfig projectConfig, IDictionary<string, Dependency> builtDependencies)
		{
			Console.WriteLine($"Building {projectConfig.Name} ...");
			var compileDirPath = Path.Combine(projectDirPath, ".bootstrapCompile");
			DeleteDirectoryIfExists(compileDirPath);

			var srcFiles = new DirectoryInfo(Path.Combine(projectDirPath, "src")).GetFiles("*.adam", SearchOption.AllDirectories);

			var mainFunctions = srcFiles.Select(srcFile =>
			{
				var relPath = Path.GetFullPath(srcFile.FullName).Substring(projectDirPath.Length + 1);
				var csPath = Path.ChangeExtension(relPath, "cs");
				return Compile(srcFile.FullName, Path.Combine(compileDirPath, csPath));
			}).Combine();

			GenerateAssemblyInfo(projectConfig, compileDirPath);

			if(mainFunctions.Count > 1)
				throw new Exception("Multiple main functions");

			if(mainFunctions.Count == 1)
				GenerateEntryPoint(compileDirPath, mainFunctions.Single());

			var isApp = projectConfig.Template == "app";
			var targetDirPath = Path.Combine(projectDirPath, "targets/debug");
			DeleteDirectoryIfExists(targetDirPath);
			var csSrc = new DirectoryInfo(compileDirPath).GetDirectories("src")
				.Single()
				.GetFiles("*.cs", SearchOption.AllDirectories);
			var assemblyName = projectConfig.Name;
			var assemblyPath = Path.Combine(targetDirPath, assemblyName) + (isApp ? ".exe" : ".dll");
			var dependencies = projectConfig.Dependencies.Keys.Concat(CoreDependencies).ToList();
			var dependencyPaths = dependencies.Select(d => builtDependencies[d].OutputPath);
			CompileCSharp(csSrc, dependencyPaths, assemblyPath, isApp);
			builtDependencies.Add(projectConfig.Name, new Dependency(assemblyPath, dependencies));
			return targetDirPath;
		}
		private static void BuildProjects(string projectDirPath, ProjectConfig projectConfig,
			IDictionary<string, Dependency> builtDependencies, string targetDirPath)
		{
			// Build Projects that weren't already built as dependencies
			foreach(var project in projectConfig.Projects)
			{
				var projectName = project.Key;
				if(builtDependencies.ContainsKey(projectName)) continue;
				Forge(Path.Combine(projectDirPath, project.Value, ProjectFileName), builtDependencies);
				// TODO copy into target
			}
		}
		private static void BuildDependencies(string projectDirPath, ProjectConfig projectConfig, IDictionary<string, Dependency> builtDependencies)
		{
			foreach(var dependency in projectConfig.Dependencies)
			{
				var dependencyName = dependency.Key;
				if(builtDependencies.ContainsKey(dependencyName)) continue;
				var path = DependencyPath(dependencyName, dependency.Value, projectDirPath, projectConfig.DependencyPaths);
				Forge(Path.Combine(path, ProjectFileName), builtDependencies);
			}
		}