Initial Pigweed modules
This change adds Pigweed's first few (incomplete) modules: pw_build,
pw_status, and pw_toolchain. The main scaffolding for Pigweed's GN-based
build system is also included, with a root BUILDCONFIG and BUILD.gn file
defining a top-level modules build target.
Change-Id: I09599443d50696343d6c5b85853cb5cee3ce0026
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a4d2b69
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+# Build artifacts
+out/
+
+# IDE artifacts
+.idea/
+.project
+.cproject
+.vscode
+.clangd/
+
+# Python artifacts
+venv/
+*.pyc
+*.egg/
+*.eggs/
+*.egg-info/
+.cache/
+python-env/
+.mypy_cache/
+
+# Mac artifacts
+.DS_Store
+
+# Vim artifacts
+*.swp
+
+.gdb_history
diff --git a/.gn b/.gn
new file mode 100644
index 0000000..de099cc
--- /dev/null
+++ b/.gn
@@ -0,0 +1,16 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+buildconfig = "//BUILDCONFIG.gn"
+script_executable = "python3"
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..437d6e7
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+# All Pigweed modules that can be built using gn.
+group("pw_modules") {
+ deps = [
+ "$dir_pw_status",
+ ]
+}
diff --git a/BUILDCONFIG.gn b/BUILDCONFIG.gn
new file mode 100644
index 0000000..3cd4a1e
--- /dev/null
+++ b/BUILDCONFIG.gn
@@ -0,0 +1,48 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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("modules.gni")
+
+# Default configs to use for all binary build targets.
+_default_common_binary_configs = [
+ "$dir_pw_build:reduced_size",
+ "$dir_pw_build:strict_warnings",
+]
+
+set_defaults("executable") {
+ configs = _default_common_binary_configs
+}
+
+set_defaults("static_library") {
+ configs = _default_common_binary_configs
+}
+
+set_defaults("shared_library") {
+ configs = _default_common_binary_configs
+}
+
+set_defaults("source_set") {
+ configs = _default_common_binary_configs
+}
+
+declare_args() {
+ # The name of the GN template used to build Pigweed executables.
+ pw_executable_target_type = "executable"
+
+ # Path to the .gni file in which the pw_executable_target_type template is
+ # defined. Empty string if using a GN primitive.
+ pw_executable_target_path = ""
+}
+
+set_default_toolchain("$dir_pw_toolchain:arm_gcc_cortex_m4_og")
diff --git a/modules.gni b/modules.gni
new file mode 100644
index 0000000..d6647d7
--- /dev/null
+++ b/modules.gni
@@ -0,0 +1,27 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+# This file defines a directory variable for each of Pigweed's modules. This
+# allows modules to be moved or swapped out without breaking existing builds.
+# All module variables are prefixed with dir_.
+
+declare_args() {
+ # Location of the Pigweed modules directory (defaults to the directory of
+ # this file).
+ dir_pigweed = get_path_info(get_path_info("BUILD.gn", "abspath"), "dir")
+}
+
+dir_pw_build = "$dir_pigweed/pw_build"
+dir_pw_status = "$dir_pigweed/pw_status"
+dir_pw_toolchain = "$dir_pigweed/pw_toolchain"
diff --git a/pw_build/BUILD.gn b/pw_build/BUILD.gn
new file mode 100644
index 0000000..ebe935d
--- /dev/null
+++ b/pw_build/BUILD.gn
@@ -0,0 +1,40 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+# Standard compiler flags to reduce output binary size.
+config("reduced_size") {
+ cflags = [
+ "-fno-common",
+ "-fno-exceptions",
+ "-ffunction-sections",
+ "-fdata-sections",
+ ]
+ cflags_cc = [ "-fno-rtti" ]
+}
+
+config("strict_warnings") {
+ cflags = [
+ "-Wall",
+ "-Wextra",
+ ]
+}
+
+config("cpp17") {
+ cflags_cc = [ "-std=c++17" ]
+}
+
+# Default C++ version for Pigweed modules.
+config("pw_default_cpp") {
+ configs = [ ":cpp17" ]
+}
diff --git a/pw_build/README.md b/pw_build/README.md
new file mode 100644
index 0000000..3879b11
--- /dev/null
+++ b/pw_build/README.md
@@ -0,0 +1 @@
+# pw\_build: Definitions for Pigweed's build system.
diff --git a/pw_build/pw_executable.gni b/pw_build/pw_executable.gni
new file mode 100644
index 0000000..9b8666d
--- /dev/null
+++ b/pw_build/pw_executable.gni
@@ -0,0 +1,30 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+# Wrapper for Pigweed executable build targets which uses a globally-defined,
+# configurable target type.
+template("pw_executable") {
+ assert(defined(pw_executable_target_type),
+ "build argument pw_executable_target_type must be defined")
+ assert(defined(pw_executable_target_path),
+ "build argument pw_executable_target_path must be defined")
+
+ if (pw_executable_target_path != "") {
+ import(invoker.pw_executable_target_path)
+ }
+
+ target(invoker.pw_executable_target_type, target_name) {
+ forward_variables_from(invoker, "*")
+ }
+}
diff --git a/pw_status/BUILD.gn b/pw_status/BUILD.gn
new file mode 100644
index 0000000..c3172af
--- /dev/null
+++ b/pw_status/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+config("default_config") {
+ include_dirs = [ "public" ]
+}
+
+source_set("pw_status") {
+ public_configs = [
+ "$dir_pw_build:pw_default_cpp",
+ ":default_config",
+ ]
+ public = [
+ "public/pw_status/status.h",
+ ]
+ sources = [ "status.cc" ] + public
+}
diff --git a/pw_status/README.md b/pw_status/README.md
new file mode 100644
index 0000000..4261b75
--- /dev/null
+++ b/pw_status/README.md
@@ -0,0 +1 @@
+# pw\_status: Pigweed error codes.
diff --git a/pw_status/public/pw_status/status.h b/pw_status/public/pw_status/status.h
new file mode 100644
index 0000000..550b10a
--- /dev/null
+++ b/pw_status/public/pw_status/status.h
@@ -0,0 +1,176 @@
+// Copyright 2019 The Pigweed Authors
+//
+// 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
+//
+// https://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.
+
+#pragma once
+
+namespace pw {
+
+class Status {
+ public:
+ // These are the canonical Google error codes (copied from Tensorflow).
+ enum Code {
+ OK = 0,
+
+ // The operation was cancelled (typically by the caller).
+ CANCELLED = 1,
+
+ // Unknown error. An example of where this error may be returned is
+ // if a Status value received from another address space belongs to
+ // an error-space that is not known in this address space. Also,
+ // errors raised by APIs that do not return enough error information
+ // may be converted to this error.
+ UNKNOWN = 2,
+
+ // Client specified an invalid argument. Note that this differs
+ // from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments
+ // that are problematic regardless of the state of the system
+ // (e.g. a malformed file name).
+ INVALID_ARGUMENT = 3,
+
+ // Deadline expired before operation could complete. For operations
+ // that change the state of the system, this error may be returned
+ // even if the operation has completed successfully. For example, a
+ // successful response from a server could have been delayed long
+ // enough for the deadline to expire.
+ DEADLINE_EXCEEDED = 4,
+
+ // Some requested entity (e.g. file or directory) was not found.
+ // For privacy reasons, this code *may* be returned when the client
+ // does not have the access right to the entity.
+ NOT_FOUND = 5,
+
+ // Some entity that we attempted to create (e.g. file or directory)
+ // already exists.
+ ALREADY_EXISTS = 6,
+
+ // The caller does not have permission to execute the specified
+ // operation. PERMISSION_DENIED must not be used for rejections
+ // caused by exhausting some resource (use RESOURCE_EXHAUSTED
+ // instead for those errors). PERMISSION_DENIED must not be
+ // used if the caller cannot be identified (use UNAUTHENTICATED
+ // instead for those errors).
+ PERMISSION_DENIED = 7,
+
+ // The request does not have valid authentication credentials for the
+ // operation.
+ UNAUTHENTICATED = 16,
+
+ // Some resource has been exhausted, perhaps a per-user quota, or
+ // perhaps the entire filesystem is out of space.
+ RESOURCE_EXHAUSTED = 8,
+
+ // Operation was rejected because the system is not in a state
+ // required for the operation's execution. For example, directory
+ // to be deleted may be non-empty, an rmdir operation is applied to
+ // a non-directory, etc.
+ //
+ // A litmus test that may help a service implementer in deciding
+ // between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
+ // (a) Use UNAVAILABLE if the client can retry just the failing call.
+ // (b) Use ABORTED if the client should retry at a higher-level
+ // (e.g. restarting a read-modify-write sequence).
+ // (c) Use FAILED_PRECONDITION if the client should not retry until
+ // the system state has been explicitly fixed. E.g. if an "rmdir"
+ // fails because the directory is non-empty, FAILED_PRECONDITION
+ // should be returned since the client should not retry unless
+ // they have first fixed up the directory by deleting files from it.
+ // (d) Use FAILED_PRECONDITION if the client performs conditional
+ // REST Get/Update/Delete on a resource and the resource on the
+ // server does not match the condition. E.g. conflicting
+ // read-modify-write on the same resource.
+ FAILED_PRECONDITION = 9,
+
+ // The operation was aborted, typically due to a concurrency issue
+ // like sequencer check failures, transaction aborts, etc.
+ //
+ // See litmus test above for deciding between FAILED_PRECONDITION,
+ // ABORTED, and UNAVAILABLE.
+ ABORTED = 10,
+
+ // Operation tried to iterate past the valid input range. E.g. seeking or
+ // reading past end of file.
+ //
+ // Unlike INVALID_ARGUMENT, this error indicates a problem that may
+ // be fixed if the system state changes. For example, a 32-bit file
+ // system will generate INVALID_ARGUMENT if asked to read at an
+ // offset that is not in the range [0,2^32-1], but it will generate
+ // OUT_OF_RANGE if asked to read from an offset past the current
+ // file size.
+ //
+ // There is a fair bit of overlap between FAILED_PRECONDITION and
+ // OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific
+ // error) when it applies so that callers who are iterating through
+ // a space can easily look for an OUT_OF_RANGE error to detect when
+ // they are done.
+ OUT_OF_RANGE = 11,
+
+ // Operation is not implemented or not supported/enabled in this service.
+ UNIMPLEMENTED = 12,
+
+ // Internal errors. Means some invariants expected by underlying
+ // system has been broken. If you see one of these errors,
+ // something is very broken.
+ INTERNAL = 13,
+
+ // The service is currently unavailable. This is a most likely a
+ // transient condition and may be corrected by retrying with
+ // a backoff.
+ //
+ // See litmus test above for deciding between FAILED_PRECONDITION,
+ // ABORTED, and UNAVAILABLE.
+ UNAVAILABLE = 14,
+
+ // Unrecoverable data loss or corruption.
+ DATA_LOSS = 15,
+
+ // An extra enum entry to prevent people from writing code that
+ // fails to compile when a new code is added.
+ //
+ // Nobody should ever reference this enumeration entry. In particular,
+ // if you write C++ code that switches on this enumeration, add a default:
+ // case instead of a case that mentions this enumeration entry.
+ //
+ // Nobody should rely on the value listed here. It may change in the future.
+ DO_NOT_USE_RESERVED_FOR_FUTURE_EXPANSION_USE_DEFAULT_IN_SWITCH_INSTEAD_,
+ };
+
+ constexpr Status(Code code = Code::OK) : code_(code) {}
+
+ constexpr Status(const Status&) = default;
+ constexpr Status& operator=(const Status&) = default;
+
+ constexpr Status& operator=(Code code) {
+ code_ = code;
+ return *this;
+ }
+
+ constexpr Code code() const { return code_; }
+ constexpr bool ok() const { return code_ == Code::OK; }
+
+ // Returns a string representation of the Status::Code.
+ const char* str() const;
+
+ private:
+ Code code_;
+};
+
+constexpr bool operator==(Status lhs, Status rhs) {
+ return lhs.code() == rhs.code();
+}
+
+constexpr bool operator!=(Status lhs, Status rhs) {
+ return lhs.code() != rhs.code();
+}
+
+} // namespace pw
diff --git a/pw_status/status.cc b/pw_status/status.cc
new file mode 100644
index 0000000..4c0f49c
--- /dev/null
+++ b/pw_status/status.cc
@@ -0,0 +1,50 @@
+// Copyright 2019 The Pigweed Authors
+//
+// 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
+//
+// https://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.
+
+#include "pw_status/status.h"
+
+namespace pw {
+
+#define PW_CASE_RETURN_ENUM_STRING(value) \
+ case (value): \
+ return #value
+
+const char* Status::str() const {
+ // Status codes are ordered by assigned number (UNAUTHENTICATED is last).
+ switch (code_) {
+ PW_CASE_RETURN_ENUM_STRING(OK);
+ PW_CASE_RETURN_ENUM_STRING(CANCELLED);
+ PW_CASE_RETURN_ENUM_STRING(UNKNOWN);
+ PW_CASE_RETURN_ENUM_STRING(INVALID_ARGUMENT);
+ PW_CASE_RETURN_ENUM_STRING(DEADLINE_EXCEEDED);
+ PW_CASE_RETURN_ENUM_STRING(NOT_FOUND);
+ PW_CASE_RETURN_ENUM_STRING(ALREADY_EXISTS);
+ PW_CASE_RETURN_ENUM_STRING(PERMISSION_DENIED);
+ PW_CASE_RETURN_ENUM_STRING(RESOURCE_EXHAUSTED);
+ PW_CASE_RETURN_ENUM_STRING(FAILED_PRECONDITION);
+ PW_CASE_RETURN_ENUM_STRING(ABORTED);
+ PW_CASE_RETURN_ENUM_STRING(OUT_OF_RANGE);
+ PW_CASE_RETURN_ENUM_STRING(UNIMPLEMENTED);
+ PW_CASE_RETURN_ENUM_STRING(INTERNAL);
+ PW_CASE_RETURN_ENUM_STRING(UNAVAILABLE);
+ PW_CASE_RETURN_ENUM_STRING(DATA_LOSS);
+ PW_CASE_RETURN_ENUM_STRING(UNAUTHENTICATED);
+ default:
+ return "INVALID STATUS";
+ }
+}
+
+#undef PW_CASE_RETURN_ENUM_STRING
+
+} // namespace pw
diff --git a/pw_toolchain/BUILD.gn b/pw_toolchain/BUILD.gn
new file mode 100644
index 0000000..c0743ce
--- /dev/null
+++ b/pw_toolchain/BUILD.gn
@@ -0,0 +1,122 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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("arm_gcc.gni")
+
+# Creates a series of toolchain targets with common compiler options.
+#
+# Args:
+# toolchain_template: The target template to use to create the toolchains.
+# common_toolchain_cflags: cflags to be shared by all toolchains.
+# common_toolchain_ldflags: ldflags to be shared by all toolchains.
+# toolchains: List of scopes defining each of the desired toolchains.
+# Each scope contains up to three variables:
+# toolchain_name: The full target name of the toolchain.
+# additional_cflags: Optional list of extra cflags for the toolchain.
+# additional_ldflags: Optional list of extra ldflags for the toolchain.
+template("generate_toolchains") {
+ not_needed([ "target_name" ])
+
+ assert(defined(invoker.toolchain_template),
+ "generate_toolchains requires a toolchain template")
+ assert(defined(invoker.toolchains),
+ "generate_toolchains must be called with a list of toolchains")
+
+ if (defined(invoker.common_toolchain_cflags)) {
+ _common_cflags = invoker.common_toolchain_cflags
+ } else {
+ _common_cflags = []
+ }
+
+ if (defined(invoker.common_toolchain_ldflags)) {
+ _common_ldflags = invoker.common_toolchain_ldflags
+ } else {
+ _common_ldflags = []
+ }
+
+ # Create a target for each of the desired toolchains, appending its own cflags
+ # and ldflags to the common ones.
+ foreach(toolchain_config, invoker.toolchains) {
+ # GN does not allow assigning a non-empty array to a non-empty array.
+ # This must be done as two assignments, first clearing the original value.
+ _toolchain_cflags = []
+ _toolchain_cflags = _common_cflags
+ if (defined(toolchain_config.additional_cflags)) {
+ _toolchain_cflags += toolchain_config.additional_cflags
+ }
+
+ _toolchain_ldflags = []
+ _toolchain_ldflags = _common_ldflags
+ if (defined(toolchain_config.additional_ldflags)) {
+ _toolchain_ldflags += toolchain_config.additional_ldflags
+ }
+
+ target(invoker.toolchain_template, toolchain_config.toolchain_name) {
+ toolchain_cflags = _toolchain_cflags
+ toolchain_ldflags = _toolchain_ldflags
+ }
+ }
+}
+
+generate_toolchains("cortex_m4") {
+ toolchain_template = "arm_gcc_toolchain"
+
+ common_toolchain_cflags = [
+ "-mabi=aapcs",
+ "-mcpu=cortex-m4",
+ "-mfpu=fpv4-sp-d16",
+ "-mfloat-abi=hard",
+ "-mthumb",
+
+ # Disable obnoxious ABI warning.
+ #
+ # GCC 7.1 adds an over-zealous ABI warning with little useful information
+ # on how to resolve the issue. The warning you get is:
+ #
+ # note: parameter passing for argument of type '...' changed in GCC 7.1
+ #
+ # There is no other information, and searching for the error is needed to
+ # understand what is happening. For upstream Pigweed, we compile from
+ # source so this is irrelevant; so disable it.
+ #
+ # See: https://gcc.gnu.org/gcc-7/changes.html (search for "psabi").
+ # https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
+ "-Wno-psabi",
+ ]
+
+ common_toolchain_ldflags = [
+ "--specs=nosys.specs",
+ "-lnosys",
+ "-lc",
+ ]
+
+ toolchains = [
+ {
+ toolchain_name = "arm_gcc_cortex_m4_og"
+ additional_cflags = [ "-Og" ]
+ },
+ {
+ toolchain_name = "arm_gcc_cortex_m4_o1"
+ additional_cflags = [ "-O1" ]
+ },
+ {
+ toolchain_name = "arm_gcc_cortex_m4_o2"
+ additional_cflags = [ "-O2" ]
+ },
+ {
+ toolchain_name = "arm_gcc_cortex_m4_os"
+ additional_cflags = [ "-Os" ]
+ },
+ ]
+}
diff --git a/pw_toolchain/README.md b/pw_toolchain/README.md
new file mode 100644
index 0000000..e73f45d
--- /dev/null
+++ b/pw_toolchain/README.md
@@ -0,0 +1 @@
+# pw\_toolchain: Pigweed's standard build toolchains.
diff --git a/pw_toolchain/arm_gcc.gni b/pw_toolchain/arm_gcc.gni
new file mode 100644
index 0000000..1b20d4f
--- /dev/null
+++ b/pw_toolchain/arm_gcc.gni
@@ -0,0 +1,121 @@
+# Copyright 2019 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+
+# Generates an arm-eabi-none gcc toolchain for a specific target.
+#
+# Args:
+# toolchain_cflags: Additional C/C++ compiler flags for the target.
+# toolchain_ldflags: Additional linker flags for the target.
+template("arm_gcc_toolchain") {
+ _toolchain_cflags = ""
+ if (defined(invoker.toolchain_cflags)) {
+ foreach(flag, invoker.toolchain_cflags) {
+ _toolchain_cflags += " " + flag
+ }
+ }
+
+ _toolchain_ldflags = ""
+ if (defined(invoker.toolchain_ldflags)) {
+ foreach(flag, invoker.toolchain_ldflags) {
+ _toolchain_ldflags += " " + flag
+ }
+ }
+
+ # TODO(frolv): This assumes that the ARM gcc toolchain is in the PATH.
+ # It should be updated to point to the prebuilt path within the source tree
+ # once that is added.
+ _tool_name_root = "arm-none-eabi-"
+
+ _ar = _tool_name_root + "ar"
+ _cc = _tool_name_root + "gcc"
+ _cxx = _tool_name_root + "g++"
+
+ toolchain(target_name) {
+ tool("asm") {
+ depfile = "{{output}}.d"
+ command = "$_cc -MMD -MF $depfile $_toolchain_cflags {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "as {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("cc") {
+ depfile = "{{output}}.d"
+ command = "$_cc -MMD -MF $depfile $_toolchain_cflags {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "cc {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("cxx") {
+ depfile = "{{output}}.d"
+ command = "$_cxx -MMD -MF $depfile $_toolchain_cflags {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "c++ {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("alink") {
+ command = "rm -f {{output}} && $_ar rcs {{output}} {{inputs}}"
+ description = "ar {{target_output_name}}{{output_extension}}"
+ outputs = [
+ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
+ ]
+ default_output_extension = ".a"
+ }
+
+ lib_switch = "-l"
+ lib_dir_switch = "-L"
+
+ _link_outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ _link_mapfile = "{{output_dir}}/{{target_output_name}}.map"
+ _link_command = "$_cxx {{ldflags}} -Wl,--gc-sections $_toolchain_cflags $_toolchain_ldflags -Wl,--start-group {{inputs}} -Wl,--end-group {{libs}} -Wl,-Map=$_link_mapfile -o $_link_outfile"
+
+ tool("link") {
+ command = _link_command
+ description = "ld $_link_outfile"
+ outputs = [
+ _link_outfile,
+ ]
+ default_output_dir = "{{target_out_dir}}"
+ default_output_extension = ".elf"
+ }
+
+ tool("solink") {
+ command = _link_command + " -shared"
+ description = "ld -shared $_link_outfile"
+ outputs = [
+ _link_outfile,
+ ]
+ default_output_dir = "{{target_out_dir}}"
+ default_output_extension = ".so"
+ }
+
+ tool("stamp") {
+ command = "touch {{output}}"
+ description = "stamp {{output}}"
+ }
+
+ tool("copy") {
+ command = "cp -af {{source}} {{output}}"
+ description = "cp {{source}} {{output}}"
+ }
+ }
+}