diff --git a/build-files.txt b/build-files.txt index 4e603e8..95a467b 100644 --- a/build-files.txt +++ b/build-files.txt @@ -16,6 +16,7 @@ source/dub/compilers/gdc.d source/dub/compilers/ldc.d source/dub/generators/build.d +source/dub/generators/cmake.d source/dub/generators/generator.d source/dub/generators/sublimetext.d source/dub/generators/visuald.d @@ -28,4 +29,4 @@ source/dub/internal/vibecompat/inet/url.d source/dub/recipe/json.d source/dub/recipe/packagerecipe.d -source/dub/recipe/sdl.d \ No newline at end of file +source/dub/recipe/sdl.d diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 8b2a9f2..1354855 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -510,6 +510,7 @@ "", "visuald - VisualD project files", "sublimetext - SublimeText project file", + "cmake - CMake build scripts", "build - Builds the package directly", "", "An optional package name can be given to generate a different package than the root/CWD package." diff --git a/source/dub/generators/cmake.d b/source/dub/generators/cmake.d new file mode 100644 index 0000000..ce49ba5 --- /dev/null +++ b/source/dub/generators/cmake.d @@ -0,0 +1,141 @@ +/** + Generator for CMake build scripts + + Copyright: © 2015 Steven Dwy + License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. + Authors: Steven Dwy +*/ +module dub.generators.cmake; + +import dub.compilers.buildsettings; +import dub.generators.generator; +import dub.internal.vibecompat.core.log; +import dub.internal.vibecompat.core.file; +import dub.internal.vibecompat.inet.path; +import dub.project; + +import std.algorithm: map, uniq, sort; +import std.array: appender, join; +import std.stdio: File, write; +import std.string: format, replace; + +class CMakeGenerator: ProjectGenerator +{ + this(Project project) + { + super(project); + } + + override void generateTargets(GeneratorSettings settings, in TargetInfo[string] targets) + { + auto script = appender!(char[]); + auto scripts = appender!(string[]); + bool[string] visited; + Path projectRoot = m_project.rootPackage.path; + Path cmakeListsPath = projectRoot ~ "CMakeLists.txt"; + + foreach(name, info; targets) + { + if(visited.get(name, false)) + continue; + + visited[name] = true; + name = name.sanitize; + string targetType; + string libType; + bool addTarget = true; + + switch(info.buildSettings.targetType) with(TargetType) + { + case autodetect: + throw new Exception("Don't know what to do about autodetect target type"); + case executable: + targetType = "executable"; + + break; + case dynamicLibrary: + libType = "SHARED"; + + goto case; + case library: + case staticLibrary: + targetType = "library"; + + break; + case sourceLibrary: + addTarget = false; + + break; + case none: + continue; + default: + assert(false); + } + + script.put("include(UseD)\n"); + script.put( + "add_d_conditions(VERSION %s DEBUG %s)\n".format( + info.buildSettings.versions.dup.join(" "), + info.buildSettings.debugVersions.dup.join(" "), + ) + ); + + foreach(directory; info.buildSettings.importPaths) + script.put("include_directories(%s)\n".format(directory)); + + if(addTarget) + { + script.put("add_%s(%s %s\n".format(targetType, name, libType)); + + foreach(file; info.buildSettings.sourceFiles) + script.put(" %s\n".format(file)); + + script.put(")\n"); + script.put( + "target_link_libraries(%s %s %s)\n".format( + name, + (info.dependencies ~ info.linkDependencies).dup.sort.uniq.map!sanitize.join(" "), + info.buildSettings.libs.dup.join(" ") + ) + ); + script.put( + `set_target_properties(%s PROPERTIES TEXT_INCLUDE_DIRECTORIES "%s")`.format( + name, + info.buildSettings.stringImportPaths.dup.join(";") + ) ~ "\n" + ); + } + + string filename = (projectRoot ~ "%s.cmake".format(name)).toNativeString; + File file = File(filename, "w"); + + file.write(script.data); + file.close; + script.shrinkTo(0); + scripts.put(filename); + } + + if(!cmakeListsPath.existsFile) + { + logWarn("You must use a fork of CMake which has D support for these scripts to function properly."); + logWarn("It is available at https://github.com/trentforkert/cmake"); + logInfo("Generating default CMakeLists.txt"); + script.put("cmake_minimum_required(VERSION 3.0)\n"); + script.put("project(%s D)\n".format(m_project.rootPackage.name)); + + foreach(path; scripts.data) + script.put("include(%s)\n".format(path)); + + File file = File(cmakeListsPath.toNativeString, "w"); + + file.write(script.data); + file.close; + } + } +} + +///Transform a package name into a valid CMake target name. +string sanitize(string name) +{ + return name.replace(":", "_"); +} diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 5492e54..d552e80 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -8,6 +8,7 @@ module dub.generators.generator; import dub.compilers.compiler; +import dub.generators.cmake; import dub.generators.build; import dub.generators.sublimetext; import dub.generators.visuald; @@ -309,6 +310,9 @@ case "sublimetext": logDebug("Creating SublimeText generator."); return new SublimeTextGenerator(project); + case "cmake": + logDebug("Creating CMake generator."); + return new CMakeGenerator(project); } }