Make better use of toolchains in the build.
This allows building for different platforms without having to retarget
the build. The configuration is also better checked by the assertions in
the toolchain templates.
A future change will redirect the root build rule to allow BSPs to
fully control their own build and configuration.
Change-Id: Iaae725d3bd000bc0ce7b9ef0f8f083350a73bd16
diff --git a/build/BUILD.gn b/build/BUILD.gn
index 9a6eaf2..46c73c7 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -12,9 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import("//build/arch/common.gni")
-import("//build/arch/aarch64.gni") # TODO: remove when no dependency on arch_aarch64_pl011_base_address
+import("//build/toolchain/platform.gni")
+# Default language and error reporting configuration.
config("compiler_defaults") {
cflags = [
"-g",
@@ -29,65 +29,24 @@
cflags_c = [ "-std=c11" ]
cflags_cc = [ "-std=c++14" ]
-
- if (current_toolchain == fake_toolchain ||
- current_toolchain == arch_toolchain) {
- include_dirs = [
- "//inc",
- "//inc/vmapi",
- "//src/arch/${arch}/inc",
- ]
-
- defines = [
- # TODO: move these build args for the platforms
- "MAX_CPUS=8",
- "MAX_VMS=16",
- "STACK_SIZE=4096",
- ]
-
- if (is_debug) {
- defines += [ "DEBUG=1" ]
- } else {
- defines += [ "DEBUG=0" ]
- }
-
- # Configuration specific for the bare metal images.
- if (current_toolchain == arch_toolchain) {
- include_dirs += [ "${root_gen_dir}/inc" ]
-
- cflags += [
- "-mcpu=${arch_cpu}",
- "-mstrict-align",
- "-fno-stack-protector",
- "-fno-builtin",
- "-ffreestanding",
- "-fpic",
- ]
-
- # TODO: this should be arch specific but it is currenly used by the
- # platform generic code to map the memory
- if (arch_aarch64_use_pl011) {
- defines += [ "PL011_BASE=${arch_aarch64_pl011_base_address}" ]
- }
- }
- }
}
-config("executable_ldconfig") {
- if (current_toolchain == arch_toolchain) {
- ldflags = [ "--gc-sections" ]
- }
-}
-
-config("sections") {
- cflags = [
- "-ffunction-sections",
- "-fdata-sections",
+# Platform configuration.
+config("platform") {
+ include_dirs = [
+ "//inc",
+ "//inc/vmapi",
+ "//src/arch/${arch}/inc",
]
-}
-config("lto") {
- if (current_toolchain == arch_toolchain) {
- cflags = [ "-flto" ]
+ defines = [
+ "MAX_CPUS=${platform_max_cpus}",
+ "MAX_VMS=${platform_max_vms}",
+ ]
+
+ if (is_debug) {
+ defines += [ "DEBUG=1" ]
+ } else {
+ defines += [ "DEBUG=0" ]
}
}
diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn
index 62cf43d..aca2f24 100644
--- a/build/BUILDCONFIG.gn
+++ b/build/BUILDCONFIG.gn
@@ -12,42 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This build configuration extends GN's cross-compilation concepts of "target",
-# "host" and "current" with "arch" which is used to refer to the embedded
-# architecture that the bare metal images are being built for.
-#
-# The concepts of "target", "host" and "current" are used when bulding tests
-# and utilities for the non-embedded device. Note that there hasn't been any
-# thought given to support building for anything other than the host so it
-# probably won't work.
-#
-# In summary:
-# - host{_os,_cpu,_toolchain} is for the system running the build
-# - target{_os,_cpu,_toolchain} is for the system that will run utilities and tests
-# - arch{,_toolchain} is for the embedded system that will run the bare metal images
-
# Configuration of the build toolchain.
declare_args() {
# Enable extra debugging.
is_debug = true
- # Set to true to build with gcc (default is clang).
- use_gcc = false
-
# The architecture to build the bare metal images for.
- arch = ""
-
- # Set by arch toolchain. Prefix for binutils tools.
- arch_tool_prefix = ""
+ arch = "host"
}
-# Check that we support the attempted build
-assert(host_os == "linux", "Only linux builds are currently supported")
+# Check that we support the attempted build.
+assert(host_os == "linux", "Only linux builds are currently supported.")
-# Check that the requested architecture is supported
-assert(arch == "aarch64" || arch == "fake", "Unsupported arch: $arch")
-
-# Setup the standard variables
+# Setup the standard variables.
if (target_os == "") {
target_os = host_os
}
@@ -61,22 +38,20 @@
current_cpu = target_cpu
}
-assert(target_os == host_os, "Cross compiles not yet supported")
-assert(target_cpu == host_cpu, "Cross compiles not yet supported")
+assert(target_os == host_os, "Cross compiles not yet supported.")
+assert(target_cpu == host_cpu, "Cross compiles not yet supported.")
-# All binary targets will get this list of configs by default
-_shared_binary_target_configs = [
- "//build:compiler_defaults",
- "//build:sections",
- "//build:lto",
-]
+# All binary targets will get this list of configs by default.
+_shared_binary_target_configs = [ "//build:compiler_defaults" ]
+
+# If it's not building a host utility, it's building against the platform so apply the configuration.
+if (arch != "host") {
+ _shared_binary_target_configs += [ "//build:platform" ]
+}
# Apply that default list to the binary target types.
set_defaults("executable") {
configs = _shared_binary_target_configs
-
- # Executables get this additional configuration
- configs += [ "//build:executable_ldconfig" ]
}
set_defaults("static_library") {
configs = _shared_binary_target_configs
@@ -88,18 +63,5 @@
configs = _shared_binary_target_configs
}
-# Select host, target and arch toolchains
-if (use_gcc) {
- host_toolchain = "//build/toolchain/host:gcc"
- target_toolchain = "//build/toolchain/host:gcc"
- fake_toolchain = "//build/toolchain/host:gcc_fake_arch"
- arch_toolchain = "//build/toolchain/arch:gcc_${arch}"
-} else {
- host_toolchain = "//build/toolchain/host:clang"
- target_toolchain = "//build/toolchain/host:clang"
- fake_toolchain = "//build/toolchain/host:clang_fake_arch"
- arch_toolchain = "//build/toolchain/arch:clang_${arch}"
-}
-
-# The default toolchain is the target toolchain for building utilities and tests
-set_default_toolchain(target_toolchain)
+# The default toolchain is the target toolchain for building utilities and tests.
+set_default_toolchain("//build/toolchain:host_clang")
diff --git a/build/arch/aarch64/fvp.args b/build/arch/aarch64/fvp.args
deleted file mode 100644
index ecb4af1..0000000
--- a/build/arch/aarch64/fvp.args
+++ /dev/null
@@ -1,5 +0,0 @@
-arch_cpu = "cortex-a57+nofp"
-arch_hypervisor_origin_address = "0x88000000"
-
-arch_aarch64_use_pl011 = true
-arch_aarch64_pl011_base_address = "0x1c090000"
diff --git a/build/arch/aarch64/hikey.args b/build/arch/aarch64/hikey.args
deleted file mode 100644
index d08989d7..0000000
--- a/build/arch/aarch64/hikey.args
+++ /dev/null
@@ -1,6 +0,0 @@
-arch_cpu = "cortex-a57+nofp"
-arch_hypervisor_origin_address = "0x01000000"
-
-# Use UART3.
-arch_aarch64_use_pl011 = true
-arch_aarch64_pl011_base_address = "0xf7113000"
diff --git a/build/arch/aarch64/qemu.args b/build/arch/aarch64/qemu.args
deleted file mode 100644
index a822859..0000000
--- a/build/arch/aarch64/qemu.args
+++ /dev/null
@@ -1,5 +0,0 @@
-arch_cpu = "cortex-a57+nofp"
-arch_hypervisor_origin_address = "0x40001000"
-
-arch_aarch64_use_pl011 = true
-arch_aarch64_pl011_base_address = "0x09000000"
diff --git a/build/arch/common.gni b/build/arch/common.gni
deleted file mode 100644
index ca2e285..0000000
--- a/build/arch/common.gni
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# 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.
-
-declare_args() {
- # The specific CPU that runs the architecture.
- arch_cpu = ""
-
- # The origin address of the hypervisor image
- arch_hypervisor_origin_address = ""
-}
-
-assert(arch_cpu != "", "Must provide the CPU to build for as \"arch_cpu\".")
-assert(
- arch_hypervisor_origin_address != "",
- "Must provide the origin address of the hypervisor image \"arch_hypervisor_origin_address\".")
diff --git a/build/image/extract_offsets.py b/build/image/extract_offsets.py
deleted file mode 100644
index e0a2b4a..0000000
--- a/build/image/extract_offsets.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2018 Google LLC
-#
-# 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.
-
-"""Extract embedded offsets from an object file.
-
-We let the compiler calculate the offsets it is going to use and have those
-emitted into and object file. This is the next pass which extracts those offsets
-and stores them in a header file for the assembly to include and use.
-"""
-
-import argparse
-import re
-import subprocess
-import sys
-
-
-def Main():
- parser = argparse.ArgumentParser()
- parser.add_argument("--tool_prefix", required=True)
- parser.add_argument("--input", required=True)
- parser.add_argument("--output", required=True)
- args = parser.parse_args()
- raw = subprocess.check_output([
- "{}objdump".format(args.tool_prefix), "--disassemble-all", "--section",
- ".rodata", args.input
- ])
- lines = raw.split('\n')
- with open(args.output, 'w') as header:
- header.write('#pragma once\n\n')
- for n in range(len(lines)):
- # Find a defined offset
- match = re.match('.+DEFINE_OFFSET__([^>]+)', lines[n])
- if not match:
- continue
- name = match.group(1)
- # The next line tells the offset
- if "..." in lines[n + 1]:
- offset = 0
- else:
- offset = re.match('.+\.[\S]+\s+(.+)$', lines[n + 1]).group(1)
- # Write the offset to the header
- header.write("#define {} {}\n".format(name, offset))
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(Main())
diff --git a/build/image/generate_offsets.gni b/build/image/generate_offsets.gni
deleted file mode 100644
index cce64bd..0000000
--- a/build/image/generate_offsets.gni
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# 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.
-
-# Calculates offsets of fields in C structures for use in assembly.
-template("generate_offsets") {
- # There are 3 targets involved:
- # 1. have the compiler calculate the offsets
- # 2. extract those offsets to a header file
- # 3. include the offsets in the build for validation
- obj_target = "${target_name}__obj"
- header_target = "${target_name}__header"
- validate_target = target_name
-
- # Have the compiler calculate the offsets and store that information in the
- # object file to extract later.
- source_set(obj_target) {
- forward_variables_from(invoker,
- [
- "cflags",
- "cflags_c",
- "defines",
- "deps",
- "public_deps",
- "sources",
- "testonly",
- ])
-
- # Disable LTO so we get an object file.
- configs -= [
- "//build:sections",
- "//build:lto",
- ]
- defines = [ "GEN_OFFSETS" ]
- visibility = [ ":${header_target}" ]
- }
-
- # Extract the offset information we've had the compiler emit into the object
- # file.
- action_foreach("${header_target}") {
- forward_variables_from(invoker,
- [
- "sources",
- "testonly",
- ])
- script = "//build/image/extract_offsets.py"
- deps = [
- ":${obj_target}",
- ]
- args = [
- "--tool_prefix",
- arch_tool_prefix,
- "--input",
- rebase_path("${target_out_dir}/${obj_target}.{{source_name_part}}.o"),
- "--output",
- rebase_path("${root_gen_dir}/inc/{{source_name_part}}.h"),
- ]
- outputs = [
- "${root_gen_dir}/inc/{{source_name_part}}.h",
- ]
- visibility = [ ":${validate_target}" ]
- }
-
- # Include the offset source file in the build so the extracted offsets can be
- # validated.
- source_set(validate_target) {
- forward_variables_from(invoker,
- [
- "cflags",
- "cflags_c",
- "defines",
- "deps",
- "public_deps",
- "sources",
- "testonly",
- ])
-
- deps = [
- ":${header_target}",
- ]
- }
-}
diff --git a/build/image/image.gni b/build/image/image.gni
index b1b1895..2f9da5b 100644
--- a/build/image/image.gni
+++ b/build/image/image.gni
@@ -12,14 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import("//build/arch/common.gni")
+import("//build/toolchain/embedded.gni")
# Build image, link to an ELF file then convert to plain binary.
template("image_binary") {
assert(defined(invoker.image_name),
"image_binary() must specify an \"image_name\" value")
- assert(defined(invoker.origin_address),
- "image_binary() must specify an \"origin_address\" value")
output_root = ""
if (defined(invoker.output_path)) {
@@ -44,10 +42,8 @@
rebase_path("//build/image/image.ld"),
]
ldflags = [
- "-pie",
"-T",
rebase_path("//build/image/image.ld"),
- "--defsym=ORIGIN_ADDRESS=${invoker.origin_address}",
]
visibility = [ ":${invoker.target_name}" ]
}
@@ -65,7 +61,7 @@
]
args = [
"--tool_prefix",
- arch_tool_prefix,
+ tool_prefix,
"--input",
rebase_path(elf_file),
"--output",
@@ -91,7 +87,6 @@
"testonly",
])
image_name = target_name
- origin_address = arch_hypervisor_origin_address
}
}
@@ -110,7 +105,6 @@
])
output_path = "vm"
image_name = target_name
- origin_address = "0x1000"
}
}
diff --git a/build/toolchain/BUILD.gn b/build/toolchain/BUILD.gn
new file mode 100644
index 0000000..344d30e
--- /dev/null
+++ b/build/toolchain/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright 2018 Google LLC
+#
+# 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("//build/toolchain/embedded.gni")
+import("//build/toolchain/host.gni")
+
+host_toolchain("host") {
+ use_fake_arch = false
+}
+
+host_toolchain("host_fake") {
+ use_fake_arch = true
+ max_cpus = 4
+ max_vms = 6
+}
+
+aarch64_toolchain("qemu_aarch64") {
+ cpu = "cortex-a57+nofp"
+ origin_address = "0x40001000"
+ use_pl011 = true
+ pl011_base_address = "0x09000000"
+ max_cpus = 8
+ max_vms = 16
+}
+
+aarch64_toolchain("hikey") {
+ cpu = "cortex-a53+nofp"
+ origin_address = "0x01000000"
+ use_pl011 = true
+ pl011_base_address = "0xf8015000"
+ max_cpus = 8
+ max_vms = 16
+}
+
+aarch64_toolchain("aem_v8a_fvp") {
+ cpu = "cortex-a57+nofp"
+ origin_address = "0x88000000"
+ use_pl011 = true
+ pl011_base_address = "0x1c090000"
+ max_cpus = 8
+ max_vms = 16
+}
diff --git a/build/toolchain/arch/BUILD.gn b/build/toolchain/arch/BUILD.gn
deleted file mode 100644
index 6ce6207..0000000
--- a/build/toolchain/arch/BUILD.gn
+++ /dev/null
@@ -1,131 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# 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.
-
-# Target toolchain specific build arguments.
-declare_args() {
- # Build with a specific compiler version e.g. when building with clang, set
- # to "3.9" to build with `clang-3.9`.
- arch_cc_version = ""
-}
-
-# Template for target toolchains; there is no support for C++ or libraries.
-# Instead, use source_set to group source together.
-template("cc_toolchain") {
- toolchain(target_name) {
- assert(defined(invoker.cc), "cc_toolchain() must specify a \"cc\" value")
- assert(defined(invoker.ld), "cc_toolchain() must specify a \"ld\" value")
-
- # Combine compiler version and compiler specific flags for this toolchain.
- cc = "${invoker.cc}"
- if (arch_cc_version != "") {
- cc += "-${arch_cc_version}"
- }
- if (defined(invoker.cflags)) {
- cc += " ${invoker.cflags}"
- }
-
- tool("cc") {
- depfile = "{{output}}.d"
- command = "${cc} -MMD -MF $depfile {{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("asm") {
- depfile = "{{output}}.d"
- command = "${cc} -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
- depsformat = "gcc"
- description = "ASM {{output}}"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
- }
-
- tool("link") {
- outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
- rspfile = "$outfile.rsp"
- command = "${invoker.ld} {{ldflags}} -o $outfile --start-group @$rspfile --end-group"
- description = "LINK $outfile"
- default_output_dir = "{{root_out_dir}}"
- rspfile_content = "{{inputs}}"
- outputs = [
- outfile,
- ]
- }
-
- tool("stamp") {
- command = "touch {{output}}"
- description = "STAMP {{output}}"
- }
-
- tool("copy") {
- command = "cp -af {{source}} {{output}}"
- description = "COPY {{source}} {{output}}"
- }
-
- toolchain_args = {
- forward_variables_from(invoker.toolchain_args, "*")
- }
- }
-}
-
-# Specialize for clang or gcc
-template("clang_toolchain") {
- assert(defined(invoker.target),
- "clang_toolchain() must specify a \"target\" value")
- assert(defined(invoker.arch_tool_prefix),
- "gcc_toolchain() must specify a \"arch_tool_prefix\" value")
-
- cc_toolchain(target_name) {
- cc = "clang"
- cflags = "-target ${invoker.target} -fcolor-diagnostics"
- ld = "ld.lld --color-diagnostics -O2 -lto-O2 --icf=all --fatal-warnings"
-
- toolchain_args = {
- arch_tool_prefix = invoker.arch_tool_prefix
- }
- }
-}
-
-template("gcc_toolchain") {
- assert(defined(invoker.arch_tool_prefix),
- "gcc_toolchain() must specify a \"arch_tool_prefix\" value")
-
- cc_toolchain(target_name) {
- cc = "${invoker.arch_tool_prefix}gcc"
- cflags = "-fdiagnostics-color=always"
- ld = "${invoker.arch_tool_prefix}ld"
-
- toolchain_args = {
- arch_tool_prefix = invoker.arch_tool_prefix
- }
- }
-}
-
-# Specialize for different architectures
-
-clang_toolchain("clang_aarch64") {
- target = "aarch64-none-eabi"
-
- # TODO: below isn't right for bare metal code, but it works fine
- arch_tool_prefix = "aarch64-linux-gnu-"
-}
-
-gcc_toolchain("gcc_aarch64") {
- # TODO: below isn't right for bare metal code, but it works fine
- arch_tool_prefix = "aarch64-linux-gnu-"
-}
diff --git a/build/toolchain/embedded.gni b/build/toolchain/embedded.gni
new file mode 100644
index 0000000..b9a5cdd
--- /dev/null
+++ b/build/toolchain/embedded.gni
@@ -0,0 +1,248 @@
+# Copyright 2018 Google LLC
+#
+# 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.
+
+declare_args() {
+ # Set by arch toolchain. Prefix for binutils tools.
+ tool_prefix = ""
+}
+
+# Template for embedded toolchains; there is no support for C++ or libraries.
+# Instead, use source_set to group source together.
+template("embedded_cc_toolchain") {
+ toolchain(target_name) {
+ assert(defined(invoker.cc), "\"cc\" must be defined for ${target_name}.")
+ assert(defined(invoker.ld), "\"ld\" must be defined for ${target_name}.")
+
+ # Collect extra flags from the toolchain.
+ extra_defines = ""
+ extra_cflags = "-flto -ffunction-sections -fdata-sections"
+ extra_ldflags = "--gc-sections -pie"
+ if (defined(invoker.extra_defines)) {
+ extra_defines += " ${invoker.extra_defines}"
+ }
+ if (defined(invoker.extra_cflags)) {
+ extra_cflags += " ${invoker.extra_cflags}"
+ }
+ if (defined(invoker.extra_ldflags)) {
+ extra_ldflags += " ${invoker.extra_ldflags}"
+ }
+
+ # Define the tools.
+ tool("cc") {
+ depfile = "{{output}}.d"
+ command = "${invoker.cc} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} ${extra_cflags} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "CC {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("asm") {
+ depfile = "{{output}}.d"
+ command = "${invoker.cc} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "ASM {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("link") {
+ outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ rspfile = "$outfile.rsp"
+ command = "${invoker.ld} ${extra_ldflags} {{ldflags}} -o $outfile --start-group @$rspfile --end-group"
+ description = "LINK $outfile"
+ default_output_dir = "{{root_out_dir}}"
+ rspfile_content = "{{inputs}}"
+ outputs = [
+ outfile,
+ ]
+ }
+
+ tool("stamp") {
+ command = "touch {{output}}"
+ description = "STAMP {{output}}"
+ }
+
+ tool("copy") {
+ command = "cp -af {{source}} {{output}}"
+ description = "COPY {{source}} {{output}}"
+ }
+
+ toolchain_args = {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
+}
+
+# Specialize for clang.
+template("embedded_clang_toolchain") {
+ assert(defined(invoker.target),
+ "\"target\" must be defined for ${target_name}.")
+ assert(defined(invoker.tool_prefix),
+ "\"tool_prefix\" must be defined for ${target_name}.")
+
+ embedded_cc_toolchain(target_name) {
+ cc = "clang -target ${invoker.target} -fcolor-diagnostics"
+ ld = "ld.lld --color-diagnostics"
+
+ extra_defines = ""
+ extra_cflags = ""
+ extra_ldflags = "-O2 -lto-O2 --icf=all --fatal-warnings"
+ if (defined(invoker.extra_defines)) {
+ extra_defines += " ${invoker.extra_defines}"
+ }
+ if (defined(invoker.extra_cflags)) {
+ extra_cflags += " ${invoker.extra_cflags}"
+ }
+ if (defined(invoker.extra_ldflags)) {
+ extra_ldflags += " ${invoker.extra_ldflags}"
+ }
+
+ toolchain_args = {
+ tool_prefix = invoker.tool_prefix
+ if (defined(invoker.toolchain_args)) {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
+ }
+}
+
+# Specialize for gcc.
+template("embedded_gcc_toolchain") {
+ assert(defined(invoker.tool_prefix),
+ "\"tool_prefix\" must be defined for ${target_name}.")
+
+ embedded_cc_toolchain(target_name) {
+ cc = "${invoker.tool_prefix}gcc -fdiagnostics-color=always"
+ ld = "${invoker.tool_prefix}ld"
+
+ extra_defines = ""
+ extra_cflags = ""
+ extra_ldflags = ""
+ if (defined(invoker.extra_defines)) {
+ extra_defines += " ${invoker.extra_defines}"
+ }
+ if (defined(invoker.extra_cflags)) {
+ extra_cflags += " ${invoker.extra_cflags}"
+ }
+ if (defined(invoker.extra_ldflags)) {
+ extra_ldflags += " ${invoker.extra_ldflags}"
+ }
+
+ toolchain_args = {
+ tool_prefix = invoker.tool_prefix
+ if (defined(invoker.toolchain_args)) {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
+ }
+}
+
+# Expand to clang and gcc variants.
+template("embedded_platform_toolchain") {
+ assert(defined(invoker.arch), "\"arch\" must be defined for ${target_name}.")
+ assert(defined(invoker.target),
+ "\"target\" must be defined for ${target_name}.")
+ assert(defined(invoker.tool_prefix),
+ "\"tool_prefix\" must be defined for ${target_name}.")
+ assert(defined(invoker.origin_address),
+ "\"origin_address\" must be defined for ${target_name}.")
+ assert(defined(invoker.max_cpus),
+ "\"max_cpus\" must be defined for ${target_name}.")
+ assert(defined(invoker.max_vms),
+ "\"max_vms\" must be defined for ${target_name}.")
+
+ defines = ""
+ cflags = "-fno-stack-protector -fno-builtin -ffreestanding -fpic"
+ ldflags = "--defsym=ORIGIN_ADDRESS=${invoker.origin_address}"
+ if (defined(invoker.extra_defines)) {
+ defines += " ${invoker.extra_defines}"
+ }
+ if (defined(invoker.extra_cflags)) {
+ cflags += " ${invoker.extra_cflags}"
+ }
+ if (defined(invoker.extra_ldflags)) {
+ ldflags += " ${invoker.extra_ldflags}"
+ }
+
+ embedded_clang_toolchain("${target_name}_clang") {
+ target = invoker.target
+ tool_prefix = invoker.tool_prefix
+ extra_defines = defines
+ extra_cflags = cflags
+ extra_ldflags = ldflags
+ toolchain_args = {
+ platform_max_cpus = invoker.max_cpus
+ platform_max_vms = invoker.max_vms
+ arch = invoker.arch
+ if (defined(invoker.toolchain_args)) {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
+ }
+
+ embedded_gcc_toolchain("${target_name}_gcc") {
+ tool_prefix = invoker.tool_prefix
+ extra_defines = defines
+ extra_cflags = cflags
+ extra_ldflags = ldflags
+ toolchain_args = {
+ platform_max_cpus = invoker.max_cpus
+ platform_max_vms = invoker.max_vms
+ arch = invoker.arch
+ if (defined(invoker.toolchain_args)) {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
+ }
+}
+
+# Specialize for different architectures.
+
+template("aarch64_toolchain") {
+ assert(defined(invoker.cpu), "\"cpu\" must be defiend for ${target_name}.")
+ assert(defined(invoker.origin_address),
+ "\"origin_address\" must be defined for ${target_name}.")
+ assert(defined(invoker.use_pl011),
+ "\"use_pl011\" must be defined for ${target_name}.")
+ assert(defined(invoker.max_cpus),
+ "\"max_cpus\" must be defined for ${target_name}.")
+ assert(defined(invoker.max_vms),
+ "\"max_vms\" must be defined for ${target_name}.")
+
+ embedded_platform_toolchain(target_name) {
+ forward_variables_from(invoker,
+ [
+ "origin_address",
+ "max_cpus",
+ "max_vms",
+ ])
+ arch = "aarch64"
+ target = "aarch64-none-eabi"
+ tool_prefix = "aarch64-linux-gnu-" # TODO: this isn't right for bare metal but it works.
+ extra_cflags = "-mcpu=${invoker.cpu} -mstrict-align"
+
+ if (invoker.use_pl011) {
+ assert(defined(invoker.pl011_base_address),
+ "\"pl011_base_address\" must be defined for ${target_name}.")
+ extra_defines = "-DPL011_BASE=${invoker.pl011_base_address}"
+ }
+
+ toolchain_args = {
+ arch_aarch64_use_pl011 = invoker.use_pl011
+ }
+ }
+}
diff --git a/build/toolchain/host.gni b/build/toolchain/host.gni
new file mode 100644
index 0000000..e2f8913
--- /dev/null
+++ b/build/toolchain/host.gni
@@ -0,0 +1,176 @@
+# Copyright 2018 Google LLC
+#
+# 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.
+
+# Template for host toolchains.
+template("host_cc_toolchain") {
+ toolchain(target_name) {
+ assert(defined(invoker.ar), "\"ar\" must be defined for ${target_name}.")
+ assert(defined(invoker.cc), "\"cc\" must be defined for ${target_name}.")
+ assert(defined(invoker.cxx), "\"cxx\" must be defined for ${target_name}.")
+
+ # Collect extra flags from the toolchain.
+ extra_defines = ""
+ extra_cflags = ""
+ extra_ldflags = ""
+ if (defined(invoker.extra_defines)) {
+ extra_defines += " ${invoker.extra_defines}"
+ }
+ if (defined(invoker.extra_cflags)) {
+ extra_cflags += " ${invoker.extra_cflags}"
+ }
+ if (defined(invoker.extra_ldflags)) {
+ extra_ldflags += " ${invoker.extra_ldflags}"
+ }
+
+ tool("cc") {
+ depfile = "{{output}}.d"
+ command = "${invoker.cc} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} ${extra_cflags} {{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 = "${invoker.cxx} -MMD -MF $depfile ${extra_defines} {{defines}} {{include_dirs}} ${extra_cflags} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "CXX {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("alink") {
+ rspfile = "{{output}}.rsp"
+ command = "rm -f {{output}} && ${invoker.ar} rcs {{output}} @$rspfile"
+ description = "AR {{target_output_name}}{{output_extension}}"
+ rspfile_content = "{{inputs}}"
+ outputs = [
+ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
+ ]
+ default_output_extension = ".a"
+ output_prefix = "lib"
+ }
+
+ tool("solink") {
+ soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
+ sofile = "{{output_dir}}/$soname"
+ rspfile = soname + ".rsp"
+
+ command = "${invoker.cxx} -shared ${extra_ldflags} {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
+ rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
+
+ description = "SOLINK $soname"
+
+ # Use this for {{output_extension}} expansions unless a target manually
+ # overrides it (in which case {{output_extension}} will be what the target
+ # specifies).
+ default_output_extension = ".so"
+
+ # Use this for {{output_dir}} expansions unless a target manually overrides
+ # it (in which case {{output_dir}} will be what the target specifies).
+ default_output_dir = "{{root_out_dir}}"
+
+ outputs = [
+ sofile,
+ ]
+ link_output = sofile
+ depend_output = sofile
+ output_prefix = "lib"
+ }
+
+ tool("link") {
+ outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
+ rspfile = "$outfile.rsp"
+ command = "${invoker.cxx} ${extra_ldflags} {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}"
+ description = "LINK $outfile"
+ default_output_dir = "{{root_out_dir}}"
+ rspfile_content = "{{inputs}}"
+ outputs = [
+ outfile,
+ ]
+ }
+
+ tool("stamp") {
+ command = "touch {{output}}"
+ description = "STAMP {{output}}"
+ }
+
+ tool("copy") {
+ command = "cp -af {{source}} {{output}}"
+ description = "COPY {{source}} {{output}}"
+ }
+
+ if (defined(invoker.toolchain_args)) {
+ toolchain_args = {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
+ }
+}
+
+template("host_toolchain") {
+ assert(defined(invoker.use_fake_arch),
+ "\"use_fake_arch\" must be defined for ${target_name}.")
+ if (invoker.use_fake_arch) {
+ assert(defined(invoker.max_cpus),
+ "\"max_cpus\" must be defined for ${target_name}.")
+ assert(defined(invoker.max_vms),
+ "\"max_vms\" must be defined for ${target_name}.")
+ }
+
+ # Specialize for clang.
+ host_cc_toolchain("${target_name}_clang") {
+ ar = "llvm-ar"
+ cc = "clang -fcolor-diagnostics"
+ cxx = "clang++"
+
+ # TODO: remove the need for this
+ extra_defines = "-DPL011_BASE=0"
+
+ if (invoker.use_fake_arch) {
+ toolchain_args = {
+ platform_max_cpus = invoker.max_cpus
+ platform_max_vms = invoker.max_vms
+
+ # When building for the ${target_name}, use the fake architecture to make things
+ # testable.
+ arch = "fake"
+ }
+ }
+ }
+
+ # Specialize for gcc.
+ host_cc_toolchain("${target_name}_gcc") {
+ ar = "ar"
+ cc = "gcc -fdiagnostics-color=always"
+ cxx = "g++ -fdiagnostics-color=always"
+
+ # TODO: remove the need for this
+ extra_defines = "-DPL011_BASE=0"
+
+ if (invoker.use_fake_arch) {
+ toolchain_args = {
+ platform_max_cpus = invoker.max_cpus
+ platform_max_vms = invoker.max_vms
+
+ # When building for the ${target_name}, use the fake architecture to make things
+ # testable.
+ arch = "fake"
+ }
+ }
+ }
+}
diff --git a/build/toolchain/host/BUILD.gn b/build/toolchain/host/BUILD.gn
deleted file mode 100644
index dd344b7..0000000
--- a/build/toolchain/host/BUILD.gn
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# 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.
-
-# Host toolchain specific build arguments.
-declare_args() {
- # Build with a specific compiler version e.g. when building with clang, set
- # to "3.9" to build with `clang-3.9`.
- host_cc_version = ""
-}
-
-# Template for host toolchains.
-template("cc_toolchain") {
- toolchain(target_name) {
- assert(defined(invoker.ar), "cc_toolchain() must specify a \"ar\" value")
- assert(defined(invoker.cc), "cc_toolchain() must specify a \"cc\" value")
- assert(defined(invoker.cxx), "cc_toolchain() must specify a \"cxx\" value")
-
- cc = "${invoker.cc}"
- cxx = "${invoker.cxx}"
- if (host_cc_version != "") {
- cc += "-${host_cc_version}"
- cxx += "-${host_cc_version}"
- }
- if (defined(invoker.cflags)) {
- cc += " ${invoker.cflags}"
- cxx += " ${invoker.cflags}"
- }
-
- tool("cc") {
- depfile = "{{output}}.d"
- command = "${cc} -MMD -MF $depfile {{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 {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
- depsformat = "gcc"
- description = "CXX {{output}}"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
- }
-
- tool("alink") {
- rspfile = "{{output}}.rsp"
- command = "rm -f {{output}} && ${invoker.ar} rcs {{output}} @$rspfile"
- description = "AR {{target_output_name}}{{output_extension}}"
- rspfile_content = "{{inputs}}"
- outputs = [
- "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
- ]
- default_output_extension = ".a"
- output_prefix = "lib"
- }
-
- tool("solink") {
- soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
- sofile = "{{output_dir}}/$soname"
- rspfile = soname + ".rsp"
-
- command =
- "${cxx} -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
- rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
-
- description = "SOLINK $soname"
-
- # Use this for {{output_extension}} expansions unless a target manually
- # overrides it (in which case {{output_extension}} will be what the target
- # specifies).
- default_output_extension = ".so"
-
- # Use this for {{output_dir}} expansions unless a target manually overrides
- # it (in which case {{output_dir}} will be what the target specifies).
- default_output_dir = "{{root_out_dir}}"
-
- outputs = [
- sofile,
- ]
- link_output = sofile
- depend_output = sofile
- output_prefix = "lib"
- }
-
- tool("link") {
- outfile = "{{output_dir}}/{{target_output_name}}{{output_extension}}"
- rspfile = "$outfile.rsp"
- command = "${cxx} {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}"
- description = "LINK $outfile"
- default_output_dir = "{{root_out_dir}}"
- rspfile_content = "{{inputs}}"
- outputs = [
- outfile,
- ]
- }
-
- tool("stamp") {
- command = "touch {{output}}"
- description = "STAMP {{output}}"
- }
-
- tool("copy") {
- command = "cp -af {{source}} {{output}}"
- description = "COPY {{source}} {{output}}"
- }
-
- if (defined(invoker.toolchain_args)) {
- toolchain_args = {
- forward_variables_from(invoker.toolchain_args, "*")
- }
- }
- }
-}
-
-# Specialize for clang or gcc
-cc_toolchain("clang") {
- ar = "llvm-ar"
- cc = "clang"
- cxx = "clang++"
- cflags = "-fcolor-diagnostics"
-}
-
-cc_toolchain("clang_fake_arch") {
- ar = "llvm-ar"
- cc = "clang"
- cxx = "clang++"
- cflags = "-fcolor-diagnostics"
-
- toolchain_args = {
- # When building for the host, use the fake architecture to make things
- # testable.
- arch = "fake"
- }
-}
-
-cc_toolchain("gcc") {
- ar = "ar"
- cc = "gcc"
- cxx = "g++"
- cflags = "-fdiagnostics-color=always"
-}
-
-cc_toolchain("gcc_fake_arch") {
- ar = "ar"
- cc = "gcc"
- cxx = "g++"
- cflags = "-fdiagnostics-color=always"
-
- toolchain_args = {
- # When building for the host, use the fake architecture to make things
- # testable.
- arch = "fake"
- }
-}
diff --git a/build/arch/aarch64.gni b/build/toolchain/platform.gni
similarity index 62%
rename from build/arch/aarch64.gni
rename to build/toolchain/platform.gni
index f9df8f2..7a1c8a9 100644
--- a/build/arch/aarch64.gni
+++ b/build/toolchain/platform.gni
@@ -12,14 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Configuration of the build for the platform.
declare_args() {
- # Whether to include the PrimeCell UART (PL011) driver.
- arch_aarch64_use_pl011 = false
+ # The maximum number of CPUs available on the platform.
+ platform_max_cpus = 0
- # The base address of the PrimeCell UART (PL011) device.
- arch_aarch64_pl011_base_address = ""
+ # The maximum number of VMs required for the platform.
+ platform_max_vms = 0
}
-
-assert(
- !arch_aarch64_use_pl011 || arch_aarch64_pl011_base_address != "",
- "Must provide the PL011 base address as \"arch_aarch64_pl011_base_address\".")