diff --git a/.whitesource b/.whitesource
new file mode 100644
index 0000000..327ddac
--- /dev/null
+++ b/.whitesource
@@ -0,0 +1,30 @@
+{
+ "scanSettings": {
+ "configMode": "AUTO",
+ "configExternalURL": "",
+ "projectToken": "",
+ "baseBranches": []
+ },
+ "checkRunSettings": {
+ "vulnerableCheckRunConclusionLevel": "failure",
+ "displayMode": "diff",
+ "useMendCheckNames": true
+ },
+ "issueSettings": {
+ "minSeverityLevel": "LOW",
+ "issueType": "DEPENDENCY"
+ },
+ "remediateSettings": {
+ "workflowRules": {
+ "enabled": true
+ }
+ },
+ "imageSettings":{
+ "imageTracing":{
+ "enableImageTracingPR": false,
+ "addRepositoryCoordinate": false,
+ "addDockerfilePath": false,
+ "addMendIdentifier": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..b63d86f
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,19 @@
+module(
+ name = "rules_d",
+)
+
+bazel_dep(
+ name = "bazel_skylib",
+ version = "1.7.1",
+)
+
+bazel_dep(name="platforms", version="0.0.11")
+
+non_module_dependencies = use_extension("//d:extensions.bzl", "non_module_dependencies")
+use_repo(non_module_dependencies, "ldc_linux_x86_64", "dmd_linux_x86_64", "dmd_darwin_x86_64", "weka_ldc_linux_x86_64")
+register_toolchains(
+ "//d:ldc_linux_x86_64_toolchain",
+ "//d:dmd_linux_x86_64_toolchain",
+ "//d:dmd_darwin_x86_64_toolchain",
+ "//d:weka_ldc_linux_x86_64_toolchain",
+ )
diff --git a/README.md b/README.md
index 3c94072..3983106 100644
--- a/README.md
+++ b/README.md
@@ -1,694 +1,5 @@
-[](https://buildkite.com/bazel/rules-d)
+# A very opinionated fork of https://github.com/bazel-contrib/rules_d
-# D rules
+## Differences with `bazel-contrib/rules_d`
-## Status
-
-We make sure this repository works with the latest version of Bazel, but no
-other development is planned.
-
-Volunteers are welcome. If you want to use the rules, consider contributing to
-this repository and becoming a maintainer.
-
-## Rules
-
-
-
-## Setup
-
-To use the D rules, add the following to your `WORKSPACE` file to add the
-external repositories for the D toolchain:
-
-```python
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-http_archive(
- name = "io_bazel_rules_d",
- urls = ["https://github.com/bazelbuild/rules_d/archive/bcf137e3c9381545ce54715632bc1d31c51ee4da.tar.gz"],
- sha256 = "a32847bf2ae634563dece49c4dc8353956b64ba5c2d01ce811ea243e1a21b5b7",
- strip_prefix = "rules_d-bcf137e3c9381545ce54715632bc1d31c51ee4da",
-)
-
-load("@io_bazel_rules_d//d:d.bzl", "d_repositories")
-d_repositories()
-```
-
-## Roadmap
-
-* Generate documentation using [`ddox`](https://github.com/rejectedsoftware/ddox)
- for `d_docs` rule.
-* Support for other options as defined in the [Dub package
- format](http://code.dlang.org/package-format?lang=json)
-* Support for specifying different configurations of a library, closer to
- [Dub's model for configurations](http://code.dlang.org/package-format?lang=json#configurations)
-* Workspace rule for retrieving dependencies from [Dub](http://code.dlang.org/)
-
-
-## d_library
-
-```python
-d_library(name, srcs, deps, includes, linkopts, versions)
-```
-
-
-
-
-
-
-
-
- | Attributes |
-
-
-
-
- name |
-
- Name, required
- A unique name for this rule.
-
- This name will be used as the name of the library built by this rule.
-
- |
-
-
- srcs |
-
- List of labels, required
- List of D .d source files used to build the library.
- |
-
-
- deps |
-
- List of labels, optional
- List of libraries to be linked to this library target.
-
- These can either be other d_library targets,
- source-only d_source_library targets, or
- cc_library targets if linking a native library.
-
- |
-
-
- imports |
-
- List of strings, optional
- List of import dirs to add to the compile line.
-
- These will be passed to the D compiler via -I flags.
-
- |
-
-
- linkopts |
-
- List of strings, optional
- List of flags that are added to the D linker command.
-
- These will be passed to the D compiler via -L flags.
-
- |
-
-
- versions |
-
- List of strings, optional
- List of versions to be defined during compilation.
-
- Versions are used for conditional compilation and are enabled in the
- code using version condition blocks. These versions
- listed here will be passed to the D compiler using
- -version flags.
-
- |
-
-
-
-
-### Example
-
-Suppose you have the following directory structure for a D project:
-
-```
-[workspace]/
- WORKSPACE
- foo/
- BUILD
- foo.d
- bar.d
- baz.d
-```
-
-The library `foo` is built using a `d_library` target:
-
-`foo/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_library")
-
-d_library(
- name = "foo",
- srcs = [
- "foo.d",
- "bar.d",
- "baz.d",
- ],
-)
-```
-
-
-## d_source_library
-
-```python
-d_source_library(name, srcs, deps, includes, linkopts, versions)
-```
-
-
-
-
-
-
-
-
-
- | Attributes |
-
-
-
-
- name |
-
- Name, required
- A unique name for this rule.
- |
-
-
- srcs |
-
- List of labels, required
-
- List of D .d source files that comprises this source
- library target.
-
- |
-
-
- deps |
-
- List of labels, optional
- List of library targets depended on by this target.
-
- These can either be other d_source_library targets or
- cc_library targets, such as when this source library
- target implements the D interface for a native library. Any native
- libraries will be linked by d_library targets that
- depend on this target.
-
- |
-
-
- imports |
-
- List of strings, optional
- List of import dirs to add to the compile line.
-
- These will be passed to the D compiler via -I flags for
- any d_library targets that depend on this target.
-
- |
-
-
- linkopts |
-
- List of strings, optional
- List of flags that are added to the D linker command.
-
- These will be passed to the D compiler via -L flags for
- any d_library targets that depend on this target.
-
- |
-
-
- versions |
-
- List of strings, optional
- List of version flags to be defined during compilation.
-
- Versions are used for conditional compilation and are enabled in the
- code using version condition blocks. These versions
- listed here will be passed to the D compiler using
- -version flags for any d_library targets
- that depend on this target.
-
- |
-
-
-
-
-### Example
-
-Suppose you have the following directory structure for a project building a
-C library and a [D interface](http://dlang.org/interfaceToC.html) for the C
-library:
-
-```
-[workspace]/
- WORKSPACE
- greeter/
- BUILD
- native_greeter.c
- native_greeter.h
- native_greeter.d
- hello_world
- BUILD
- hello_world.d
-```
-
-Build the C library using the `cc_library` rule and then use the
-`d_source_library` to define the target for the D interface for the C
-`native_greeter` library:
-
-`greeter/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_source_library")
-
-cc_library(
- name = "native_greeter_lib",
- srcs = ["native_greeter.c"],
- hdrs = ["native_greeter.h"],
-)
-
-d_source_library(
- name = "native_greeter",
- srcs = ["native_greeter.d"],
- deps = [":native_greeter_lib"],
-)
-```
-
-Other targets can directly depend on the `d_source_library` target to link
-the C library:
-
-`hello_world/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_source_library")
-
-d_binary(
- name = "hello_world",
- srcs = ["hello_world.d"],
- deps = ["//greeter:native_greeter"],
-)
-```
-
-
-## d_binary
-
-```python
-d_binary(name, srcs, deps, includes, linkopts, versions)
-```
-
-
-
-
-
-
-
-
- | Attributes |
-
-
-
-
- name |
-
- Name, required
- A unique name for this rule.
-
- This name will be used as the name of the binary built by this rule.
-
- |
-
-
- srcs |
-
- List of labels, required
- List of D .d source files used to build the binary.
- |
-
-
- deps |
-
- List of labels, optional
- List of libraries to be linked to this binary target.
-
- These can either be other d_library targets,
- source-only d_source_library targets, or
- cc_library targets if linking a native library.
-
- |
-
-
- imports |
-
- List of strings, optional
- List of import dirs to add to the compile line.
-
- These will be passed to the D compiler via -I flags.
-
- |
-
-
- linkopts |
-
- List of strings, optional
- List of flags that are added to the D linker command.
-
- These will be passed to the D compiler via -L flags.
-
- |
-
-
- versions |
-
- List of strings, optional
- List of versions to be defined during compilation.
-
- Versions are used for conditional compilation and are enabled in the
- code using version condition blocks. These versions
- listed here will be passed to the D compiler using
- -version flags.
-
- |
-
-
-
-
-Suppose you have the following directory structure for a D project:
-
-```
-[workspace]/
- WORKSPACE
- hello_lib/
- BUILD
- greeter.d
- hello_world
- BUILD
- hello_world.d
-```
-
-The source file `hello_lib/greeter.d` defines a module `greeter`:
-
-```d
-module greeter;
-...
-```
-
-The `hello_lib` library is built using a `d_library` target:
-
-`hello_lib/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_library")
-
-d_library(
- name = "hello_lib",
- srcs = ["greeter.d"],
-)
-```
-
-By default, import paths are from the root of the workspace. Thus, the source
-for the `hello_world` binary, `hello_world.d`, would import the `greeter`
-module as follows:
-
-```d
-import hello_lib.greeter;
-```
-
-However, this can be changed via the `imports` attribute on the `d_library`
-rule.
-
-The `hello_world` binary is built using a `d_binary` target:
-
-`hello_world/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_library")
-
-d_binary(
- name = "hello_world",
- srcs = ["hello_world.d"],
- deps = ["//hello_lib"],
-)
-```
-
-
-## d_test
-
-```python
-d_test(name, srcs, deps, includes, linkopts, versions)
-```
-
-
-
-
-
-
-
-
- | Attributes |
-
-
-
-
- name |
-
- Name, required
- A unique name for this rule.
-
- This name will be used as the name of the test built by this rule.
-
- |
-
-
- srcs |
-
- List of labels, required
- List of D .d source files used to build the test.
- |
-
-
- deps |
-
- List of labels, optional
- List of libraries to be linked to this test target.
-
- These can either be other d_library targets,
- source-only d_source_library targets, or
- cc_library targets if linking a native library.
-
- |
-
-
- imports |
-
- List of strings, optional
- List of import dirs to add to the compile line.
-
- These will be passed to the D compiler via -I flags.
-
- |
-
-
- linkopts |
-
- List of strings, optional
- List of flags that are added to the D linker command.
-
- These will be passed to the D compiler via -L flags.
-
- |
-
-
- versions |
-
- List of strings, optional
- List of versions to be defined during compilation.
-
- Versions are used for conditional compilation and are enabled in the
- code using version condition blocks. These versions
- listed here will be passed to the D compiler using
- -version flags.
-
- |
-
-
-
-
-### Example
-
-Suppose you have the following directory structure for a D project:
-
-```
-[workspace]/
- WORKSPACE
- hello_lib/
- BUILD
- greeter.d
- greeter_test.d
-```
-
-`hello_lib/greeter.d`:
-
-```d
-module greeter;
-
-import std.stdio;
-import std.string;
-
-class Greeter {
- private string greeting;
-
- public:
- this(in string greeting) {
- this.greeting = greeting.dup;
- }
-
- string makeGreeting(in immutable string thing) {
- return format("%s %s!", this.greeting, thing);
- }
-
- void greet(in immutable string thing) {
- writeln(makeGreeting(thing));
- }
-}
-```
-
-`hello_lib/greeter_test.d`:
-
-```d
-import hello_lib.greeter;
-
-unittest {
- auto greeter = new Greeter("Hello");
- assert(greeter.makeGreeting("world") == "Hello world!");
-}
-
-void main() {}
-```
-
-To build the library and unit test:
-
-`hello_lib/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_library", "d_test")
-
-d_library(
- name = "greeter",
- srcs = ["greeter.d"],
-)
-
-d_test(
- name = "greeter_test",
- srcs = ["greeter_test.d"],
- deps = [":greeter"],
-)
-```
-
-The unit test can then be run using:
-
-```sh
-bazel test //hello_lib:greeter_test
-```
-
-
-## d_docs
-
-```python
-d_docs(name, dep)
-```
-
-
-
-
-
-
-
-
- | Attributes |
-
-
-
-
- name |
-
- Name, required
- A unique name for this rule.
- |
-
-
- dep |
-
- Label, required
- The label of the target to generate code documentation for.
-
- d_docs can generate HTML code documentation for the
- source files of d_library, d_source_library,
- d_binary, or d_test targets.
-
- |
-
-
-
-
-### Example
-
-Suppose you have the following directory structure for a D project:
-
-```
-[workspace]/
- WORKSPACE
- foo/
- BUILD
- foo.d
- bar.d
- baz.d
-```
-
-The `foo/` directory contains the sources for the `d_library` `foo`. To
-generate HTML documentation for the `foo` library, define a `d_docs` target
-that takes the `d_library` `foo` as its dependency:
-
-`foo/BUILD`:
-
-```python
-load("@io_bazel_rules_d//d:d.bzl", "d_library", "d_docs")
-
-d_library(
- name = "foo",
- srcs = [
- "foo.d",
- "bar.d",
- "baz.d",
- ],
-)
-
-d_docs(
- name = "foo_docs",
- dep = ":foo",
-)
-```
-
-Running `bazel build //foo:foo_docs` will generate a zip file containing the
-HTML documentation generated from the source files. See the official D language
-documentation on the [Documentation Generator](http://dlang.org/ddoc.html) for
-more information on the conventions for source documentation.
+1. TBD
diff --git a/WORKSPACE b/WORKSPACE
index 733a0f4..9aceb46 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,4 +1,2 @@
-workspace(name = "io_bazel_rules_d")
-
-load("@io_bazel_rules_d//d:d.bzl", "d_repositories")
-d_repositories()
+## This is just a root of workspace marked
+## Dependencies are moved to MODULE.bazel
diff --git a/d/BUILD b/d/BUILD
index 11b67c9..f0e4bc4 100644
--- a/d/BUILD
+++ b/d/BUILD
@@ -1,57 +1,126 @@
package(default_visibility = ["//visibility:public"])
+load("//d:toolchain.bzl", "D_TOOLCHAIN", "d_toolchain")
+
+toolchain_type(name = "toolchain_type")
+
filegroup(
name = "srcs",
srcs = glob(["**"]),
)
-config_setting(
- name = "darwin",
- values = {"host_cpu": "darwin"},
-)
+[d_toolchain(
+ name = "dmd_" + os + "_x86_64",
+ d_compiler = "@dmd_" + os + "_x86_64//:dmd",
+ druntime_src = "@dmd_" + os + "_x86_64//:druntime_src",
+ libphobos = "@dmd_" + os + "_x86_64//:libphobos2",
+ libphobos_src = "@dmd_" + os + "_x86_64//:phobos_src",
+ version_flag = "-version",
+) for os in ["linux", "darwin"]] # , "windows"]]
-config_setting(
- name = "k8",
- values = {"host_cpu": "k8"},
+toolchain(
+ name = "dmd_linux_x86_64_toolchain",
+ exec_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ "//d/constraints/compiler:dmd",
+ ],
+ target_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ ],
+ toolchain = ":dmd_linux_x86_64",
+ toolchain_type = D_TOOLCHAIN,
)
-config_setting(
- name = "x64_windows",
- values = {"host_cpu": "x64_windows"},
+toolchain(
+ name = "dmd_darwin_x86_64_toolchain",
+ exec_compatible_with = [
+ "@platforms//os:macos",
+ "@platforms//cpu:x86_64",
+ "//d/constraints/compiler:dmd",
+ ],
+ target_compatible_with = [
+ "@platforms//os:macos",
+ "@platforms//cpu:x86_64",
+ ],
+ toolchain = ":dmd_darwin_x86_64",
+ toolchain_type = D_TOOLCHAIN,
)
-filegroup(
- name = "dmd",
- srcs = select({
- ":darwin": ["@dmd_darwin_x86_64//:dmd"],
- ":k8": ["@dmd_linux_x86_64//:dmd"],
- ":x64_windows": ["@dmd_windows_x86_64//:dmd"],
- }),
+# toolchain(
+# name = "dmd_windows_x86_64_toolchain",
+# exec_compatible_with = [
+# "@platforms//os:windows",
+# "@platforms//cpu:x86_64",
+# "//d/constraints/compiler:dmd",
+# ],
+# target_compatible_with = [
+# "@platforms//os:windows",
+# "@platforms//cpu:x86_64",
+# ],
+# toolchain = ":dmd_windows_x86_64",
+# toolchain_type = D_TOOLCHAIN,
+# )
+
+d_toolchain(
+ name = "ldc_linux_x86_64",
+ d_compiler = "@ldc_linux_x86_64//:ldc2",
+ druntime = "@ldc_linux_x86_64//:druntime",
+ druntime_src = "@ldc_linux_x86_64//:druntime_src",
+ libphobos = "@ldc_linux_x86_64//:libphobos2",
+ libphobos_src = "@ldc_linux_x86_64//:phobos_src",
+ version_flag = "--d-version",
+ lib_flags = [
+ "-lib", "-oq",
+ ],
+ output_bc_flags = ["--output-bc"],
)
-filegroup(
- name = "libphobos2",
- srcs = select({
- ":darwin": ["@dmd_darwin_x86_64//:libphobos2"],
- ":k8": ["@dmd_linux_x86_64//:libphobos2"],
- ":x64_windows": ["@dmd_windows_x86_64//:libphobos2"],
- }),
+toolchain(
+ name = "ldc_linux_x86_64_toolchain",
+ exec_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ "//d/constraints/compiler:ldc",
+ ],
+ target_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ ],
+ toolchain = ":ldc_linux_x86_64",
+ toolchain_type = D_TOOLCHAIN,
)
-filegroup(
- name = "phobos-src",
- srcs = select({
- ":darwin": ["@dmd_darwin_x86_64//:phobos-src"],
- ":k8": ["@dmd_linux_x86_64//:phobos-src"],
- ":x64_windows": ["@dmd_windows_x86_64//:phobos-src"],
- }),
+d_toolchain(
+ name = "weka_ldc_linux_x86_64",
+ d_compiler = "@weka_ldc_linux_x86_64//:ldc2",
+ druntime = "@weka_ldc_linux_x86_64//:druntime",
+ druntime_src = "@weka_ldc_linux_x86_64//:druntime_src",
+ libphobos = "@weka_ldc_linux_x86_64//:libphobos2",
+ libphobos_src = "@weka_ldc_linux_x86_64//:phobos_src",
+ version_flag = "--d-version",
+ lib_flags = [
+ "-lib", "-oq",
+ ],
+ hdrgen_flags = [
+ "-Honly",
+ ],
+ debug_repo_root_override = "/source",
+ output_bc_flags = ["--output-bc"],
)
-filegroup(
- name = "druntime-import-src",
- srcs = select({
- ":darwin": ["@dmd_darwin_x86_64//:druntime-import-src"],
- ":k8": ["@dmd_linux_x86_64//:druntime-import-src"],
- ":x64_windows": ["@dmd_windows_x86_64//:druntime-import-src"],
- }),
+toolchain(
+ name = "weka_ldc_linux_x86_64_toolchain",
+ exec_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ "//d/constraints/compiler:weka-ldc",
+ ],
+ target_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ ],
+ toolchain = ":weka_ldc_linux_x86_64",
+ toolchain_type = D_TOOLCHAIN,
)
diff --git a/d/DMD.bzl b/d/DMD.bzl
new file mode 100644
index 0000000..3645d34
--- /dev/null
+++ b/d/DMD.bzl
@@ -0,0 +1,50 @@
+load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
+
+package(default_visibility = ["//visibility:public"])
+
+native_binary(
+ name = "dmd",
+ out = "dmdcopy.exe",
+ src = select({
+ "@bazel_tools//src/conditions:darwin": "osx/bin/dmd",
+ "@bazel_tools//src/conditions:linux_x86_64": "linux/bin64/dmd",
+ # "@bazel_tools//src/conditions:windows_x64": "windows/bin64/dmd.exe",
+ }),
+ data = select({
+ "@bazel_tools//src/conditions:darwin": ["osx/bin/dmd.conf"],
+ "@bazel_tools//src/conditions:linux_x86_64": ["linux/bin64/dmd.conf"],
+ # "@bazel_tools//src/conditions:windows_x64": glob(["windows/lib64/mingw/**"]) + [
+ # "windows/bin64/sc.ini",
+ # "windows/bin64/lld-link.exe",
+ # "windows/bin64/libcurl.dll",
+ # "windows/bin64/msvcr120.dll",
+ # "windows/lib64/curl.lib",
+ # ],
+ }),
+)
+
+cc_import(
+ name = "libphobos2",
+ # shared_library = select({
+ # "@bazel_tools//src/conditions:linux_x86_64": "linux/lib64/libphobos2.so",
+ # "//conditions:default": None,
+ # }),
+ static_library = select({
+ "@bazel_tools//src/conditions:darwin": "osx/lib/libphobos2.a",
+ "@bazel_tools//src/conditions:linux_x86_64": "linux/lib64/libphobos2.a",
+ # "@bazel_tools//src/conditions:windows_x64": "windows/lib64/phobos64.lib",
+ }),
+)
+
+filegroup(
+ name = "phobos_src",
+ srcs = glob(["src/phobos/**/*.*"]),
+)
+
+filegroup(
+ name = "druntime_src",
+ srcs = glob([
+ "src/druntime/import/*.*",
+ "src/druntime/import/**/*.*",
+ ]),
+)
diff --git a/d/LDC.bzl b/d/LDC.bzl
new file mode 100644
index 0000000..b89e096
--- /dev/null
+++ b/d/LDC.bzl
@@ -0,0 +1,62 @@
+load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
+
+package(default_visibility = ["//visibility:public"])
+
+native_binary(
+ name = "ldc2",
+ out = "ldc2copy.exe",
+ src = select({
+ "@bazel_tools//src/conditions:darwin": "bin/ldc2",
+ "@bazel_tools//src/conditions:linux_x86_64": "bin/ldc2",
+ # "@bazel_tools//src/conditions:windows_x64": "bin/ldc2.exe",
+ }),
+ # TODO: add the conf files to `data` field.
+)
+
+cc_import(
+ name = "libphobos2",
+ shared_library = select({
+ "@bazel_tools//src/conditions:darwin": "osx/lib/dmd",
+ "@bazel_tools//src/conditions:linux_x86_64": "lib/libphobos2-ldc-shared.so",
+ # "@bazel_tools//src/conditions:windows_x64": "lib/phobos2-ldc-shared.lib",
+ }),
+ static_library = select({
+ "@bazel_tools//src/conditions:darwin": "osx/lib/dmd",
+ "@bazel_tools//src/conditions:linux_x86_64": "lib/libphobos2-ldc.a",
+ # "@bazel_tools//src/conditions:windows_x64": "lib/phobos2-ldc.lib",
+ }),
+)
+
+cc_import(
+ name = "druntime",
+ shared_library = select({
+ "@bazel_tools//src/conditions:darwin": "osx/lib/dmd",
+ "@bazel_tools//src/conditions:linux_x86_64": "lib/libdruntime-ldc-shared.so",
+ # "@bazel_tools//src/conditions:windows_x64": "lib/druntime-ldc-shared.lib",
+ }),
+ static_library = select({
+ "@bazel_tools//src/conditions:darwin": "osx/lib/dmd",
+ "@bazel_tools//src/conditions:linux_x86_64": "lib/libdruntime-ldc.a",
+ # "@bazel_tools//src/conditions:windows_x64": "lib/druntime-ldc.lib",
+ }),
+)
+
+filegroup(
+ name = "phobos_src",
+ srcs = glob([
+ "import/std/**/*.*",
+ "import/std/*.*",
+ "import/etc/**/*.*",
+ # "import/etc/*.*",
+ ]),
+)
+
+filegroup(
+ name = "druntime_src",
+ srcs = glob([
+ "import/core/**/*.*",
+ "import/core/*.*",
+ "import/ldc/**/*.*",
+ "import/ldc/*.*",
+ ]),
+)
diff --git a/d/config.bzl b/d/config.bzl
new file mode 100644
index 0000000..dfdce8b
--- /dev/null
+++ b/d/config.bzl
@@ -0,0 +1,34 @@
+"""
+Configuration information for the D toolchain.
+"""
+
+DToolchainConfigInfo = provider(
+ doc = "Configuration information for the D toolchain.",
+ fields = [
+ # binaries
+ "d_compiler",
+ "c_compiler",
+ "llc_compiler",
+ # libraries
+ "libphobos",
+ "libphobos_src",
+ "druntime",
+ "druntime_src",
+ # flags that can differ for different toolchains
+ "lib_flags",
+ "import_flags", # unused
+ "version_flag",
+ "hdrgen_flags",
+ "output_bc_flags",
+ # compilation modes
+ "copts_per_mode",
+ "copts_common",
+ "linkopts_per_mode",
+ "linkopts_common",
+ "codegen_opts_common",
+ "codegen_opts_per_mode",
+ "global_versions_per_mode",
+ "global_versions_common",
+ "debug_repo_root_override",
+ ],
+)
diff --git a/d/constraints/compiler/BUILD b/d/constraints/compiler/BUILD
new file mode 100644
index 0000000..53d2e18
--- /dev/null
+++ b/d/constraints/compiler/BUILD
@@ -0,0 +1,21 @@
+package(default_visibility = ["//visibility:public"])
+
+constraint_setting(
+ name = "d_compiler",
+ default_constraint_value = ":dmd",
+)
+
+constraint_value(
+ name = "dmd",
+ constraint_setting = ":d_compiler",
+)
+
+constraint_value(
+ name = "ldc",
+ constraint_setting = ":d_compiler",
+)
+
+constraint_value(
+ name = "weka-ldc",
+ constraint_setting = ":d_compiler",
+)
diff --git a/d/d.bzl b/d/d.bzl
index 0d2696f..a1ef590 100644
--- a/d/d.bzl
+++ b/d/d.bzl
@@ -14,7 +14,7 @@
"""D rules for Bazel."""
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//d:toolchain.bzl", "D_TOOLCHAIN")
def _is_windows(ctx):
return ctx.configuration.host_path_separator == ";"
@@ -23,10 +23,20 @@ def a_filetype(ctx, files):
lib_suffix = ".lib" if _is_windows(ctx) else ".a"
return [f for f in files if f.basename.endswith(lib_suffix)]
-D_FILETYPE = [".d", ".di"]
+D_FILETYPE = [".d", ".di", ".h"] # TODO: restrict support of .di and .h files to source libraries
ZIP_PATH = "/usr/bin/zip"
+DInfo = provider()
+
+def _with_runfiles(tool):
+ """Returns a list of files _and_ runfiles for `tool`."""
+ files = tool.files.to_list()
+ runfiles = tool[DefaultInfo].default_runfiles
+ if runfiles:
+ files += runfiles.files.to_list()
+ return files
+
def _files_directory(files):
"""Returns the shortest parent directory of a list of files."""
dir = files[0].dirname
@@ -35,179 +45,371 @@ def _files_directory(files):
dir = f.dirname
return dir
-def _d_toolchain(ctx):
- """Returns a struct containing info about the D toolchain.
-
- Args:
- ctx: The ctx object.
-
- Return:
- Struct containing the following fields:
- d_compiler_path: The path to the D compiler.
- link_flags: Linker (-L) flags for adding the standard library to the
- library search paths.
- import_flags: import (-I) flags for adding the standard library sources
- to the import paths.
- """
-
- d_compiler_path = ctx.file._d_compiler.path
- return struct(
- d_compiler_path = d_compiler_path,
- link_flags = [("-L/LIBPATH:" if _is_windows(ctx) else "-L-L") + ctx.files._d_stdlib[0].dirname],
- import_flags = [
- "-I" + _files_directory(ctx.files._d_stdlib_src),
- "-I" + _files_directory(ctx.files._d_runtime_import_src),
- ],
- )
-
-COMPILATION_MODE_FLAGS_POSIX = {
+DEFAULT_COMPILATION_MODE_FLAGS_POSIX = {
"fastbuild": ["-g"],
- "dbg": ["-debug", "-g"],
+ "dbg": ["-d-debug", "-d-version=debug_assert", "-g"],
"opt": ["-checkaction=halt", "-boundscheck=safeonly", "-O"],
}
-COMPILATION_MODE_FLAGS_WINDOWS = {
+DEFAULT_COMPILATION_MODE_FLAGS_WINDOWS = {
"fastbuild": ["-g", "-m64", "-mscrtlib=msvcrt"],
"dbg": ["-debug", "-g", "-m64", "-mscrtlib=msvcrtd"],
- "opt": ["-checkaction=halt", "-boundscheck=safeonly", "-O",
- "-m64", "-mscrtlib=msvcrt"],
+ "opt": [
+ "-checkaction=halt",
+ "-boundscheck=safeonly",
+ "-O",
+ "-m64",
+ "-mscrtlib=msvcrt",
+ ],
}
-def _compilation_mode_flags(ctx):
- """Returns a list of flags based on the compilation_mode."""
+def _default_compilation_mode_flags(ctx):
+ """Returns the default compilation mode flags."""
if _is_windows(ctx):
- return COMPILATION_MODE_FLAGS_WINDOWS[ctx.var["COMPILATION_MODE"]]
+ return DEFAULT_COMPILATION_MODE_FLAGS_WINDOWS[ctx.var["COMPILATION_MODE"]]
+ else:
+ return DEFAULT_COMPILATION_MODE_FLAGS_POSIX[ctx.var["COMPILATION_MODE"]]
+
+def _compilation_mode_flags_helper(ctx):
+ """Helper function to return the flags for the compilation mode."""
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
+ compilation_mode = ctx.var["COMPILATION_MODE"]
+ default_flags = _default_compilation_mode_flags(ctx)
+ if compilation_mode == "dbg":
+ return toolchain.dbg_flags or default_flags
+ elif compilation_mode == "opt":
+ return toolchain.opt_flags or default_flags
+ elif compilation_mode == "fastbuild":
+ return toolchain.fastbuild_flags or default_flags
else:
- return COMPILATION_MODE_FLAGS_POSIX[ctx.var["COMPILATION_MODE"]]
+ fail("Invalid compilation mode: %s" % compilation_mode)
+
+def _compilation_mode_flags(ctx):
+ """Returns a list of flags based on the compilation mode."""
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
+ return (toolchain.common_flags or []) + _compilation_mode_flags_helper(ctx)
def _format_version(name):
"""Formats the string name to be used in a --version flag."""
return name.replace("-", "_")
-def _build_import(label, im):
+def _build_import(label, im, gen_dir = None):
"""Builds the import path under a specific label"""
import_path = ""
if label.workspace_root:
import_path += label.workspace_root + "/"
if label.package:
import_path += label.package + "/"
- import_path += im
+ if im == ".":
+ import_path = import_path[0:len(import_path) - 1]
+ else:
+ import_path += im
+ if gen_dir:
+ import_path = gen_dir + "/" + import_path
return import_path
def _build_compile_arglist(ctx, out, depinfo, extra_flags = []):
"""Returns a list of strings constituting the D compile command arguments."""
- toolchain = _d_toolchain(ctx)
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
+ version_flag = toolchain.version_flag
+ gen_dir = ctx.genfiles_dir.path if ctx.attr.is_generated else None
+
+ ws_root = gen_dir if ctx.attr.is_generated else "."
+
+ versions = depset(
+ toolchain.global_versions_common + toolchain.global_versions_per_mode[ctx.var["COMPILATION_MODE"]],
+ transitive = [depinfo.versions])
return (
_compilation_mode_flags(ctx) +
extra_flags + [
"-of" + out.path,
- "-I.",
"-w",
] +
- ["-I%s" % _build_import(ctx.label, im) for im in ctx.attr.imports] +
+ (toolchain.output_bc_flags if ctx.attr.compile_via_bc else []) +
+ (["-I%s" % ws_root] if ctx.attr.include_workspace_root else []) +
["-I%s" % im for im in depinfo.imports] +
- toolchain.import_flags +
- ["-version=Have_%s" % _format_version(ctx.label.name)] +
- ["-version=%s" % v for v in ctx.attr.versions] +
- ["-version=%s" % v for v in depinfo.versions]
+ ["-J%s" % im for im in depinfo.string_imports] +
+ # toolchain.import_flags +
+ [version_flag + "=%s" % v for v in versions.to_list()]
)
-def _build_link_arglist(ctx, objs, out, depinfo):
+def _sort_objects(objs, link_order):
+ """Sorts the objects in the order they need to be linked."""
+ if not link_order:
+ return [o.path for o in objs]
+ return [
+ obj.path for i, obj in sorted(enumerate(objs), key=lambda x: link_order.get(x[1].path, x[0]))
+ ]
+
+def _link_order_dict(objs, link_order):
+ """Builds a dictionary mapping object file paths to their link order index."""
+ if not link_order:
+ return {}
+ size = len(objs)
+ link_order_dict = dict()
+ for k, v in link_order.items():
+ idx = int(v)
+ if idx < 0:
+ idx = size - 1 - idx
+ for p in k.files.to_list():
+ link_order_dict[p.path] = idx
+ return link_order_dict
+
+def _build_link_arglist(ctx, objs, out, depinfo, c_compiler, link_flags, link_order):
"""Returns a list of strings constituting the D link command arguments."""
- toolchain = _d_toolchain(ctx)
+ if not ctx.attr.use_lto:
+ transitive_libs = [depinfo.libs, depinfo.transitive_libs]
+ else:
+ transitive_libs = [depinfo.libs_bc, depinfo.libs_non_bc, depinfo.transitive_libs_bc, depinfo.transitive_libs_non_bc]
+ all_objs = objs + depset(transitive = transitive_libs).to_list()
+ sorted_objs = _sort_objects(all_objs, _link_order_dict(all_objs, link_order))
return (
_compilation_mode_flags(ctx) +
+ (["-gcc=%s" % c_compiler.files.to_list()[0].path] if c_compiler else []) +
+ (link_flags or []) +
+ (["-L--dynamic-list=%s" % ctx.files.dynamic_symbols[0].path] if ctx.files.dynamic_symbols else []) +
["-of" + out.path] +
- toolchain.link_flags +
- [f.path for f in depset(transitive = [depinfo.libs, depinfo.transitive_libs]).to_list()] +
depinfo.link_flags +
- objs
+ sorted_objs
)
-def _setup_deps(ctx, deps, name, working_dir):
+def _find_gensrc_location(loc, src):
+ if loc.startswith("@"):
+ fail("Cannot place the generated source %s into location %s" % (
+ src, loc))
+ if loc.startswith("//"):
+ label = Label(loc)
+ return label.package + "/" + label.name
+ return src.label.package + "/" + loc
+
+def _setup_deps(ctx, deps, impl_deps, name):
"""Sets up dependencies.
Walks through dependencies and constructs the commands and flags needed
for linking the necessary dependencies.
Args:
+ ctx: The context of the current target.
deps: List of deps labels from ctx.attr.deps.
+ impl_deps: List of deps labels from ctx.attr.implementation_deps.
name: Name of the current target.
- working_dir: The output directory of the current target's output.
Returns:
Returns a struct containing the following fields:
libs: List of Files containing the target's direct library dependencies.
transitive_libs: List of Files containing all of the target's
transitive libraries.
+ transitive_bc_libs: List of transitive deps as bc files (where they exist)
+ transitive_non_bc_libs: List of transitive deps that don't exists as bc
d_srcs: List of Files representing D source files of dependencies that
will be used as inputs for this target.
versions: List of D versions to be used for compiling the target.
imports: List of Strings containing input paths that will be passed
to the D compiler via -I flags.
+ string_imports: List of strings containing input paths that will be
+ passed to the D compiler via -J flags.
link_flags: List of linker flags.
+ generated_srcs: A dictionary mapping generated files to their
+ desired locations.
+ data: List of Files containing extra (non-source) files that will
+ be used as inputs for this target.
"""
+ gen_dir = ctx.genfiles_dir.path
libs = []
+ libs_bc = []
+ libs_non_bc = []
transitive_libs = []
+ transitive_libs_bc = []
+ transitive_libs_non_bc = []
d_srcs = []
+ data = []
transitive_d_srcs = []
- versions = []
- imports = []
+ transitive_data = []
+ versions = ctx.attr.versions + ["Have_%s" % _format_version(name)]
+ transitive_versions = []
+ gen_dir_for_imports = gen_dir if ctx.attr.is_generated else None
+ imports = [_build_import(ctx.label, im, gen_dir_for_imports) for im in ctx.attr.imports]
+ string_imports = [_build_import(ctx.label, im, gen_dir_for_imports) for im in ctx.attr.string_imports]
link_flags = []
+ generated_srcs = {
+ src.files.to_list()[0]: _find_gensrc_location(loc, src) for src, loc in ctx.attr.generated_srcs.items()}
for dep in deps:
- if hasattr(dep, "d_lib"):
+ if DInfo in dep and hasattr(dep[DInfo], "d_lib"):
# The dependency is a d_library.
- libs.append(dep.d_lib)
- transitive_libs.append(dep.transitive_libs)
- d_srcs += dep.d_srcs
- transitive_d_srcs.append(dep.transitive_d_srcs)
- versions += dep.versions + ["Have_%s" % _format_version(dep.label.name)]
- link_flags.extend(dep.link_flags)
- imports += [_build_import(dep.label, im) for im in dep.imports]
-
- elif hasattr(dep, "d_srcs"):
+ ddep = dep[DInfo]
+ if ddep.d_lib:
+ libs.append(ddep.d_lib)
+ if ddep.d_lib_bc:
+ libs_bc.append(ddep.d_lib_bc)
+ else:
+ libs_non_bc.append(ddep.d_lib)
+ transitive_libs.append(ddep.transitive_libs)
+ transitive_libs_bc.append(ddep.transitive_libs_bc)
+ transitive_libs_non_bc.append(ddep.transitive_libs_non_bc)
+
+ d_srcs += ddep.d_exports
+ transitive_d_srcs.append(ddep.transitive_d_srcs)
+ data += ddep.data
+ transitive_data.append(ddep.transitive_data)
+ transitive_versions.append(ddep.versions)
+ link_flags.extend(ddep.link_flags)
+ link_flags += ["-L%s" % linkopt for linkopt in ddep.linkopts]
+ imports += ddep.imports
+ if ddep.is_generated:
+ imports.append(gen_dir)
+ string_imports += ddep.string_imports
+ generated_srcs = generated_srcs | ddep.generated_srcs
+
+ elif DInfo in dep and hasattr(dep[DInfo], "d_srcs"):
# The dependency is a d_source_library.
- d_srcs += dep.d_srcs
- transitive_d_srcs.append(dep.transitive_d_srcs)
- transitive_libs.append(dep.transitive_libs)
- link_flags += ["-L%s" % linkopt for linkopt in dep.linkopts]
- imports += [_build_import(dep.label, im) for im in dep.imports]
- versions += dep.versions
+ ddep = dep[DInfo]
+ d_srcs += ddep.d_srcs
+ transitive_d_srcs.append(ddep.transitive_d_srcs)
+ data += ddep.data
+ transitive_data.append(ddep.transitive_data)
+ transitive_libs.append(ddep.transitive_libs)
+ transitive_libs_bc.append(ddep.transitive_libs_bc)
+ transitive_libs_non_bc.append(ddep.transitive_libs_non_bc)
+ link_flags += ["-L%s" % linkopt for linkopt in ddep.linkopts]
+ imports += ddep.imports
+ if ddep.is_generated:
+ imports.append(gen_dir)
+ string_imports += ddep.string_imports
+ transitive_versions.append(ddep.versions)
+ generated_srcs = generated_srcs | ddep.generated_srcs
elif CcInfo in dep:
# The dependency is a cc_library
native_libs = a_filetype(ctx, _get_libs_for_static_executable(dep))
libs.extend(native_libs)
+ libs_non_bc.extend(native_libs)
transitive_libs.append(depset(native_libs))
+ transitive_libs_non_bc.append(depset(native_libs))
else:
fail("D targets can only depend on d_library, d_source_library, or " +
- "cc_library targets.", "deps")
+ "cc_library targets.", dep)
+
+ impl_srcs = []
+ for dep in impl_deps:
+ if DInfo in dep and hasattr(dep[DInfo], "d_lib"):
+ ddep = dep[DInfo]
+ libs.append(ddep.d_lib)
+ if ddep.d_lib_bc:
+ libs_bc.append(ddep.d_lib_bc)
+ else:
+ libs_non_bc.append(ddep.d_lib)
+ transitive_libs.append(ddep.transitive_libs)
+ transitive_libs_bc.append(ddep.transitive_libs_bc)
+ transitive_libs_non_bc.append(ddep.transitive_libs_non_bc)
+ impl_srcs.extend(ddep.d_exports)
+ elif CcInfo in dep:
+ native_libs = a_filetype(ctx, _get_libs_for_static_executable(dep))
+ libs.extend(native_libs)
+ libs_non_bc.extend(native_libs)
+ transitive_libs.append(depset(native_libs))
+ transitive_libs_non_bc.append(depset(native_libs))
+ else:
+ fail("Implementation dependencies can only depend on d_library or cc_library targets.", dep)
return struct(
libs = depset(libs),
+ libs_bc = depset(libs_bc),
+ libs_non_bc = depset(libs_non_bc),
transitive_libs = depset(transitive = transitive_libs),
- d_srcs = depset(d_srcs).to_list(),
- transitive_d_srcs = depset(transitive = transitive_d_srcs),
- versions = versions,
+ transitive_libs_bc = depset(transitive = transitive_libs_bc),
+ transitive_libs_non_bc = depset(transitive = transitive_libs_non_bc),
+ transitive_d_srcs = depset(d_srcs, transitive = transitive_d_srcs),
+ data = depset(data).to_list(),
+ transitive_data = depset(transitive = transitive_data),
+ versions = depset(versions, transitive = transitive_versions),
imports = depset(imports).to_list(),
+ string_imports = depset(string_imports).to_list(),
link_flags = depset(link_flags).to_list(),
+ generated_srcs = generated_srcs,
+ impl_srcs = impl_srcs,
)
-def _d_library_impl(ctx):
+def _handle_generated_srcs(ctx, generated_srcs, d_compiler, debug_repo_root_override):
+ """Handles the generated source files."""
+ if not generated_srcs and not debug_repo_root_override:
+ return (ctx.files.srcs, None)
+ mapped_srcs = [src if src not in generated_srcs else generated_srcs[src] for src in ctx.files.srcs]
+
+ wrapper = ctx.actions.declare_file(ctx.label.name + "_d_compile_wrapper.sh")
+ debug_prefix_map = "-fdebug-prefix-map=$PWD=%s " % debug_repo_root_override if debug_repo_root_override else ""
+ ctx.actions.write(
+ output = wrapper,
+ content = "\n".join(
+ [
+ "#!/bin/bash",
+ "set -e",
+ ] +
+ [
+ "mkdir -p $(dirname %s)\n" % loc +
+ "[ -f $PWD/%s ] && ln -s $PWD/%s %s" % (src.path, src.path, loc) for src, loc in generated_srcs.items()
+ ] + [
+ "%s %s$*" % (d_compiler.path, debug_prefix_map),
+ ]),
+ is_executable = True,
+ )
+
+ return (mapped_srcs, wrapper)
+
+def _d_library_impl_common(ctx, extra_flags = []):
"""Implementation of the d_library rule."""
- d_lib = ctx.actions.declare_file((ctx.label.name + ".lib") if _is_windows(ctx) else ("lib" + ctx.label.name + ".a"))
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
+ d_compiler = toolchain.d_compiler.files.to_list()[0]
+
+ if ctx.attr.compile_via_bc and not toolchain.output_bc_flags:
+ fail("'compile_via_bc' requires a toolchain with 'output_bc_flags' set")
# Dependencies
- depinfo = _setup_deps(ctx, ctx.attr.deps, ctx.label.name, d_lib.dirname)
+ deps = ctx.attr.deps + ([toolchain.libphobos] if toolchain.libphobos != None else []) + ([toolchain.druntime] if toolchain.druntime != None else [])
+ depinfo = _setup_deps(ctx, ctx.attr.deps, ctx.attr.implementation_deps, ctx.label.name)
+
+ public_srcs = ctx.files.hdrs + ctx.files.exports
+ if not public_srcs:
+ public_srcs = ctx.files.srcs
+
+ if not ctx.files.srcs:
+ return [
+ DefaultInfo(
+ files = depset(),
+ ),
+ DInfo(
+ d_srcs = ctx.files.srcs,
+ d_exports = public_srcs,
+ transitive_d_srcs = depinfo.transitive_d_srcs,
+ data = ctx.files.data,
+ transitive_data = depset(depinfo.data, transitive = [depinfo.transitive_data]),
+ transitive_libs = depset(transitive = [depinfo.libs, depinfo.transitive_libs]),
+ transitive_libs_bc = depset(transitive = [depinfo.libs_bc, depinfo.transitive_libs_bc]),
+ transitive_libs_non_bc = depset(transitive = [depinfo.libs_non_bc, depinfo.transitive_libs_non_bc]),
+ link_flags = depinfo.link_flags,
+ linkopts = ctx.attr.linkopts,
+ versions = depinfo.versions,
+ imports = depinfo.imports,
+ string_imports = depinfo.string_imports,
+ d_lib = "", # TODO: we only need it to distinguish from d_source_library. Either drop d_source_library or make another provider for it.
+ is_generated = ctx.attr.is_generated,
+ generated_srcs = depinfo.generated_srcs,
+ ),
+ ]
+
+ #d_lib = ctx.actions.declare_file((ctx.label.name + ".lib") if _is_windows(ctx) else ("lib" + ctx.label.name + ".a"))
+ d_lib = ctx.actions.declare_file(ctx.label.name + ".o")
+ d_lib_bc = None
+ if ctx.attr.compile_via_bc:
+ d_lib_bc = ctx.actions.declare_file(ctx.label.name + ".bc.o")
# Build compile command.
compile_args = _build_compile_arglist(
ctx = ctx,
- out = d_lib,
+ out = d_lib if not d_lib_bc else d_lib_bc,
depinfo = depinfo,
- extra_flags = ["-lib"],
+ extra_flags = ["-c"] + extra_flags,
)
# Convert sources to args
@@ -215,115 +417,218 @@ def _d_library_impl(ctx):
# args will auto-expand this to the contained files
args = ctx.actions.args()
args.add_all(compile_args)
- args.add_all(ctx.files.srcs)
+ mapped_srcs, generated_srcs_wrapper = _handle_generated_srcs(ctx, depinfo.generated_srcs, d_compiler, toolchain.debug_repo_root_override)
+
+ args.add_all(mapped_srcs)
+
+ phobos_files = toolchain.libphobos.files if toolchain.libphobos != None else depset()
+ phobos_src_files = toolchain.libphobos_src.files if toolchain.libphobos_src != None else depset()
+ druntime_src_files = toolchain.druntime_src.files if toolchain.druntime_src != None else depset()
+ # TODO: Should they be in transitive?
compile_inputs = depset(
ctx.files.srcs +
- depinfo.d_srcs +
- ctx.files._d_stdlib +
- ctx.files._d_stdlib_src +
- ctx.files._d_runtime_import_src,
+ ctx.files.hdrs +
+ ctx.files.exports +
+ ctx.files.data +
+ depinfo.data +
+ depinfo.impl_srcs,
transitive = [
depinfo.transitive_d_srcs,
- depinfo.libs,
- depinfo.transitive_libs,
+ depinfo.transitive_data,
+ phobos_files,
+ phobos_src_files,
+ druntime_src_files,
],
)
+ executable = generated_srcs_wrapper if generated_srcs_wrapper else d_compiler
ctx.actions.run(
inputs = compile_inputs,
- tools = [ctx.file._d_compiler],
- outputs = [d_lib],
+ tools = _with_runfiles(toolchain.d_compiler) + ([generated_srcs_wrapper] if generated_srcs_wrapper else []),
+ outputs = [d_lib] if not d_lib_bc else [d_lib_bc],
mnemonic = "Dcompile",
- executable = ctx.file._d_compiler.path,
+ executable = executable,
arguments = [args],
use_default_shell_env = True,
progress_message = "Compiling D library " + ctx.label.name,
)
- return struct(
- files = depset([d_lib]),
- d_srcs = ctx.files.srcs,
- transitive_d_srcs = depset(depinfo.d_srcs),
- transitive_libs = depset(transitive = [depinfo.libs, depinfo.transitive_libs]),
- link_flags = depinfo.link_flags,
- versions = ctx.attr.versions,
- imports = ctx.attr.imports,
- d_lib = d_lib,
- )
+ if d_lib_bc:
+ # need to compile .bc.o -> .o in an extra step
+ codegen_flags = toolchain.codegen_common_flags + toolchain.codegen_per_mode_flags[ctx.var["COMPILATION_MODE"]]
+ # this is a hack, just hoping there is some llc is not good
+ # TODO: enforce this is only used with toolchain.llc_compiler
+ # This also _could_ be clang, but aligning LDC backend options with
+ # clang ones is non-trivial, whereas llc has exactly the same options
+ # as ldc does.
+ llc = toolchain.llc_compiler.files.to_list()[0] if toolchain.llc_compiler else "llc"
+ ctx.actions.run(
+ inputs = [d_lib_bc],
+ tools = _with_runfiles(toolchain.llc_compiler) if toolchain.llc_compiler else [],
+ outputs = [d_lib],
+ executable = llc,
+ arguments = codegen_flags + ["--filetype=obj", "-o", d_lib.path, d_lib_bc.path],
+ use_default_shell_env = True,
+ progress_message = "Compiling bitcode for D library " + ctx.label.name,
+ )
+ return [
+ DefaultInfo(
+ files = depset([d_lib]),
+ ),
+ DInfo(
+ d_srcs = ctx.files.srcs,
+ d_exports = public_srcs,
+ transitive_d_srcs = depinfo.transitive_d_srcs,
+ data = ctx.files.data,
+ transitive_data = depset(depinfo.data, transitive = [depinfo.transitive_data]),
+ transitive_libs = depset(transitive = [depinfo.libs, depinfo.transitive_libs]),
+ transitive_libs_bc = depset(transitive = [depinfo.libs_bc, depinfo.transitive_libs_bc]),
+ transitive_libs_non_bc = depset(transitive = [depinfo.libs_non_bc, depinfo.transitive_libs_non_bc]),
+ link_flags = depinfo.link_flags,
+ linkopts = ctx.attr.linkopts,
+ versions = depinfo.versions,
+ imports = depinfo.imports,
+ string_imports = depinfo.string_imports,
+ d_lib = d_lib,
+ d_lib_bc = d_lib_bc,
+ is_generated = ctx.attr.is_generated,
+ generated_srcs = depinfo.generated_srcs,
+ ),
+ ]
def _d_binary_impl_common(ctx, extra_flags = []):
"""Common implementation for rules that build a D binary."""
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
d_bin = ctx.actions.declare_file(ctx.label.name + ".exe" if _is_windows(ctx) else ctx.label.name)
- d_obj = ctx.actions.declare_file(ctx.label.name + (".obj" if _is_windows(ctx) else ".o"))
- depinfo = _setup_deps(ctx, ctx.attr.deps, ctx.label.name, d_bin.dirname)
-
- # Build compile command
- compile_args = _build_compile_arglist(
- ctx = ctx,
- depinfo = depinfo,
- out = d_obj,
- extra_flags = ["-c"] + extra_flags,
- )
-
- # Convert sources to args
- # This is done to support receiving a File that is a directory, as
- # args will auto-expand this to the contained files
- args = ctx.actions.args()
- args.add_all(compile_args)
- args.add_all(ctx.files.srcs)
-
- toolchain_files = (
- ctx.files._d_stdlib +
- ctx.files._d_stdlib_src +
- ctx.files._d_runtime_import_src
- )
-
- compile_inputs = depset(
- ctx.files.srcs + depinfo.d_srcs + toolchain_files,
- transitive = [depinfo.transitive_d_srcs],
- )
- ctx.actions.run(
- inputs = compile_inputs,
- tools = [ctx.file._d_compiler],
- outputs = [d_obj],
- mnemonic = "Dcompile",
- executable = ctx.file._d_compiler.path,
- arguments = [args],
- use_default_shell_env = True,
- progress_message = "Compiling D binary " + ctx.label.name,
- )
+ d_compiler = toolchain.d_compiler.files.to_list()[0]
+ # Dependencies
+ deps = ctx.attr.deps + ([toolchain.libphobos] if toolchain.libphobos != None else []) + ([toolchain.druntime] if toolchain.druntime != None else [])
+ depinfo = _setup_deps(ctx, deps, [], ctx.label.name)
+
+ d_obj = None
+ toolchain_files = [
+ toolchain.libphobos.files if toolchain.libphobos != None else depset(),
+ toolchain.libphobos_src.files if toolchain.libphobos_src != None else depset(),
+ toolchain.druntime_src.files if toolchain.druntime_src != None else depset(),
+ ]
+
+ d_obj_bc = None
+ if ctx.files.srcs:
+ if ctx.attr.compile_via_bc or ctx.attr.use_lto:
+ if not toolchain.output_bc_flags:
+ fail("'compile_via_bc' and 'use_lto' require a toolchain with 'output_bc_flags' set")
+ d_obj_bc = ctx.actions.declare_file(ctx.label.name + ".bc.o")
+
+ d_obj = ctx.actions.declare_file(ctx.label.name + (".obj" if _is_windows(ctx) else ".o"))
+ # Build compile command
+ compile_args = _build_compile_arglist(
+ ctx = ctx,
+ depinfo = depinfo,
+ out = d_obj if not d_obj_bc else d_obj_bc,
+ extra_flags = ["-c"] + extra_flags,
+ )
+
+ # Convert sources to args
+ # This is done to support receiving a File that is a directory, as
+ # args will auto-expand this to the contained files
+ args = ctx.actions.args()
+ args.add_all(compile_args)
+
+ mapped_srcs, generated_srcs_wrapper = _handle_generated_srcs(ctx, depinfo.generated_srcs, d_compiler, toolchain.debug_repo_root_override)
+
+ args.add_all(mapped_srcs)
+
+ compile_inputs = depset(
+ ctx.files.srcs + ctx.files.data + depinfo.data,
+ transitive = [depinfo.transitive_d_srcs, depinfo.transitive_data] + toolchain_files,
+ )
+ ctx.actions.run(
+ inputs = compile_inputs,
+ tools = _with_runfiles(toolchain.d_compiler) + ([generated_srcs_wrapper] if generated_srcs_wrapper else []),
+ outputs = [d_obj] if not d_obj_bc else [d_obj_bc],
+ mnemonic = "Dcompile",
+ executable = generated_srcs_wrapper if generated_srcs_wrapper else d_compiler,
+ arguments = [args],
+ use_default_shell_env = True,
+ progress_message = "Compiling D binary " + ctx.label.name,
+ )
+
+ if d_obj_bc:
+ # TODO: this code is almost exactly the same as in d_library
+ # need to compile .bc.o -> .o in an extra step
+ codegen_flags = toolchain.codegen_common_flags + toolchain.codegen_per_mode_flags[ctx.var["COMPILATION_MODE"]]
+ # this is a hack, just hoping there is some llc is not good
+ # TODO: enforce this is only used with toolchain.llc_compiler
+ # This also _could_ be clang, but aligning LDC backend options with
+ # clang ones is non-trivial, whereas llc has exactly the same options
+ # as ldc does.
+ llc = toolchain.llc_compiler.files.to_list()[0] if toolchain.llc_compiler else "llc"
+ ctx.actions.run(
+ inputs = [d_obj_bc],
+ tools = _with_runfiles(toolchain.llc_compiler) if toolchain.llc_compiler else [],
+ outputs = [d_obj],
+ executable = llc,
+ arguments = codegen_flags + ["--filetype=obj", "-o", d_obj.path, d_obj_bc.path],
+ use_default_shell_env = True,
+ progress_message = "Compiling bitcode for D binary " + ctx.label.name,
+ )
+
+ obj = d_obj_bc if ctx.attr.use_lto else d_obj
# Build link command
link_args = _build_link_arglist(
ctx = ctx,
- objs = [d_obj.path],
+ objs = [obj] if obj else [],
depinfo = depinfo,
out = d_bin,
+ c_compiler = toolchain.c_compiler,
+ link_flags = toolchain.link_flags + ["-L%s" % linkopt for linkopt in ctx.attr.linkopts],
+ link_order = ctx.attr.link_order,
)
+ if ctx.attr.use_lto:
+ libs = [depinfo.libs_bc, depinfo.libs_non_bc, depinfo.transitive_libs_bc, depinfo.transitive_libs_non_bc]
+ else:
+ libs = [depinfo.libs, depinfo.transitive_libs]
link_inputs = depset(
- [d_obj] + toolchain_files,
- transitive = [depinfo.libs, depinfo.transitive_libs],
+ ([obj] if obj else []) + ([ctx.files.dynamic_symbols[0]] if ctx.files.dynamic_symbols else []),
+ transitive = libs + toolchain_files,
)
ctx.actions.run(
inputs = link_inputs,
- tools = [ctx.file._d_compiler],
+ tools = _with_runfiles(toolchain.d_compiler) + (_with_runfiles(toolchain.c_compiler) if toolchain.c_compiler else []),
outputs = [d_bin],
mnemonic = "Dlink",
- executable = ctx.file._d_compiler.path,
+ executable = d_compiler,
arguments = link_args,
use_default_shell_env = True,
- progress_message = "Linking D binary " + ctx.label.name,
+ progress_message = "Linking " + ("(with LTO) " if ctx.attr.use_lto else "") + "D binary " + ctx.label.name,
)
- return struct(
- d_srcs = ctx.files.srcs,
- transitive_d_srcs = depset(depinfo.d_srcs),
- imports = ctx.attr.imports,
- executable = d_bin,
- )
+ return [
+ DInfo(
+ d_srcs = ctx.files.srcs,
+ transitive_d_srcs = depinfo.transitive_d_srcs,
+ data = ctx.files.data,
+ transitive_data = depset(depinfo.data),
+ imports = ctx.attr.imports,
+ string_imports = ctx.attr.string_imports,
+ ),
+ DefaultInfo(
+ executable = d_bin,
+ ),
+ ]
+
+def _d_library_impl(ctx):
+ """Implementation of the d_library rule."""
+ return _d_library_impl_common(ctx)
+
+def _d_test_library_impl(ctx):
+ """Implementation of the d_test_library rule."""
+ # A test library is just a d_library with testonly=True
+ return _d_library_impl_common(ctx, extra_flags=["-unittest"])
def _d_binary_impl(ctx):
"""Implementation of the d_binary rule."""
@@ -358,19 +663,32 @@ def _get_libs_for_static_executable(dep):
def _d_source_library_impl(ctx):
"""Implementation of the d_source_library rule."""
transitive_d_srcs = []
+ transitive_data = []
transitive_libs = []
transitive_transitive_libs = []
+ transitive_transitive_libs_bc = []
+ transitive_transitive_libs_non_bc = []
transitive_imports = depset()
+ transitive_string_imports = depset()
transitive_linkopts = depset()
transitive_versions = depset()
+ generated_srcs = {
+ src.files.to_list()[0]: src.label.package + "/" + loc for src, loc in ctx.attr.generated_srcs.items()}
for dep in ctx.attr.deps:
- if hasattr(dep, "d_srcs"):
+ if DInfo in dep and hasattr(dep[DInfo], "d_srcs") and not hasattr(dep[DInfo], "d_lib"):
# Dependency is another d_source_library target.
- transitive_d_srcs.append(dep.d_srcs)
- transitive_imports = depset(dep.imports, transitive = [transitive_imports])
- transitive_linkopts = depset(dep.linkopts, transitive = [transitive_linkopts])
- transitive_versions = depset(dep.versions, transitive = [transitive_versions])
- transitive_transitive_libs.append(dep.transitive_libs)
+ # TODO: Could we also support d_library here?
+ ddep = dep[DInfo]
+ transitive_d_srcs.append(depset(ddep.d_srcs, transitive = [ddep.transitive_d_srcs]))
+ transitive_data.append(depset(ddep.data))
+ transitive_imports = depset(ddep.imports, transitive = [transitive_imports])
+ transitive_string_imports = depset(ddep.string_imports, transitive = [transitive_string_imports])
+ transitive_linkopts = depset(ddep.linkopts, transitive = [transitive_linkopts])
+ transitive_versions = depset(transitive = [ddep.versions, transitive_versions])
+ transitive_transitive_libs.append(ddep.transitive_libs)
+ transitive_transitive_libs_bc.append(ddep.transitive_libs_bc)
+ transitive_transitive_libs_non_bc.append(ddep.transitive_libs_non_bc)
+ generated_srcs = generated_srcs | ddep.generated_srcs
elif CcInfo in dep:
# Dependency is a cc_library target.
@@ -381,14 +699,25 @@ def _d_source_library_impl(ctx):
fail("d_source_library can only depend on other " +
"d_source_library or cc_library targets.", "deps")
- return struct(
- d_srcs = ctx.files.srcs,
- transitive_d_srcs = depset(transitive = transitive_d_srcs, order = "postorder"),
- transitive_libs = depset(transitive_libs, transitive = transitive_transitive_libs),
- imports = ctx.attr.imports + transitive_imports.to_list(),
- linkopts = ctx.attr.linkopts + transitive_linkopts.to_list(),
- versions = ctx.attr.versions + transitive_versions.to_list(),
- )
+ gen_dir = ctx.genfiles_dir.path if ctx.attr.is_generated else None
+
+ return [
+ DInfo(
+ d_srcs = ctx.files.srcs,
+ data = ctx.files.data,
+ transitive_d_srcs = depset(transitive = transitive_d_srcs, order = "postorder"),
+ transitive_data = depset(transitive = transitive_data, order = "postorder"),
+ transitive_libs = depset(transitive_libs, transitive = transitive_transitive_libs),
+ transitive_libs_bc = depset(transitive_libs, transitive = transitive_transitive_libs_bc),
+ transitive_libs_non_bc = depset(transitive_libs, transitive = transitive_transitive_libs_non_bc),
+ imports = [_build_import(ctx.label, im, gen_dir) for im in ctx.attr.imports] + transitive_imports.to_list(),
+ string_imports = [_build_import(ctx.label, im, gen_dir) for im in ctx.attr.string_imports] + transitive_string_imports.to_list(),
+ linkopts = ctx.attr.linkopts + transitive_linkopts.to_list(),
+ versions = depset(ctx.attr.versions, transitive = [transitive_versions]),
+ is_generated = ctx.attr.is_generated,
+ generated_srcs = generated_srcs,
+ ),
+ ]
# TODO(dzc): Use ddox for generating HTML documentation.
def _d_docs_impl(ctx):
@@ -406,19 +735,21 @@ def _d_docs_impl(ctx):
target = struct(
name = ctx.attr.dep.label.name,
- srcs = ctx.attr.dep.d_srcs,
- transitive_srcs = ctx.attr.dep.transitive_d_srcs,
- imports = ctx.attr.dep.imports,
+ srcs = ctx.attr.dep[DInfo].d_srcs,
+ transitive_srcs = ctx.attr.dep[DInfo].transitive_d_srcs,
+ imports = ctx.attr.dep[DInfo].imports,
)
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
+ d_compiler = toolchain.d_compiler.files.to_list()[0]
+
# Build D docs command
- toolchain = _d_toolchain(ctx)
doc_cmd = (
[
"set -e;",
"rm -rf %s; mkdir -p %s;" % (docs_dir, docs_dir),
"rm -rf %s; mkdir -p %s;" % (objs_dir, objs_dir),
- toolchain.d_compiler_path,
+ d_compiler.path,
"-c",
"-D",
"-Dd%s" % docs_dir,
@@ -426,7 +757,7 @@ def _d_docs_impl(ctx):
"-I.",
] +
["-I%s" % _build_import(ctx.label, im) for im in target.imports] +
- toolchain.import_flags +
+ # toolchain.import_flags +
[src.path for src in target.srcs] +
[
"&&",
@@ -439,15 +770,16 @@ def _d_docs_impl(ctx):
]
)
- toolchain_files = (
- ctx.files._d_stdlib +
- ctx.files._d_stdlib_src +
- ctx.files._d_runtime_import_src
- )
- ddoc_inputs = depset(target.srcs + toolchain_files, transitive = [target.transitive_srcs])
+ toolchain_files = [
+ toolchain.libphobos.files if toolchain.libphobos != None else depset(),
+ toolchain.libphobos_src.files if toolchain.libphobos_src != None else depset(),
+ toolchain.druntime_src.files if toolchain.druntime_src != None else depset(),
+ ]
+
+ ddoc_inputs = depset(target.srcs, transitive = [target.transitive_srcs] + toolchain_files)
ctx.actions.run_shell(
inputs = ddoc_inputs,
- tools = [ctx.file._d_compiler],
+ tools = _with_runfiles(toolchain.d_compiler),
outputs = [d_docs_zip],
mnemonic = "Ddoc",
command = " ".join(doc_cmd),
@@ -455,53 +787,128 @@ def _d_docs_impl(ctx):
progress_message = "Generating D docs for " + ctx.label.name,
)
+def _d_header_generator_impl(ctx):
+ """Implementation of the d_header_generator rule."""
+ toolchain = ctx.toolchains[D_TOOLCHAIN]
+ if not toolchain.hdrgen_flags:
+ fail("d_header_generator requires a toolchain with hdrgen_flags set.")
+
+ d_compiler = toolchain.d_compiler.files.to_list()[0]
+
+ infile = ctx.file.src
+ if not infile:
+ fail("d_header_generator requires a single source file.")
+
+ if not infile.path.endswith(".d"):
+ fail("d_header_generator only supports .d files, got: %s" % infile.path)
+
+ header = ctx.actions.declare_file(ctx.label.name + ".di")
+
+ ctx.actions.run(
+ inputs = [ctx.file.src],
+ tools = _with_runfiles(toolchain.d_compiler),
+ outputs = [header],
+ mnemonic = "Dhdrgen",
+ executable = d_compiler,
+ arguments = toolchain.hdrgen_flags + [infile.path, "--Hf", header.path],
+ use_default_shell_env = True,
+ progress_message = "Generating D header for " + ctx.label.name,
+ )
+ return [
+ DefaultInfo(
+ files = depset([header]),
+ ),
+ DInfo(
+ d_exports = [header]
+ ),
+ ]
+
_d_common_attrs = {
"srcs": attr.label_list(allow_files = D_FILETYPE),
"imports": attr.string_list(),
+ "string_imports": attr.string_list(),
+ "data": attr.label_list(allow_files = True),
"linkopts": attr.string_list(),
"versions": attr.string_list(),
+ "include_workspace_root": attr.bool(default = True),
+ "is_generated": attr.bool(default = False),
+ "generated_srcs": attr.label_keyed_string_dict(allow_files = True),
+ "compile_via_bc": attr.bool(default = False),
"deps": attr.label_list(),
}
-_d_compile_attrs = {
- "_d_compiler": attr.label(
- default = Label("//d:dmd"),
- executable = True,
- allow_single_file = True,
- cfg = "exec",
- ),
- "_d_runtime_import_src": attr.label(
- default = Label("//d:druntime-import-src"),
- ),
- "_d_stdlib": attr.label(
- default = Label("//d:libphobos2"),
- ),
- "_d_stdlib_src": attr.label(
- default = Label("//d:phobos-src"),
- ),
+_d_library_attrs = {
+ "hdrs": attr.label_list(allow_files = D_FILETYPE, allow_empty = True),
+ "exports": attr.label_list(allow_files = D_FILETYPE),
+ "implementation_deps": attr.label_list(),
}
+_d_binary_attrs = {
+ "dynamic_symbols" : attr.label(allow_files = True),
+ "link_order": attr.label_keyed_string_dict(),
+ "use_lto": attr.bool(default = False),
+}
+
+# _d_compile_attrs = {
+# "_d_compiler": attr.label(
+# default = Label("//d:dmd"),
+# executable = True,
+# allow_single_file = True,
+# cfg = "host",
+# ),
+# "_d_runtime_import_src": attr.label(
+# default = Label("//d:druntime-import-src"),
+# ),
+# "_d_stdlib": attr.label(
+# default = Label("//d:libphobos2"),
+# ),
+# "_d_stdlib_src": attr.label(
+# default = Label("//d:phobos-src"),
+# ),
+# }
+
d_library = rule(
_d_library_impl,
- attrs = dict(_d_common_attrs.items() + _d_compile_attrs.items()),
+ attrs = dict(_d_common_attrs.items() + _d_library_attrs.items()),
+ toolchains = [D_TOOLCHAIN],
+)
+
+d_test_library = rule(
+ _d_test_library_impl,
+ attrs = dict(_d_common_attrs.items() + _d_library_attrs.items()),
+ toolchains = [D_TOOLCHAIN],
+)
+
+d_header_generator = rule(
+ _d_header_generator_impl,
+ attrs = {
+ "src": attr.label(
+ mandatory = True,
+ allow_single_file = [".d"],
+ ),
+ },
+ toolchains = [D_TOOLCHAIN],
)
d_source_library = rule(
_d_source_library_impl,
attrs = _d_common_attrs,
+ toolchains = [D_TOOLCHAIN],
)
d_binary = rule(
_d_binary_impl,
- attrs = dict(_d_common_attrs.items() + _d_compile_attrs.items()),
+ attrs = dict(_d_common_attrs.items() + _d_binary_attrs.items()),
executable = True,
+ toolchains = [D_TOOLCHAIN],
)
d_test = rule(
_d_test_impl,
- attrs = dict(_d_common_attrs.items() + _d_compile_attrs.items()),
+ attrs = dict(_d_common_attrs.items() + _d_binary_attrs.items()),
executable = True,
test = True,
+ toolchains = [D_TOOLCHAIN],
)
_d_docs_attrs = {
@@ -510,89 +917,132 @@ _d_docs_attrs = {
d_docs = rule(
_d_docs_impl,
- attrs = dict(_d_docs_attrs.items() + _d_compile_attrs.items()),
+ attrs = dict(_d_docs_attrs.items()),
outputs = {
"d_docs": "%{name}-docs.zip",
},
+ toolchains = [D_TOOLCHAIN],
)
-DMD_BUILD_FILE = """
-package(default_visibility = ["//visibility:public"])
-
-config_setting(
- name = "darwin",
- values = {"host_cpu": "darwin"},
-)
-
-config_setting(
- name = "k8",
- values = {"host_cpu": "k8"},
-)
-
-config_setting(
- name = "x64_windows",
- values = {"host_cpu": "x64_windows"},
-)
-
-filegroup(
- name = "dmd",
- srcs = select({
- ":darwin": ["dmd2/osx/bin/dmd"],
- ":k8": ["dmd2/linux/bin64/dmd"],
- ":x64_windows": ["dmd2/windows/bin64/dmd.exe"],
- }),
-)
-
-filegroup(
- name = "libphobos2",
- srcs = select({
- ":darwin": ["dmd2/osx/lib/libphobos2.a"],
- ":k8": [
- "dmd2/linux/lib64/libphobos2.a",
- "dmd2/linux/lib64/libphobos2.so",
- ],
- ":x64_windows": ["dmd2/windows/lib64/phobos64.lib"],
- }),
-)
-
-filegroup(
- name = "phobos-src",
- srcs = glob(["dmd2/src/phobos/**/*.*"]),
-)
-
-filegroup(
- name = "druntime-import-src",
- srcs = glob([
- "dmd2/src/druntime/import/*.*",
- "dmd2/src/druntime/import/**/*.*",
- ]),
-)
-"""
-
-def d_repositories():
- http_archive(
- name = "dmd_linux_x86_64",
- urls = [
- "https://downloads.dlang.org/releases/2.x/2.101.2/dmd.2.101.2.linux.tar.xz",
- ],
- sha256 = "95d96731853805a8a026324240f8ea7bd871927f6a405d14268408685bbbdc5c",
- build_file_content = DMD_BUILD_FILE,
- )
-
- http_archive(
- name = "dmd_darwin_x86_64",
- urls = [
- "https://downloads.dlang.org/releases/2.x/2.101.2/dmd.2.101.2.osx.tar.xz",
- ],
- sha256 = "45bbe0d0e500faee5c84aaa5b124553671f1cec06a711860647cfaa7016aeb56",
- build_file_content = DMD_BUILD_FILE,
- )
-
- http_archive(
- name = "dmd_windows_x86_64",
- urls = [
- "https://downloads.dlang.org/releases/2.x/2.101.2/dmd.2.101.2.windows.zip",
- ],
- sha256 = "8065df7316e4d2d9e1f322998ec16b4b52c5c966dc3e7220159ba4029d5b97ba",
- build_file_content = DMD_BUILD_FILE,
- )
+def d_lib(
+ name,
+ srcs = [],
+ imports = [],
+ string_imports = [],
+ data = [],
+ linkopts = [],
+ versions = [],
+ hdrs = [],
+ exports = [],
+ exports_no_hdrs = [],
+ deps = [],
+ implementation_deps = [],
+ include_workspace_root = True,
+ is_generated = False,
+ generated_srcs = {},
+ test = False,
+ exports_lib = None,
+ **kwargs,
+):
+ """d_lib is a macro that can generate header files for a D library.
+
+ It wraps the d_library rule and automatically generates header files
+ for the exported D source files. It takes mostly the same arguments
+ as d_library, plus an additional `exports_no_hdrs` argument that
+ specifies the exported D source files that should be exported without
+ generating headers for them (this might be useful if they contain
+ non-templated functions that need to be called during CTFE).
+ Args:
+ name: The name of the target.
+ srcs: List of D source files to compile.
+ imports: List of import paths to include in the compilation.
+ string_imports: List of string import paths to include in the compilation.
+ data: List of extra files to include in the compilation.
+ linkopts: List of linker options to pass to the linker.
+ versions: List of D versions to define during compilation.
+ hdrs: List of header files to include in the library.
+ exports: List of D source files to export, which will have headers generated for them.
+ exports_no_hdrs: List of D source files to export without generating headers.
+ deps: List of dependencies for this library.
+ implementation_deps: List of implementation dependencies for this library.
+ include_workspace_root: Whether to include the workspace root in import paths.
+ is_generated: Whether this library is generated (used for generated sources).
+ generated_srcs: A dictionary mapping generated source files to their desired locations.
+ test: Whether this library is a test library (compiled with -unittest flag).
+ exports_lib: Optional label of a d_library target that contains the exported files.
+ If provided, will create an extra `d_source_library` with headers+exports.
+ This could be used to break a circular dependency.
+ **kwargs: Additional attributes for the d_library rule.
+ """
+ exports_hdrs = []
+ new_generated_srcs = {}
+ new_generated_srcs |= generated_srcs
+ for exp in exports:
+ if not exp.endswith(".d"):
+ fail("Exported files must be D source files, got: %s" % exp)
+ hdr = name + ".hdrgen/" + exp + "_hdrgen"
+ d_header_generator(
+ name = hdr,
+ src = exp,
+ )
+ if exp in generated_srcs:
+ # If the file is already in generated_srcs, let's put di file next to the target d file.
+ target = generated_srcs[exp]
+ else:
+ target = exp
+ exports_hdrs.append(hdr)
+ di_name = target[:-2] + ".di" # Replace .d with .di
+ new_generated_srcs[hdr] = di_name
+
+ if not test:
+ d_library(
+ name = name,
+ srcs = srcs,
+ imports = imports,
+ string_imports = string_imports,
+ data = data,
+ linkopts = linkopts,
+ versions = versions,
+ hdrs = hdrs + exports_hdrs,
+ exports = exports_no_hdrs,
+ deps = deps,
+ implementation_deps = implementation_deps,
+ include_workspace_root = include_workspace_root,
+ is_generated = is_generated,
+ generated_srcs = new_generated_srcs,
+ **kwargs,
+ )
+ else:
+ d_test_library(
+ name = name,
+ srcs = srcs,
+ imports = imports,
+ string_imports = string_imports,
+ data = data,
+ linkopts = linkopts,
+ versions = versions,
+ hdrs = hdrs + exports_hdrs,
+ exports = exports_no_hdrs,
+ deps = deps,
+ implementation_deps = implementation_deps,
+ include_workspace_root = include_workspace_root,
+ is_generated = is_generated,
+ generated_srcs = new_generated_srcs,
+ **kwargs,
+ )
+
+ if exports_lib:
+ # Create a d_source_library with the exported files.
+ d_library(
+ name = exports_lib,
+ hdrs = hdrs + exports_hdrs + exports_no_hdrs,
+ imports = imports,
+ string_imports = string_imports,
+ data = data,
+ linkopts = linkopts,
+ versions = versions,
+ include_workspace_root = include_workspace_root,
+ is_generated = is_generated,
+ generated_srcs = new_generated_srcs,
+ **kwargs,
+ )
diff --git a/d/extensions.bzl b/d/extensions.bzl
new file mode 100644
index 0000000..fdde34e
--- /dev/null
+++ b/d/extensions.bzl
@@ -0,0 +1,6 @@
+load("//d:repositories.bzl", "rules_d_toolchains")
+
+def _non_module_dependencies_impl(_ctx):
+ rules_d_toolchains()
+
+non_module_dependencies = module_extension(implementation = _non_module_dependencies_impl)
diff --git a/d/platforms/BUILD b/d/platforms/BUILD
new file mode 100644
index 0000000..51ee5d6
--- /dev/null
+++ b/d/platforms/BUILD
@@ -0,0 +1,25 @@
+package(default_visibility = ["//visibility:public"])
+
+platform(
+ name = "dmd",
+ parents = ["@local_config_platform//:host"],
+ constraint_values = [
+ "//d/constraints/compiler:dmd",
+ ],
+)
+
+platform(
+ name = "ldc",
+ parents = ["@local_config_platform//:host"],
+ constraint_values = [
+ "//d/constraints/compiler:ldc",
+ ],
+)
+
+platform(
+ name = "weka-ldc",
+ parents = ["@local_config_platform//:host"],
+ constraint_values = [
+ "//d/constraints/compiler:weka-ldc",
+ ],
+)
\ No newline at end of file
diff --git a/d/repositories.bzl b/d/repositories.bzl
new file mode 100644
index 0000000..c123a35
--- /dev/null
+++ b/d/repositories.bzl
@@ -0,0 +1,111 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("@bazel_skylib//lib:versions.bzl", "versions")
+
+DMD_BUILD_FILE = "//d:DMD.bzl"
+LDC_BUILD_FILE = "//d:LDC.bzl"
+DMD_STRIP_PREFIX = "dmd2"
+
+def fetch_dmd(version = None):
+ if version == None:
+ http_archive(
+ name = "dmd_linux_x86_64",
+ urls = [
+ "https://downloads.dlang.org/releases/2.x/2.102.1/dmd.2.102.1.linux.tar.xz",
+ ],
+ sha256 = "f3f62fd7357d9c0c0349c7b96721d6734fe8285c0f32a37649d378c8abb0e9eb",
+ strip_prefix = DMD_STRIP_PREFIX,
+ build_file = DMD_BUILD_FILE,
+ )
+
+ http_archive(
+ name = "dmd_darwin_x86_64",
+ urls = [
+ "https://downloads.dlang.org/releases/2.x/2.102.1/dmd.2.102.1.osx.tar.xz",
+ ],
+ sha256 = "300d309a2b71e95404f58e14a23daf342f47cc8608476a0b6414d356485df2bc",
+ strip_prefix = DMD_STRIP_PREFIX,
+ build_file = DMD_BUILD_FILE,
+ )
+
+ # http_archive(
+ # name = "dmd_windows_x86_64",
+ # urls = [
+ # "https://downloads.dlang.org/releases/2.x/2.102.1/dmd.2.102.1.windows.zip",
+ # ],
+ # sha256 = "a263ffbf6232288fa093c71a43a5cc1cd09ef5a75e7eca385ece16606c245090",
+ # strip_prefix = DMD_STRIP_PREFIX,
+ # build_file = DMD_BUILD_FILE,
+ # )
+
+ elif versions.is_at_least("2.0.0", version):
+ http_archive(
+ name = "dmd_linux_x86_64",
+ urls = [
+ "https://downloads.dlang.org/releases/2.x/{version}/dmd.{version}.linux.tar.xz".format(version = version),
+ ],
+ strip_prefix = DMD_STRIP_PREFIX,
+ build_file = DMD_BUILD_FILE,
+ )
+
+ http_archive(
+ name = "dmd_darwin_x86_64",
+ urls = [
+ "https://downloads.dlang.org/releases/2.x/{version}/dmd.{version}.osx.tar.xz".format(version = version),
+ ],
+ strip_prefix = DMD_STRIP_PREFIX,
+ build_file = DMD_BUILD_FILE,
+ )
+
+ http_archive(
+ name = "dmd_windows_x86_64",
+ urls = [
+ "https://downloads.dlang.org/releases/2.x/{version}/dmd.{version}.windows.zip".format(version = version),
+ ],
+ strip_prefix = DMD_STRIP_PREFIX,
+ build_file = DMD_BUILD_FILE,
+ )
+
+ else:
+ fail("Sorry, only DMD 2 is supported, but got %s. Maybe consider switching to D2?" % version)
+
+def fetch_ldc(version = None):
+ http_archive(
+ name = "ldc_linux_x86_64",
+ urls = [
+ "https://github.com/ldc-developers/ldc/releases/download/v1.31.0/ldc2-1.31.0-linux-x86_64.tar.xz",
+ ],
+ sha256 = "7dbd44786c0772ec41890a8c03e22b0985d6ef547c40943dd56bc6be21cf4d98",
+ strip_prefix = "ldc2-1.31.0-linux-x86_64",
+ build_file = LDC_BUILD_FILE,
+ )
+
+def fetch_weka_ldc(version = "1.30.0-weka20"):
+ http_archive(
+ name = "weka_ldc_linux_x86_64",
+ urls = [
+ "https://github.com/weka/ldc/releases/download/v{version}/ldc2-{version}-linux-x86_64.tar.xz".format(version = version),
+ ],
+ sha256 = "0a6001fb4975361724b1975eb49cde70ef53546f78b281a69446121072342f7a",
+ strip_prefix = "ldc2-{version}-linux-x86_64".format(version = version),
+ build_file = LDC_BUILD_FILE,
+ )
+
+def rules_d_toolchains(ctype = "dmd", version = None):
+ if ctype == "dmd":
+ fetch_dmd(version = version)
+ fetch_ldc()
+ fetch_weka_ldc()
+
+ elif ctype == "ldc":
+ fetch_dmd()
+ fetch_ldc(version = version)
+ fetch_weka_ldc()
+
+ elif ctype == "weka-ldc":
+ # Special case for Weka LDC, which is a fork of LDC
+ fetch_weka_ldc(version = version)
+ fetch_dmd()
+ fetch_ldc()
+
+ else:
+ fail("Only \"dmd\", \"ldc\" and \"weka-ldc\" compilers are supported at this moment.")
diff --git a/d/toolchain.bzl b/d/toolchain.bzl
new file mode 100644
index 0000000..67143cf
--- /dev/null
+++ b/d/toolchain.bzl
@@ -0,0 +1,139 @@
+load("@bazel_skylib//rules:common_settings.bzl", "string_setting")
+load("//d:config.bzl", "DToolchainConfigInfo")
+
+D_TOOLCHAIN = "//d:toolchain_type"
+
+# string_setting(
+# name = "compiler_type",
+# values = [
+# "dmd",
+# "ldc",
+# ],
+# )
+#
+# config_setting(
+# name = "dmd",
+# flag_values = {
+# ":compiler_type": "dmd",
+# },
+# )
+#
+# config_setting(
+# name = "ldc",
+# flag_values = {
+# ":compiler_type": "ldc",
+# },
+# )
+
+def _d_toolchain_impl(ctx):
+ config = ctx.attr.config[DToolchainConfigInfo] if ctx.attr.config else None
+ codegen_opts_per_mode = {
+ "fastbuild": ctx.attr.codegen_fastbuild_flags,
+ "dbg": ctx.attr.codegen_dbg_flags,
+ "opt": ctx.attr.codegen_opt_flags,
+ }
+ if config == None:
+ # TODO: deprecate this
+ toolchain_info = platform_common.ToolchainInfo(
+ name = ctx.label.name,
+ d_compiler = ctx.attr.d_compiler,
+ c_compiler = ctx.attr.c_compiler,
+ llc_compiler = ctx.attr.llc_compiler,
+ lib_flags = ctx.attr.lib_flags,
+ link_flags = ctx.attr.link_flags,
+ import_flags = ctx.attr.import_flags,
+ libphobos = ctx.attr.libphobos,
+ libphobos_src = ctx.attr.libphobos_src,
+ druntime = ctx.attr.druntime,
+ druntime_src = ctx.attr.druntime_src,
+ version_flag = ctx.attr.version_flag,
+ common_flags = ctx.attr.common_flags,
+ fastbuild_flags = ctx.attr.fastbuild_flags,
+ dbg_flags = ctx.attr.dbg_flags,
+ opt_flags = ctx.attr.opt_flags,
+ codegen_common_flags = ctx.attr.codegen_common_flags,
+ codegen_per_mode_flags = codegen_opts_per_mode,
+ hdrgen_flags = ctx.attr.hdrgen_flags,
+ output_bc_flags = ctx.attr.output_bc_flags,
+ global_versions_common = [],
+ global_versions_per_mode = {
+ "fastbuild": [],
+ "dbg": [],
+ "opt": [],
+ },
+ debug_repo_root_override = ctx.attr.debug_repo_root_override,
+ )
+ else:
+ toolchain_info = platform_common.ToolchainInfo(
+ name = ctx.attr.name,
+ d_compiler = config.d_compiler or ctx.attr.d_compiler,
+ c_compiler = config.c_compiler or ctx.attr.c_compiler,
+ llc_compiler = config.llc_compiler or ctx.attr.llc_compiler,
+ lib_flags = config.lib_flags or ctx.attr.lib_flags,
+ link_flags = (config.linkopts_common + config.linkopts_per_mode[ctx.var["COMPILATION_MODE"]]) or ctx.attr.link_flags,
+ import_flags = config.import_flags or ctx.attr.import_flags,
+ libphobos = config.libphobos or ctx.attr.libphobos,
+ libphobos_src = config.libphobos_src or ctx.attr.libphobos_src,
+ druntime = config.druntime or ctx.attr.druntime,
+ druntime_src = config.druntime_src or ctx.attr.druntime_src,
+ version_flag = config.version_flag or ctx.attr.version_flag,
+ common_flags = config.copts_common or ctx.attr.common_flags,
+ fastbuild_flags = config.copts_per_mode["fastbuild"] or ctx.attr.fastbuild_flags,
+ dbg_flags = config.copts_per_mode["dbg"] or ctx.attr.dbg_flags,
+ opt_flags = config.copts_per_mode["opt"] or ctx.attr.opt_flags,
+ codegen_common_flags = config.codegen_opts_common or ctx.attr.codegen_common_flags,
+ codegen_per_mode_flags = config.codegen_opts_per_mode or codegen_opts_per_mode,
+ hdrgen_flags = config.hdrgen_flags,
+ output_bc_flags = config.output_bc_flags,
+ global_versions_common = config.global_versions_common,
+ global_versions_per_mode = config.global_versions_per_mode,
+ debug_repo_root_override = config.debug_repo_root_override,
+ )
+ return [toolchain_info]
+
+d_toolchain = rule(
+ _d_toolchain_impl,
+ attrs = {
+ "d_compiler": attr.label(
+ executable = True,
+ # allow_files = True,
+ cfg = "exec",
+ ),
+ "c_compiler": attr.label(
+ executable = True,
+ allow_files = True,
+ cfg = "exec",
+ ),
+ "llc_compiler": attr.label(
+ executable = True,
+ allow_files = True,
+ cfg = "exec",
+ ),
+ "lib_flags": attr.string_list(
+ default = ["-lib"],
+ ),
+ "link_flags": attr.string_list(
+ default = [],
+ ),
+ "import_flags": attr.string_list(),
+ "libphobos": attr.label(),
+ "libphobos_src": attr.label(),
+ "druntime": attr.label(),
+ "druntime_src": attr.label(),
+ "version_flag": attr.string(),
+ "common_flags": attr.string_list(),
+ "fastbuild_flags": attr.string_list(),
+ "dbg_flags": attr.string_list(),
+ "opt_flags": attr.string_list(),
+ "codegen_common_flags": attr.string_list(default = []),
+ "codegen_fastbuild_flags": attr.string_list(),
+ "codegen_dbg_flags": attr.string_list(),
+ "codegen_opt_flags": attr.string_list(),
+ "hdrgen_flags": attr.string_list(),
+ "output_bc_flags": attr.string_list(),
+ "debug_repo_root_override": attr.string(),
+ "config": attr.label(
+ providers = [DToolchainConfigInfo],
+ ),
+ },
+)
diff --git a/examples/dynamic_symbols/BUILD b/examples/dynamic_symbols/BUILD
new file mode 100644
index 0000000..659241e
--- /dev/null
+++ b/examples/dynamic_symbols/BUILD
@@ -0,0 +1,13 @@
+package(default_visibility = ["//visibility:public"])
+
+load("//d:d.bzl", "d_binary")
+
+d_binary(
+ name = "dynamic_symbols",
+ srcs = ["dynamic_symbols.d"],
+ dynamic_symbols = ":dynamic_symbols.txt",
+ deps = [
+ "//examples/hello_lib:greeter",
+ "//examples/hello_lib:native_greeter",
+ ],
+)
diff --git a/examples/dynamic_symbols/dynamic_symbols.d b/examples/dynamic_symbols/dynamic_symbols.d
new file mode 100644
index 0000000..1bd0235
--- /dev/null
+++ b/examples/dynamic_symbols/dynamic_symbols.d
@@ -0,0 +1,26 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import std.stdio;
+import examples.hello_lib.greeter;
+import examples.hello_lib.native_greeter;
+
+void main() {
+ Greeter greeter = new Greeter("Hello");
+ greeter.greet("World");
+
+ NativeGreeter* nativeGreeter = native_greeter_new("Hello");
+ native_greeter_greet(nativeGreeter, "World");
+ native_greeter_free(nativeGreeter);
+}
diff --git a/examples/dynamic_symbols/dynamic_symbols.txt b/examples/dynamic_symbols/dynamic_symbols.txt
new file mode 100644
index 0000000..53f38aa
--- /dev/null
+++ b/examples/dynamic_symbols/dynamic_symbols.txt
@@ -0,0 +1,4 @@
+{
+a;
+b;
+};
diff --git a/examples/string_imports/BUILD b/examples/string_imports/BUILD
new file mode 100644
index 0000000..f876803
--- /dev/null
+++ b/examples/string_imports/BUILD
@@ -0,0 +1,16 @@
+load("//d:d.bzl", "d_binary", "d_library")
+
+d_library(
+ name = "lib",
+ srcs = ["lib.d"],
+ data = ["imports/test.txt"],
+ string_imports = ["imports"],
+)
+
+d_binary(
+ name = "main",
+ srcs = ["main.d"],
+ deps = [
+ ":lib",
+ ]
+)
\ No newline at end of file
diff --git a/examples/string_imports/imports/test.txt b/examples/string_imports/imports/test.txt
new file mode 100644
index 0000000..f2ba8f8
--- /dev/null
+++ b/examples/string_imports/imports/test.txt
@@ -0,0 +1 @@
+abc
\ No newline at end of file
diff --git a/examples/string_imports/lib.d b/examples/string_imports/lib.d
new file mode 100644
index 0000000..4bd7df0
--- /dev/null
+++ b/examples/string_imports/lib.d
@@ -0,0 +1,8 @@
+
+string testTemplate()() {
+ return import("test.txt");
+}
+
+string test() {
+ return import("test.txt");
+}
\ No newline at end of file
diff --git a/examples/string_imports/main.d b/examples/string_imports/main.d
new file mode 100644
index 0000000..544abaf
--- /dev/null
+++ b/examples/string_imports/main.d
@@ -0,0 +1,8 @@
+import examples.string_imports.lib;
+
+import std.stdio;
+
+void main() {
+ writeln(test);
+ writeln(testTemplate);
+}
\ No newline at end of file
diff --git a/tests/c_library_usage/BUILD b/tests/c_library_usage/BUILD
index caf85f0..06c0cc7 100644
--- a/tests/c_library_usage/BUILD
+++ b/tests/c_library_usage/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "c_library_usage",
diff --git a/tests/c_library_usage_no_wrapper/BUILD b/tests/c_library_usage_no_wrapper/BUILD
index 8e152f9..8552a7a 100644
--- a/tests/c_library_usage_no_wrapper/BUILD
+++ b/tests/c_library_usage_no_wrapper/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "c_library_usage_no_wrapper",
diff --git a/tests/circular_deps/BUILD b/tests/circular_deps/BUILD
new file mode 100644
index 0000000..06699e7
--- /dev/null
+++ b/tests/circular_deps/BUILD
@@ -0,0 +1,51 @@
+
+load("//d:d.bzl", "d_lib", "d_test")
+
+d_lib(
+ name = "lib_a",
+ srcs = ["lib_a.d"],
+ exports = ["lib_a.d"],
+ exports_lib = "lib_a_exports",
+ deps = [
+ ":lib_b",
+ ],
+)
+
+d_lib(
+ name = "lib_b",
+ srcs = ["lib_b.d"],
+ exports = ["lib_b.d"],
+ deps = [
+ ":lib_a_exports",
+ ],
+)
+
+d_test(
+ name = "circular_deps_test",
+ srcs = ["circular_deps_test.d"],
+ link_order = {
+ ":lib_a": "-1", # lib_a must be linked last
+ },
+ args = [
+ "--DRT-oncycle=ignore",
+ ],
+ deps = [
+ ":lib_a",
+ ":lib_b",
+ ],
+)
+
+d_test(
+ name = "circular_deps_test2",
+ srcs = ["circular_deps_test.d"],
+ link_order = {
+ ":lib_a": "-1", # lib_a must be linked last
+ },
+ args = [
+ "--DRT-oncycle=ignore",
+ ],
+ deps = [
+ ":lib_b",
+ ":lib_a",
+ ],
+)
\ No newline at end of file
diff --git a/tests/circular_deps/circular_deps_test.d b/tests/circular_deps/circular_deps_test.d
new file mode 100644
index 0000000..d65b9b5
--- /dev/null
+++ b/tests/circular_deps/circular_deps_test.d
@@ -0,0 +1,14 @@
+module tests.circular_deps.circular_deps_test;
+
+void main() {}
+
+unittest
+{
+ import tests.circular_deps.lib_a;
+ import tests.circular_deps.lib_b;
+
+ assert(f(1) == 4);
+ assert(g(1) == 3);
+ assert(h(1) == 2);
+ assert(globalVar == 10);
+}
diff --git a/tests/circular_deps/lib_a.d b/tests/circular_deps/lib_a.d
new file mode 100644
index 0000000..fe8b554
--- /dev/null
+++ b/tests/circular_deps/lib_a.d
@@ -0,0 +1,19 @@
+module tests.circular_deps.lib_a;
+
+import tests.circular_deps.lib_b;
+
+__gshared int globalVar = 2;
+
+int f(int x) {
+ return x + g(x);
+}
+
+int h(int x) {
+ return x + 1;
+}
+
+shared static this() {
+ import std.stdio;
+ globalVar += 3;
+ writeln("lib_a initialized");
+}
diff --git a/tests/circular_deps/lib_b.d b/tests/circular_deps/lib_b.d
new file mode 100644
index 0000000..f51df99
--- /dev/null
+++ b/tests/circular_deps/lib_b.d
@@ -0,0 +1,13 @@
+module tests.circular_deps.lib_b;
+
+import tests.circular_deps.lib_a;
+
+int g(int x) {
+ return x + h(x);
+}
+
+shared static this() {
+ import std.stdio;
+ globalVar *= 2;
+ writeln("lib_b initialized");
+}
diff --git a/tests/circular_deps_with_gensrcs/BUILD b/tests/circular_deps_with_gensrcs/BUILD
new file mode 100644
index 0000000..0d17abe
--- /dev/null
+++ b/tests/circular_deps_with_gensrcs/BUILD
@@ -0,0 +1,61 @@
+
+load("//d:d.bzl", "d_lib", "d_test")
+
+genrule(
+ name = "lib_a_preprocess",
+ srcs = ["lib_a.d"],
+ outs = ["lib_a_preprocessed.d"],
+ cmd = "cp $< $@",
+)
+
+d_lib(
+ name = "lib_a",
+ srcs = ["lib_a_preprocessed.d"],
+ exports = ["lib_a_preprocessed.d"],
+ exports_lib = "lib_a_exports",
+ generated_srcs = {
+ "lib_a_preprocessed.d": "lib_a.d",
+ },
+ deps = [
+ ":lib_b",
+ ],
+)
+
+d_lib(
+ name = "lib_b",
+ srcs = ["lib_b.d"],
+ exports = ["lib_b.d"],
+ deps = [
+ ":lib_a_exports",
+ ],
+)
+
+d_test(
+ name = "circular_deps_test",
+ srcs = ["circular_deps_test.d"],
+ link_order = {
+ ":lib_a": "-1", # lib_a must be linked last
+ },
+ args = [
+ "--DRT-oncycle=ignore",
+ ],
+ deps = [
+ ":lib_a",
+ ":lib_b",
+ ],
+)
+
+d_test(
+ name = "circular_deps_test2",
+ srcs = ["circular_deps_test.d"],
+ link_order = {
+ ":lib_a": "-1", # lib_a must be linked last
+ },
+ args = [
+ "--DRT-oncycle=ignore",
+ ],
+ deps = [
+ ":lib_b",
+ ":lib_a",
+ ],
+)
\ No newline at end of file
diff --git a/tests/circular_deps_with_gensrcs/circular_deps_test.d b/tests/circular_deps_with_gensrcs/circular_deps_test.d
new file mode 100644
index 0000000..f05e47a
--- /dev/null
+++ b/tests/circular_deps_with_gensrcs/circular_deps_test.d
@@ -0,0 +1,14 @@
+module tests.circular_deps_with_gensrcs.circular_deps_test;
+
+void main() {}
+
+unittest
+{
+ import tests.circular_deps_with_gensrcs.lib_a;
+ import tests.circular_deps_with_gensrcs.lib_b;
+
+ assert(f(1) == 4);
+ assert(g(1) == 3);
+ assert(h(1) == 2);
+ assert(globalVar == 10);
+}
diff --git a/tests/circular_deps_with_gensrcs/lib_a.d b/tests/circular_deps_with_gensrcs/lib_a.d
new file mode 100644
index 0000000..c5b8a38
--- /dev/null
+++ b/tests/circular_deps_with_gensrcs/lib_a.d
@@ -0,0 +1,19 @@
+module tests.circular_deps_with_gensrcs.lib_a;
+
+import tests.circular_deps_with_gensrcs.lib_b;
+
+__gshared int globalVar = 2;
+
+int f(int x) {
+ return x + g(x);
+}
+
+int h(int x) {
+ return x + 1;
+}
+
+shared static this() {
+ import std.stdio;
+ globalVar += 3;
+ writeln("lib_a initialized");
+}
diff --git a/tests/circular_deps_with_gensrcs/lib_b.d b/tests/circular_deps_with_gensrcs/lib_b.d
new file mode 100644
index 0000000..8074e69
--- /dev/null
+++ b/tests/circular_deps_with_gensrcs/lib_b.d
@@ -0,0 +1,13 @@
+module tests.circular_deps_with_gensrcs.lib_b;
+
+import tests.circular_deps_with_gensrcs.lib_a;
+
+int g(int x) {
+ return x + h(x);
+}
+
+shared static this() {
+ import std.stdio;
+ globalVar *= 2;
+ writeln("lib_b initialized");
+}
diff --git a/tests/d_binary_no_source/BUILD b/tests/d_binary_no_source/BUILD
new file mode 100644
index 0000000..27ac54c
--- /dev/null
+++ b/tests/d_binary_no_source/BUILD
@@ -0,0 +1,20 @@
+load("//d:d.bzl", "d_library", "d_test_library", "d_test")
+
+d_test_library(
+ name = "testlib",
+ srcs = ["testlib.d"],
+)
+
+d_library(
+ name = "main",
+ srcs = ["main.d"],
+)
+
+d_test(
+ name = "test",
+ srcs = [],
+ deps = [
+ ":main",
+ ":testlib",
+ ],
+)
\ No newline at end of file
diff --git a/tests/d_binary_no_source/main.d b/tests/d_binary_no_source/main.d
new file mode 100644
index 0000000..34f46e2
--- /dev/null
+++ b/tests/d_binary_no_source/main.d
@@ -0,0 +1,2 @@
+void main() {
+}
diff --git a/tests/d_binary_no_source/testlib.d b/tests/d_binary_no_source/testlib.d
new file mode 100644
index 0000000..f1027fa
--- /dev/null
+++ b/tests/d_binary_no_source/testlib.d
@@ -0,0 +1,13 @@
+
+int f(int x) {
+ return x * 2;
+}
+
+unittest
+{
+ assert(f(2) == 4);
+ assert(f(3) == 6);
+ assert(f(0) == 0);
+ assert(f(-1) == -2);
+ assert(f(-5) == -10);
+}
\ No newline at end of file
diff --git a/tests/d_lib/BUILD b/tests/d_lib/BUILD
new file mode 100644
index 0000000..7548ea3
--- /dev/null
+++ b/tests/d_lib/BUILD
@@ -0,0 +1,20 @@
+load("//d:d.bzl", "d_binary", "d_lib")
+
+d_lib(
+ name = "d_lib",
+ srcs = ["lib.d"],
+ exports = ["lib.d"],
+)
+
+d_lib(
+ name = "d_lib2",
+ srcs = ["lib2.d"],
+ exports = ["lib2.d"],
+ deps = [":d_lib"],
+)
+
+d_binary(
+ name = "main",
+ srcs = ["main.d"],
+ deps = [":d_lib2"],
+)
\ No newline at end of file
diff --git a/tests/d_lib/lib.d b/tests/d_lib/lib.d
new file mode 100644
index 0000000..d248f29
--- /dev/null
+++ b/tests/d_lib/lib.d
@@ -0,0 +1,6 @@
+module tests.d_lib.lib;
+
+int plusOne(int x)
+{
+ return x + 1;
+}
\ No newline at end of file
diff --git a/tests/d_lib/lib2.d b/tests/d_lib/lib2.d
new file mode 100644
index 0000000..3651497
--- /dev/null
+++ b/tests/d_lib/lib2.d
@@ -0,0 +1,8 @@
+module tests.d_lib.lib2;
+
+import tests.d_lib.lib;
+
+int plusOneTwice(int x)
+{
+ return plusOne(plusOne(x));
+}
\ No newline at end of file
diff --git a/tests/d_lib/main.d b/tests/d_lib/main.d
new file mode 100644
index 0000000..1409cd5
--- /dev/null
+++ b/tests/d_lib/main.d
@@ -0,0 +1,11 @@
+module tests.d_lib.main;
+
+import tests.d_lib.lib2;
+
+void main()
+{
+ int x = 5;
+ int result = plusOneTwice(x);
+ import std.stdio;
+ writeln("The result of plusOne(", x, ") is: ", result);
+}
\ No newline at end of file
diff --git a/tests/d_lib_headers/BUILD b/tests/d_lib_headers/BUILD
new file mode 100644
index 0000000..3e1c74a
--- /dev/null
+++ b/tests/d_lib_headers/BUILD
@@ -0,0 +1,6 @@
+load("//d:d.bzl", "d_header_generator")
+
+d_header_generator(
+ name = "d_lib_headers",
+ src = "lib.d",
+)
\ No newline at end of file
diff --git a/tests/d_lib_headers/lib.d b/tests/d_lib_headers/lib.d
new file mode 100644
index 0000000..6e95086
--- /dev/null
+++ b/tests/d_lib_headers/lib.d
@@ -0,0 +1,6 @@
+module tests.d_lib_headers.lib;
+
+int plusOne(int x)
+{
+ return x + 1;
+}
\ No newline at end of file
diff --git a/tests/d_library_compile_via_bc/BUILD b/tests/d_library_compile_via_bc/BUILD
new file mode 100644
index 0000000..5653250
--- /dev/null
+++ b/tests/d_library_compile_via_bc/BUILD
@@ -0,0 +1,9 @@
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_d//d:d.bzl", "d_library")
+
+d_library(
+ name = "simple_d_library",
+ compile_via_bc = True,
+ srcs = ["simple_library.d"],
+)
diff --git a/tests/d_library_compile_via_bc/simple_library.d b/tests/d_library_compile_via_bc/simple_library.d
new file mode 100644
index 0000000..5b162ad
--- /dev/null
+++ b/tests/d_library_compile_via_bc/simple_library.d
@@ -0,0 +1,6 @@
+module simple_library;
+
+int plusOne(uint x)
+{
+ return x + 1;
+}
diff --git a/tests/d_library_usage/BUILD b/tests/d_library_usage/BUILD
index f668a20..a1a4d2f 100644
--- a/tests/d_library_usage/BUILD
+++ b/tests/d_library_usage/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "d_library_usage",
diff --git a/tests/deps_only_library/BUILD b/tests/deps_only_library/BUILD
new file mode 100644
index 0000000..1e6b97c
--- /dev/null
+++ b/tests/deps_only_library/BUILD
@@ -0,0 +1,16 @@
+load("//d:d.bzl", "d_library", "d_test")
+
+d_library(
+ name = "deps_only_library",
+ srcs = [],
+ deps = [
+ "//tests/header_only_library:header_only_library",
+ "//tests/simple_d_library:simple_d_library",
+ ],
+)
+
+d_test(
+ name = "deps_only_library_test",
+ srcs = ["test.d"],
+ deps = [":deps_only_library"],
+)
\ No newline at end of file
diff --git a/tests/deps_only_library/test.d b/tests/deps_only_library/test.d
new file mode 100644
index 0000000..6cec4d0
--- /dev/null
+++ b/tests/deps_only_library/test.d
@@ -0,0 +1,15 @@
+module tests.deps_only_library.test;
+
+void main() {
+ import tests.header_only_library.lib;
+
+ int result = add(2, 3);
+
+ assert(result == 5);
+
+ import tests.simple_d_library.simple_library;
+
+ int result2 = plusOne(4);
+
+ assert(result2 == 5);
+}
\ No newline at end of file
diff --git a/tests/directory_srcs/BUILD b/tests/directory_srcs/BUILD
index 9c440a5..8f3c810 100644
--- a/tests/directory_srcs/BUILD
+++ b/tests/directory_srcs/BUILD
@@ -1,5 +1,5 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
-load("@io_bazel_rules_d//tests/directory_srcs:directory_generator.bzl", "directory_generator")
+load("@rules_d//d:d.bzl", "d_test")
+load("@rules_d//tests/directory_srcs:directory_generator.bzl", "directory_generator")
# Provides a single declared directory File as its output in Default Info,
# containing a copy of all srcs. This is similar to capturing the output of the
diff --git a/tests/fiber_thread_usage/BUILD b/tests/fiber_thread_usage/BUILD
index 6836ce4..3380ce2 100644
--- a/tests/fiber_thread_usage/BUILD
+++ b/tests/fiber_thread_usage/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "fiber_thread_usage",
diff --git a/tests/header_only_library/BUILD b/tests/header_only_library/BUILD
new file mode 100644
index 0000000..d84eae3
--- /dev/null
+++ b/tests/header_only_library/BUILD
@@ -0,0 +1,17 @@
+load("//d:d.bzl", "d_library", "d_test")
+
+package(
+ default_visibility = ["//visibility:public"],
+)
+
+d_library(
+ name = "header_only_library",
+ srcs = [],
+ hdrs = ["lib.di"],
+)
+
+d_test(
+ name = "header_only_library_test",
+ srcs = ["header_only_library_test.d"],
+ deps = [":header_only_library"],
+)
\ No newline at end of file
diff --git a/tests/header_only_library/header_only_library_test.d b/tests/header_only_library/header_only_library_test.d
new file mode 100644
index 0000000..d4ec9aa
--- /dev/null
+++ b/tests/header_only_library/header_only_library_test.d
@@ -0,0 +1,9 @@
+module tests.header_only_library.header_only_library_test;
+
+void main() {
+ import tests.header_only_library.lib;
+
+ int result = add(2, 3);
+
+ assert(result == 5);
+}
\ No newline at end of file
diff --git a/tests/header_only_library/lib.di b/tests/header_only_library/lib.di
new file mode 100644
index 0000000..c763937
--- /dev/null
+++ b/tests/header_only_library/lib.di
@@ -0,0 +1,5 @@
+module tests.header_only_library.lib;
+
+int add(T)(T a, T b) {
+ return a + b;
+}
diff --git a/tests/implementation_deps/BUILD b/tests/implementation_deps/BUILD
new file mode 100644
index 0000000..0fded26
--- /dev/null
+++ b/tests/implementation_deps/BUILD
@@ -0,0 +1,17 @@
+load("//d:d.bzl", "d_lib")
+
+d_lib(
+ name = "liba",
+ srcs = ["liba.d"],
+ implementation_deps = [
+ "//tests/simple_d_library",
+ ],
+)
+
+d_lib(
+ name = "libb",
+ srcs = ["libb.d"],
+ deps = [
+ ":liba",
+ ],
+)
\ No newline at end of file
diff --git a/tests/implementation_deps/liba.d b/tests/implementation_deps/liba.d
new file mode 100644
index 0000000..40dbfc0
--- /dev/null
+++ b/tests/implementation_deps/liba.d
@@ -0,0 +1,6 @@
+module tests.implementation_deps.liba;
+
+int public_func(int x) {
+ import tests.simple_d_library.simple_library;
+ return plusOne(x);
+}
\ No newline at end of file
diff --git a/tests/implementation_deps/libb.d b/tests/implementation_deps/libb.d
new file mode 100644
index 0000000..056b0d1
--- /dev/null
+++ b/tests/implementation_deps/libb.d
@@ -0,0 +1,7 @@
+module tests.implementation_deps.libb;
+
+import tests.implementation_deps.liba;
+
+int libb_func(int x) {
+ return public_func(x);
+}
\ No newline at end of file
diff --git a/tests/lib_that_depends_on_lib/BUILD b/tests/lib_that_depends_on_lib/BUILD
index 3c09675..7e6f693 100644
--- a/tests/lib_that_depends_on_lib/BUILD
+++ b/tests/lib_that_depends_on_lib/BUILD
@@ -1,6 +1,6 @@
package(default_visibility = ["//visibility:public"])
-load("@io_bazel_rules_d//d:d.bzl", "d_library")
+load("@rules_d//d:d.bzl", "d_library")
d_library(
name = "lib_that_depends_on_lib",
diff --git a/tests/lib_that_depends_on_lib_test/BUILD b/tests/lib_that_depends_on_lib_test/BUILD
index 2c8b87b..63982d4 100644
--- a/tests/lib_that_depends_on_lib_test/BUILD
+++ b/tests/lib_that_depends_on_lib_test/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "lib_that_depends_on_lib_test",
diff --git a/tests/mix_sources_and_generated/BUILD b/tests/mix_sources_and_generated/BUILD
new file mode 100644
index 0000000..1c84eca
--- /dev/null
+++ b/tests/mix_sources_and_generated/BUILD
@@ -0,0 +1,39 @@
+load("//d:d.bzl", "d_binary", "d_library")
+
+genrule(
+ name = "generate_b",
+ srcs = ["b.d"],
+ outs = ["b_generated.d"],
+ cmd = "cat $< > $@",
+)
+
+d_library(
+ name = "lib",
+ srcs = ["a.d", ":generate_b"],
+ generated_srcs = {
+ ":generate_b": "b.d",
+ },
+)
+
+d_library(
+ name = "lib_no_map",
+ srcs = ["a.d", ":generate_b"],
+)
+
+d_binary(
+ name = "bin",
+ srcs = ["main.d"],
+ deps = [
+ ":lib",
+ ],
+)
+
+# This is expected to fail because the generated source file is not mapped
+d_binary(
+ name = "bin_no_map",
+ srcs = ["main.d"],
+ deps = [
+ ":lib_no_map",
+ ],
+ tags = ["manual"],
+)
\ No newline at end of file
diff --git a/tests/mix_sources_and_generated/a.d b/tests/mix_sources_and_generated/a.d
new file mode 100644
index 0000000..e7c4379
--- /dev/null
+++ b/tests/mix_sources_and_generated/a.d
@@ -0,0 +1,7 @@
+module tests.mix_sources_and_generated.a;
+
+import tests.mix_sources_and_generated.b;
+
+int a() {
+ return bfun();
+}
diff --git a/tests/mix_sources_and_generated/b.d b/tests/mix_sources_and_generated/b.d
new file mode 100644
index 0000000..ce8b226
--- /dev/null
+++ b/tests/mix_sources_and_generated/b.d
@@ -0,0 +1,5 @@
+module tests.mix_sources_and_generated.b;
+
+int bfun() {
+ return 42;
+}
diff --git a/tests/mix_sources_and_generated/main.d b/tests/mix_sources_and_generated/main.d
new file mode 100644
index 0000000..9bdd5e6
--- /dev/null
+++ b/tests/mix_sources_and_generated/main.d
@@ -0,0 +1,9 @@
+import tests.mix_sources_and_generated.b;
+
+void main() {
+ // This is a test to check if the mix of sources and generated code works
+ // The generated code is in the `generated` directory
+ // The source code is in the `src` directory
+ // The test should pass if the mix works
+ assert(bfun() == 42);
+}
diff --git a/tests/simple/BUILD b/tests/simple/BUILD
index 429a644..1e672d6 100644
--- a/tests/simple/BUILD
+++ b/tests/simple/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "simple",
diff --git a/tests/simple_as_binary/BUILD b/tests/simple_as_binary/BUILD
index c1168c1..a9ce516 100644
--- a/tests/simple_as_binary/BUILD
+++ b/tests/simple_as_binary/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_binary")
+load("@rules_d//d:d.bzl", "d_binary")
d_binary(
name = "simple",
diff --git a/tests/simple_c_library/BUILD b/tests/simple_c_library/BUILD
index 278aedf..292bd77 100644
--- a/tests/simple_c_library/BUILD
+++ b/tests/simple_c_library/BUILD
@@ -1,6 +1,6 @@
package(default_visibility = ["//visibility:public"])
-load("@io_bazel_rules_d//d:d.bzl", "d_source_library")
+load("@rules_d//d:d.bzl", "d_source_library")
cc_library(
name = "simple_c_library",
diff --git a/tests/simple_d_library/BUILD b/tests/simple_d_library/BUILD
index 59eb77a..1004b3a 100644
--- a/tests/simple_d_library/BUILD
+++ b/tests/simple_d_library/BUILD
@@ -1,6 +1,6 @@
package(default_visibility = ["//visibility:public"])
-load("@io_bazel_rules_d//d:d.bzl", "d_library")
+load("@rules_d//d:d.bzl", "d_library")
d_library(
name = "simple_d_library",
diff --git a/tests/simplest/BUILD b/tests/simplest/BUILD
index 2f494b9..e489339 100644
--- a/tests/simplest/BUILD
+++ b/tests/simplest/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_d//d:d.bzl", "d_test")
+load("@rules_d//d:d.bzl", "d_test")
d_test(
name = "simplest",