- /**
- 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.file;
- import dub.internal.vibecompat.inet.path;
- import dub.internal.logging;
- import dub.project;
-
- import std.algorithm: map, uniq;
- import std.algorithm : stdsort = sort; // to avoid clashing with built-in sort
- import std.array: appender, join, replace;
- import std.stdio: File, write;
- import std.string: format;
-
- 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;
- NativePath projectRoot = m_project.rootPackage.path;
- NativePath 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.join(" "),
- info.buildSettings.debugVersions.join(" "),
- )
- );
-
- foreach(directory; info.buildSettings.importPaths)
- script.put("include_directories(%s)\n".format(directory.sanitizeSlashes));
-
- foreach(directory; info.buildSettings.cImportPaths)
- script.put("c_include_directories(%s)\n".format(directory.sanitizeSlashes));
-
- if(addTarget)
- {
- script.put("add_%s(%s %s\n".format(targetType, name, libType));
-
- foreach(file; info.buildSettings.sourceFiles)
- script.put(" %s\n".format(file.sanitizeSlashes));
-
- script.put(")\n");
- script.put(
- "target_link_libraries(%s %s %s)\n".format(
- name,
- (info.dependencies ~ info.linkDependencies).dup.stdsort.uniq.map!(s => sanitize(s)).join(" "),
- info.buildSettings.libs.join(" ")
- )
- );
- script.put(
- `set_target_properties(%s PROPERTIES TEXT_INCLUDE_DIRECTORIES "%s")`.format(
- name,
- info.buildSettings.stringImportPaths.map!(s => sanitizeSlashes(s)).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);
-
- logInfo("Generated", Color.green, "%s.cmake", name);
- }
-
- 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");
- logDiagnostic("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;
-
- logInfo("Generated", Color.green, "CMakeLists.txt (default)");
- }
- }
- }
-
- ///Transform a package name into a valid CMake target name.
- private string sanitize(string name)
- {
- return name.replace(":", "_");
- }
-
- private string sanitizeSlashes(string path)
- {
- version(Windows)
- return path.replace("\\", "/");
- else
- return path;
- }