diff --git a/druntime/Makefile b/druntime/Makefile index ddd457c969ee..15b9e329bb4e 100644 --- a/druntime/Makefile +++ b/druntime/Makefile @@ -147,7 +147,7 @@ else TAGS:=$(OS),posix_threads endif -TGEN_CMD:=./parse_tagged_hier.sh $(TAGGED_SRCS_FILE) $(TAGGED_COPY_LIST_FILE) $(TAGGED_COPY_FILE) $(IMPDIR) $(TAGS) config > /dev/null +TGEN_CMD:=./parse_tagged_hier.d $(TAGGED_SRCS_FILE) $(TAGGED_COPY_LIST_FILE) $(TAGGED_COPY_FILE) $(IMPDIR) $(TAGS) config > /dev/null TAGGED_SRCS:=$(shell $(TGEN_CMD) && cat $(TAGGED_SRCS_FILE)) diff --git a/druntime/parse_tagged_hier.d b/druntime/parse_tagged_hier.d new file mode 100755 index 000000000000..df2ff72acf3b --- /dev/null +++ b/druntime/parse_tagged_hier.d @@ -0,0 +1,115 @@ +#!/usr/bin/env dub +/+ + dub.sdl: + name "parse_tagged_hier" ++/ + +import std.algorithm; +import std.array; +import std.conv: to; +import std.file; +import std.exception: enforce; +import std.path; +import std.stdio; +import std.string: splitLines; +import std.typecons; + +int main(in string[] args) +{ + try + worker(args); + catch(Exception e) + { + stderr.writeln("Error: "~e.msg); + return 1; + } + + return 0; +} + +void worker(in string[] args) +{ + enforce(args.length >= 7 && args.length <= 8, "need 6 or 7 CLI arguments"); + + immutable dstFile = args[1].buildNormalizedPath; /// i.e. GEN_SRCS file + immutable taggedImportsFile = args[2].buildNormalizedPath; /// i.e. mak/TAGGED_COPY + immutable dstCopyFile = args[3].buildNormalizedPath; /// i.e. GEN_COPY file, generated list of imports choised by tags + immutable impDir = args[4].buildNormalizedPath; /// path to druntime ./import/ dir + immutable tagsArg = args[5]; /// comma separated list of tags + immutable configDir = args[6]; /// path to druntime config/ dir where is placed tags implementations + immutable externalConfigDir = (args.length > 7) ? args[7] : null; /// path to additional (external) config/ dir + + enforce(taggedImportsFile.isFile, `Tagged imports file '`~taggedImportsFile~`' not found`); + enforce(impDir.isDir, `DRuntime import/ dir '`~impDir~`' not found`); + enforce(configDir.isDir, `Tags implementations dir '`~configDir~`' not found`); + + if(externalConfigDir !is null) + enforce(externalConfigDir.isDir, `Additional tags dir '`~externalConfigDir~`' not found`); + + immutable string[] tags = tagsArg.split(","); + + writeln("Tags will be applied: ", tagsArg); + + immutable allConfigDirs = [configDir, externalConfigDir]; + + auto availTagsDirs = allConfigDirs + .map!(a => a.dirEntries(SpanMode.shallow)) + .join + .filter!(a => a.isDir) + .map!(a => Tuple!(string, "base", string, "path")(a.name.baseName, a.name)) + .array + .sort!((a, b) => a.base < b.base); + + static struct SrcElem + { + string basePath; // ~/a/b/c/confing_dir/tag_1_name + string tag; // tag_1_name + string relPath; // core/internal/somemodule.d + + string fullPath() const => basePath~"/"~relPath; // ~/a/b/c/confing_dir/tag_1_name/core/internal/somemodule.d + } + + SrcElem[] resultSrcsList; + + foreach(tag; tags) + { + auto foundSUbdirs = availTagsDirs.filter!(a => a.base == tag); + + if(foundSUbdirs.empty) + { + stderr.writeln(`Warning: tag '`, tag, `' doesn't corresponds to any subdirectory inside of '`, allConfigDirs,`', skip`); + continue; + } + + // tag matched, files from matching dirs should be added to list recursively + auto filesToAdd = foundSUbdirs.map!( + d => dirEntries(d.path, SpanMode.depth) + .filter!(a => a.isFile) + .map!(e => SrcElem(d.path, tag, e.name[d.path.length+1 .. $])) + ).join; + + foreach(f; filesToAdd) + { + auto found = resultSrcsList.find!((a, b) => a.relPath == b.relPath)(f); + + enforce(found.empty, `File '`~f.fullPath~`' overrides already defined file '`~found.front.fullPath~`'`); + + resultSrcsList ~= f; + } + } + + auto taggedImportsList = taggedImportsFile.readText.replace(`\`, `/`).splitLines.sort.uniq.array; + auto importsToCopy = File(dstCopyFile, "w"); + + foreach(imp; taggedImportsList) + { + auto found = resultSrcsList.find!(a => a.relPath == imp); + enforce(!found.empty, `Required for import file '`~imp~`' is not found in tagged sources`); + + importsToCopy.writeln(found.front.fullPath); + } + + resultSrcsList.map!(a => a.fullPath).join("\n").toFile(dstFile); + + writeln("All tags applied"); +} diff --git a/druntime/parse_tagged_hier.sh b/druntime/parse_tagged_hier.sh deleted file mode 100755 index f093dc1d88d7..000000000000 --- a/druntime/parse_tagged_hier.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -DST_FILE=$1 -SRC_COPY_FILE=$2 -DST_COPY_FILE=$3 -IMPDIR=$4 -TAGS=$5 -SRC_DIR=$6 - -if [[ ! -d ${SRC_DIR} ]]; then - echo "Tags dir '${SRC_DIR}' not found" >&2 - exit 1 -fi - -if [[ -f ${DST_FILE} ]]; then - echo "Tagged sources list already generated" - exit 0 -fi - -TAGS_LIST=($(echo "$TAGS" | tr "," "\n")) - -echo -e "\nTags will be applied: $TAGS" - -APPLIED="" - -function applyTaggedFiles { - TAG=$1 - SRC_TAG_DIR=${SRC_DIR}/${TAG} - - if [[ ! -d ${SRC_TAG_DIR} ]]; then - echo "Warning: tag '${TAG}' doesn't corresponds to any subdirectory inside of '${SRC_DIR}', skip" >&2 - else - SRC_FILES_LIST+=($(find ${SRC_TAG_DIR} -type f )) - - pushd ${SRC_TAG_DIR} > /dev/null - MAYBE_COPY_LIST+=($(find * -type f )) - popd > /dev/null - fi - - APPLIED+=" $TAG" - - echo "Currently applied tags:$APPLIED" -} - -for tag in "${TAGS_LIST[@]}" -do - applyTaggedFiles ${tag} -done - -LINES_TO_COPY=$(grep -v '^$' ${SRC_COPY_FILE} | sort | uniq | wc -l) -COPIED=0 - -mkdir -p $(dirname ${DST_FILE}) -mkdir -p $(dirname ${DST_COPY_FILE}) -echo -ne > ${DST_FILE} -echo -ne > ${DST_COPY_FILE} - -for i in "${!SRC_FILES_LIST[@]}" -do - echo ${SRC_FILES_LIST[$i]} >> ${DST_FILE} - - maybe_copy=$(echo ${MAYBE_COPY_LIST[$i]} | tr '/' '\\') - - # Adds copy entry if file mentioned in the list - grep -F "$maybe_copy" ${SRC_COPY_FILE} > /dev/null && { - echo ${IMPDIR}'/'${SRC_FILES_LIST[$i]} >> ${DST_COPY_FILE} - COPIED=$((COPIED+1)) - } -done - -if [ $COPIED -ne $LINES_TO_COPY ]; then - echo "File '$SRC_COPY_FILE' contains $LINES_TO_COPY meaningful line(s), but to '$DST_COPY_FILE' added $COPIED line(s)" >&2 - - mv ${DST_FILE} "$DST_FILE.disabled" - echo "File '$DST_FILE' moved to '$DST_FILE.disabled' to avoid considering that tags parsing process was sucessfully done" >&2 - exit 1 -fi - -echo "All tags applied"