diff --git a/source/dub/dub.d b/source/dub/dub.d index 1083905..90bec38 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -169,9 +169,6 @@ logError("Unsupported IDE, there is no generator available for '"~ide~"'"); throw new Exception("Unsupported IDE, there is no generator available for '"~ide~"'"); } - - // Q: update before generating? - generator.generateProject(build_platform); } diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 3355c3e..75b393e 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -25,6 +25,9 @@ // version = VISUALD_SEPERATE_PROJECT_FILES; version = VISUALD_SINGLE_PROJECT_FILE; +// Dubbing is developing dub... +//version = DUBBING; + class VisualDGenerator : ProjectGenerator { private { Project m_app; @@ -83,7 +86,7 @@ // Writing solution file logTrace("About to write to .sln file with %s bytes", to!string(ret.data().length)); - auto sln = openFile(m_app.mainPackage().name ~ ".sln", FileMode.CreateTrunc); + auto sln = openFile(solutionFileName(), FileMode.CreateTrunc); scope(exit) sln.close(); sln.write(ret.data()); sln.flush(); @@ -102,7 +105,7 @@ void generateSolutionEntry(Appender!(char[]) ret, const Package pack) { auto projUuid = generateUUID(); auto projName = pack.name; - auto projPath = pack.name ~ ".visualdproj"; + auto projPath = projFileName(pack); auto projectUuid = guid(projName); // Write project header, like so @@ -169,19 +172,12 @@ // generateProjectConfiguration(ret, pack, Config.Unittest); // Add all files - // TODO: nice folders - struct SourceFile { - string pkg; - Path structurePath; - Path filePath; - int opCmp(ref const SourceFile rhs) const { return filePath.opCmp(rhs.filePath); } - } bool[SourceFile] sourceFiles; - void gatherSources(const(Package) package_, string prefix) { - logDebug("Gather sources for %s", package_.name); + void gatherSources(const(Package) pack, string prefix) { + logDebug("Gather sources for %s", pack.name); if(prefix != "") prefix = "|" ~ prefix ~ "|"; - foreach(source; package_.sources) { - SourceFile f = { package_.name, source, source }; + foreach(source; pack.sources) { + SourceFile f = { pack.name, Path(pack.name)~source, pack.path ~ source }; sourceFiles[f] = true; logDebug("pkg file: %s", source); } @@ -207,34 +203,37 @@ } // Create folders and files - // TODO: nice foldering ret.formattedWrite("\n ", pack.name); - version(VISUALD_SINGLE_PROJECT_FILE) { - SourceFile[] files = sourceFiles.keys; - sort!("a.pkg > b.pkg")(files); - string last = ""; - foreach(source; files) { - if(last != source.pkg) { - if(!last.empty) - ret.put("\n "); - ret.formattedWrite("\n ", source.pkg); - last = source.pkg; - } - ret.formattedWrite("\n ", source.filePath.toNativeString()); + Path lastFolder; + foreach(source; sortedSources(sourceFiles.keys)) { + auto cur = source.structurePath[0..$-1]; + if(lastFolder != cur) { + int same = 0; + foreach(int idx; 0..min(lastFolder.length, cur.length)) + if(lastFolder[idx] != cur[idx]) break; + else same = idx+1; + + const int decrease = max(0, lastFolder.length - same); + const int increase = max(0, cur.length - same); + + foreach(unused; 0..decrease) + ret.put("\n "); + foreach(idx; 0..increase) + ret.formattedWrite("\n ", cur[same + idx].toString()); + lastFolder = cur; } + ret.formattedWrite("\n ", source.filePath.toNativeString()); + } + // Finalize all open folders + foreach(unused; 0..lastFolder.length) ret.put("\n "); - } - version(VISUALD_SEPERATE_PROJECT_FILES) { - foreach(source, dummy; sourceFiles) - ret.formattedWrite("\n ", source.filePath.toNativeString()); - } ret.put("\n \n"); logTrace("About to write to '%s.visualdproj' file %s bytes", pack.name, ret.data().length); - auto sln = openFile(pack.name ~ ".visualdproj", FileMode.CreateTrunc); - scope(exit) sln.close(); - sln.write(ret.data()); - sln.flush(); + auto proj = openFile(projFileName(pack), FileMode.CreateTrunc); + scope(exit) proj.close(); + proj.write(ret.data()); + proj.flush(); } void generateProjectConfiguration(Appender!(char[]) ret, const Package pack, Config type, BuildPlatform platform) { @@ -297,15 +296,20 @@ 0"); // include paths and string imports - string imports; - string stringImports; + string imports = join(getSettings!"importPaths"(), " "); + string stringImports = join(getSettings!"stringImportPaths"(), " "); ret.formattedWrite(" %s %s", imports, stringImports); // Compiler? + string compiler = "$(DMDInstallDir)windows\\bin\\dmd.exe"; + string dflags = join(getSettings!"dflags"(), " "); ret.formattedWrite(" - $(DMDInstallDir)windows\\bin\\dmd.exe + %s + %s", compiler, dflags); + + ret.formattedWrite(" $(ConfigurationName) $(OutDir) @@ -351,7 +355,7 @@ "); // Add libraries, system libs need to be suffixed by ".lib". - string linkLibs = join(map!("a~\".lib\"")(getSettings!"libs"()), " "); + string linkLibs = join(map!(a => a~".lib")(getSettings!"libs"()), " "); string addLinkFiles = join(getSettings!"files"(), " "); ret.formattedWrite(" %s", linkLibs ~ " " ~ addLinkFiles); @@ -362,7 +366,6 @@ bin\\$(ProjectName)_d.exe - "); // Add a post build command to copy files @@ -398,9 +401,74 @@ m_projectUuids[projectName] = generateUUID(); return m_projectUuids[projectName]; } - - string libfiles(const Package pack) { - return ""; + + auto solutionFileName() const { + version(DUBBING) return m_app.mainPackage().name ~ ".dubbed.sln"; + else return m_app.mainPackage().name ~ ".sln"; } + + auto projFileName(ref const Package pack) const { + version(DUBBING) return pack.name ~ ".dubbed.visualdproj"; + else return pack.name ~ ".visualdproj"; + } + } + + // TODO: nice folders + struct SourceFile { + string pkg; + Path structurePath; + Path filePath; + + int opCmp(ref const SourceFile rhs) const { return sortOrder(this, rhs); } + // "a < b" for folder structures (deepest folder first, else lexical) + private final static int sortOrder(ref const SourceFile a, ref const SourceFile b) { + enforce(!a.structurePath.empty()); + enforce(!b.structurePath.empty()); + auto as = a.structurePath; + auto bs = b.structurePath; + + // Check for different folders, compare folders only (omit last one). + for(uint idx=0; idx bs.length? -1 : 1; + } + else { + // Both paths indicate files in the same directory, use lexical + // ordering for those. + return as.head.opCmp(bs.head); + } + } + } + + auto sortedSources(SourceFile[] sources) { + return sort(sources); + } + + unittest { + SourceFile[] sfs = [ + { "", Path("b/file.d"), Path("") }, + { "", Path("b/b/fileA.d"), Path("") }, + { "", Path("a/file.d"), Path("") }, + { "", Path("b/b/fileB.d"), Path("") }, + { "", Path("b/b/b/fileA.d"), Path("") }, + { "", Path("b/c/fileA.d"), Path("") }, + ]; + auto sorted = sort(sfs); + SourceFile[] sortedSfs; + foreach(sr; sorted) { + logInfo("%s", sr.structurePath.toNativeString()); + sortedSfs ~= sr; + } + assert(sortedSfs[0].structurePath == Path("a/file.d"), "1"); + assert(sortedSfs[1].structurePath == Path("b/b/b/fileA.d"), "2"); + assert(sortedSfs[2].structurePath == Path("b/b/fileA.d"), "3"); + assert(sortedSfs[3].structurePath == Path("b/b/fileB.d"), "4"); + assert(sortedSfs[4].structurePath == Path("b/c/fileA.d"), "5"); + assert(sortedSfs[5].structurePath == Path("b/file.d"), "6"); } } \ No newline at end of file diff --git a/source/dub/package_.d b/source/dub/package_.d index c2d83b1..828703a 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -244,15 +244,20 @@ return ret; } - /// Returns all sources as absolute paths. + /// Returns all sources as relative paths, prepend each with + /// path() to get the absolute one. @property const(Path[]) sources() const { Path[] allSources; auto sourcePath = Path("source"); auto customSourcePath = "sourcePath" in m_meta; if(customSourcePath) sourcePath = Path(customSourcePath.get!string()); - foreach(d; dirEntries((m_path ~ sourcePath).toNativeString(), "*.d", SpanMode.depth)) - allSources ~= Path(d.name); + foreach(d; dirEntries((m_path ~ sourcePath).toNativeString(), "*.d", SpanMode.depth)) { + // direct assignment allSources ~= Path(d.name)[...] spawns internal compiler/linker error + if(isDir(d.name)) continue; + auto p = Path(d.name); + allSources ~= p[m_path.length..$]; + } return allSources; } @@ -288,4 +293,4 @@ toPrettyJson(js, m_meta); dstFile.write( js.data ); } -} +} \ No newline at end of file