feat: doxygen compilation from source (wip)
diff --git a/doxygen/doxygen.bzl b/doxygen/doxygen.bzl index 02e0828..e635c31 100644 --- a/doxygen/doxygen.bzl +++ b/doxygen/doxygen.bzl
@@ -2,7 +2,7 @@ def _expand_make_variables(string, ctx): """Replace make variables in a string with their values. - + Args: string: The string to expand. ctx: The context object. @@ -44,7 +44,7 @@ outputs = outs, arguments = [doxyfile.path] + ctx.attr.doxygen_extra_args, progress_message = "Running doxygen", - executable = ctx.executable._executable, + executable = ctx.executable.executable, ) return [ @@ -104,7 +104,7 @@ doc = "The dot executable to use. Must refer to an executable file.", ), "doxygen_extra_args": attr.string_list(default = [], doc = "Extra arguments to pass to the doxygen executable."), - "_executable": attr.label( + "executable": attr.label( executable = True, cfg = "exec", allow_single_file = True, @@ -1113,7 +1113,7 @@ _add_generic_configuration(configurations, "MSCFILE_DIRS", mscfile_dirs) if doxyfile_template: - kwargs["doxyfile_template"] = doxyfile_template + kwargs["doxyfile_template"] = doxyfile_template _doxygen( name = name,
diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel index f74aa16..b532738 100644 --- a/examples/MODULE.bazel +++ b/examples/MODULE.bazel
@@ -9,6 +9,43 @@ bazel_dep(name = "aspect_bazel_lib", version = "2.10.0") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "rules_foreign_cc", version = "0.14.0") +bazel_dep(name = "libconfig", version = "1.7.3") +bazel_dep(name = "rules_flex", version = "0.4") +bazel_dep(name = "rules_bison", version = "0.4") + +github_archive = use_repo_rule("//:git_archive.bzl", "github_archive") + +github_archive( + name = "doxygen_source", + build_file = "//:doxygen_source.BUILD.bazel", + commit = "200cec9b87fa544f39deeb96966568985f40aea8", + repository = "doxygen/doxygen", + sha256 = "6aa71da24aa7b8fc8f9eba5a6651b1fb47c569c68d3e226b011d39a15087c2fb", +) + +bison = use_extension( + "@rules_bison//bison/extensions:bison_repository_ext.bzl", + "bison_repository_ext", +) +bison.repository( + name = "bison", + version = "3.3.2", + extra_copts = ["-O3"], +) +use_repo(bison, "bison") +register_toolchains("@bison//:toolchain") + +flex = use_extension( + "@rules_flex//flex/extensions:flex_repository_ext.bzl", + "flex_repository_ext", +) +flex.repository( + name = "flex", + version = "2.6.4", + extra_copts = ["-O3"], +) +use_repo(flex, "flex") +register_toolchains("@flex//:toolchain") doxygen_extension = use_extension("@rules_doxygen//:extensions.bzl", "doxygen_extension")
diff --git a/examples/doxygen_source.BUILD.bazel b/examples/doxygen_source.BUILD.bazel new file mode 100644 index 0000000..5f7ca4e --- /dev/null +++ b/examples/doxygen_source.BUILD.bazel
@@ -0,0 +1,35 @@ +load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") + +filegroup( + name = "all_srcs", + srcs = glob(["**"]), + visibility = ["//visibility:public"], +) + +cmake( + name = "doxygen", + lib_source = ":all_srcs", + out_binaries = ["doxygen"], + visibility = ["//visibility:public"], + env = { + "FLEX": "$$EXT_BUILD_DEPS/flex/bin/flex/bin", + }, + build_data = [ + "@rules_flex//flex:current_flex_toolchain", + "@rules_bison//bison:current_bison_toolchain", + ], +) + +genrule( + name = "doxygen_binary", + srcs = [":doxygen"], + outs = ["doxygen_bin"], + cmd = "cp $$1 $@", + visibility = ["//visibility:public"], +) + +filegroup( + name = "doxygen_source", + srcs = [":doxygen_binary"], + visibility = ["//visibility:public"], +)
diff --git a/examples/git_archive.bzl b/examples/git_archive.bzl new file mode 100644 index 0000000..745a5ac --- /dev/null +++ b/examples/git_archive.bzl
@@ -0,0 +1,93 @@ +"""Repository rules for downloading archives from GitHub and GitLab""" + +def workspace_and_buildfile(ctx): + """Utility function for writing WORKSPACE and, if requested, a BUILD file. + + This rule is intended to be used in the implementation function of a + repository rule. + It assumes the parameters `name`, `build_file`, `build_file_content`, + `workspace_file`, and `workspace_file_content` to be + present in `ctx.attr`; the latter four possibly with value None. + + Args: + ctx: The repository context of the repository rule calling this utility + function. + """ + if ctx.attr.build_file and ctx.attr.build_file_content: + ctx.fail("Only one of build_file and build_file_content can be provided.") + + if ctx.attr.workspace_file and ctx.attr.workspace_file_content: + ctx.fail("Only one of workspace_file and workspace_file_content can be provided.") + + if ctx.attr.workspace_file: + ctx.file("WORKSPACE", ctx.read(ctx.attr.workspace_file)) + elif ctx.attr.workspace_file_content: + ctx.file("WORKSPACE", ctx.attr.workspace_file_content) + else: + ctx.file("WORKSPACE", "workspace(name = \"{name}\")\n".format(name = ctx.name)) + + if ctx.attr.build_file: + ctx.file("BUILD.bazel", ctx.read(ctx.attr.build_file)) + elif ctx.attr.build_file_content: + ctx.file("BUILD.bazel", ctx.attr.build_file_content) + +def _github_archive_impl(repository_ctx): + """A rule to be called in the WORKSPACE that adds an external from github using a workspace rule. + + The required name= is the rule name and so is used for @name//... labels when referring to this archive from BUILD files. + + The required commit= is the git hash to download. + When the git project is also a git submodule in CMake, this should be kept in sync with the git submodule commit used there. + This can also be a tag. + + The required sha256= is the checksum of the downloaded archive. + When unsure, you can omit this argument (or comment it out) and then the checksum-mismatch error message message will offer a suggestion. + + The optional build_file= is the BUILD file label to use for building this external. + When omitted, the BUILD file(s) within the archive will be used. + + The optional local_repository_override= can be used for temporary local testing; + instead of retrieving the code from github, the code is retrieved from the local filesystem path given in the argument. + + Args: + repository_ctx: The context object for the repository rule. + """ + if repository_ctx.attr.build_file and repository_ctx.attr.build_file_content: + fail("Only one of build_file and build_file_content can be provided.") + if repository_ctx.attr.workspace_file and repository_ctx.attr.workspace_file_content: + fail("Only one of workspace_file and workspace_file_content can be provided.") + + repository = repository_ctx.attr.repository + commit = repository_ctx.attr.commit + + urls = ["https://github.com/%s/archive/%s.tar.gz" % (repository, commit)] + + repository_split = repository.split("/") + if len(repository_split) != 2: + fail("The repository must be formatted as 'organization/project'. Got: %s" % repository) + _, project = repository_split + + # Github archives omit the "v" in version tags, for some reason. + strip_commit = commit.removeprefix("v") + strip_prefix = project + "-" + strip_commit + + repository_ctx.download_and_extract( + urls, + sha256 = repository_ctx.attr.sha256, + stripPrefix = strip_prefix, + ) + workspace_and_buildfile(repository_ctx) + +github_archive = repository_rule( + implementation = _github_archive_impl, + local = True, + attrs = { + "repository": attr.string(mandatory = True, doc = "The github repository to download from."), + "commit": attr.string(mandatory = True, doc = "The git commit hash to download."), + "sha256": attr.string(default = "0" * 64, doc = "The sha256 checksum of the downloaded archive."), + "build_file": attr.label(doc = "The BUILD file label to use for building this external."), + "build_file_content": attr.string(doc = "The content for the BUILD file for this repository."), + "workspace_file": attr.label(doc = "The file to use as the `WORKSPACE` file for this repository."), + "workspace_file_content": attr.string(doc = "The content for the WORKSPACE file for this repository."), + }, +)
diff --git a/examples/source/BUILD.bazel b/examples/source/BUILD.bazel new file mode 100644 index 0000000..4f51bf7 --- /dev/null +++ b/examples/source/BUILD.bazel
@@ -0,0 +1,12 @@ +load("@doxygen//:doxygen.bzl", "doxygen") + +doxygen( + name = "doxygen", + srcs = glob([ + "*.h", + "*.cpp", + ]), + executable = "@doxygen_source//:doxygen_source", + project_brief = "Example project for doxygen", + project_name = "base", +)
diff --git a/examples/source/README.md b/examples/source/README.md new file mode 100644 index 0000000..c7f1c01 --- /dev/null +++ b/examples/source/README.md
@@ -0,0 +1,8 @@ +# Basic usage example + +This is a basic example of how to use the rules. +Move to the parent directory and run the following command: + +```bash +bazel build //base:doxygen +```
diff --git a/examples/source/lib.cpp b/examples/source/lib.cpp new file mode 100644 index 0000000..e9c08bc --- /dev/null +++ b/examples/source/lib.cpp
@@ -0,0 +1,9 @@ +/** + * @file lib.cpp + * @author Ernesto Casablanca (casablancaernesto@gmail.com) + * @copyright 2024 + */ + +#include "lib.h" + +int add(int a, int b) { return a + b; } \ No newline at end of file
diff --git a/examples/source/lib.h b/examples/source/lib.h new file mode 100644 index 0000000..9608ca2 --- /dev/null +++ b/examples/source/lib.h
@@ -0,0 +1,18 @@ +/** + * @file lib.h + * @author Ernesto Casablanca (casablancaernesto@gmail.com) + * @copyright 2024 + */ +#pragma once + +/** + * @brief Add two integers + * + * Who knows what the result will be? + * @note This function is very complex. Use it with caution. + * @warning The result can be greater than the maximum value that can be stored! + * @param a First integer + * @param b Second integer + * @return Sum of a and b + */ +int add(int a, int b); \ No newline at end of file