pw_tokenizer: Add the linker sections automatically

- Add the pw_tokenizer linker script using linker flags.
- Apply --gc-sections to host builds, since the pw_tokenizer sections
  are now preserved without it.

Change-Id: I8cbd087d808cb75492c6113411618f2c079189c1
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/23303
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn
index 4efa585..67f3614 100644
--- a/pw_tokenizer/BUILD.gn
+++ b/pw_tokenizer/BUILD.gn
@@ -35,6 +35,32 @@
   visibility = [ ":*" ]
 }
 
+config("linker_script") {
+  inputs = [ "pw_tokenizer_linker_sections.ld" ]
+
+  # Automatically add the tokenizer linker sections when cross-compiling or
+  # building for Linux. macOS and Windows executables are not supported.
+  if (current_os == "") {
+    ldflags = [
+      "-T",
+      rebase_path("pw_tokenizer_linker_sections.ld"),
+    ]
+  } else if (current_os == "linux") {
+    # When building for Linux, the linker provides a default linker script.
+    # The add_tokenizer_sections_to_default_script.ld wrapper includes the
+    # pw_tokenizer_linker_sections.ld script in a way that appends to the the
+    # default linker script instead of overriding it.
+    ldflags = [
+      "-T",
+      rebase_path("add_tokenizer_sections_to_default_script.ld"),
+      "-L",
+      rebase_path("."),
+    ]
+    inputs += [ "add_tokenizer_sections_to_default_script.ld" ]
+  }
+  visibility = [ ":*" ]
+}
+
 pw_source_set("config") {
   public = [ "public/pw_tokenizer/config.h" ]
   public_configs = [ ":public_include_path" ]
@@ -43,6 +69,7 @@
 
 pw_source_set("pw_tokenizer") {
   public_configs = [ ":public_include_path" ]
+  all_dependent_configs = [ ":linker_script" ]
   public_deps = [
     ":config",
     dir_pw_preprocessor,
diff --git a/pw_tokenizer/add_tokenizer_sections_to_default_script.ld b/pw_tokenizer/add_tokenizer_sections_to_default_script.ld
new file mode 100644
index 0000000..41cc0c1
--- /dev/null
+++ b/pw_tokenizer/add_tokenizer_sections_to_default_script.ld
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020 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_tokenizer_linker_sections.ld
+
+/*
+ * The INSERT directive instructs the linker to append the directives in this
+ * script to the default linker script, rather than replace the default with
+ * this script. It doesn't matter where the tokenizer sections are inserted, so
+ * insert them after the standard .strtab section.
+ */
+INSERT AFTER .strtab
diff --git a/pw_tokenizer/docs.rst b/pw_tokenizer/docs.rst
index 3036272..121f025 100644
--- a/pw_tokenizer/docs.rst
+++ b/pw_tokenizer/docs.rst
@@ -117,14 +117,15 @@
      the BUILD.gn's ``pw_tokenizer`` target to the build.
   2. Use the tokenization macros in your code. See `Tokenization`_.
   3. Add the contents of ``pw_tokenizer_linker_sections.ld`` to your project's
-     linker script.
+     linker script. In GN and CMake, this step is done automatically.
   4. Compile your code to produce an ELF file.
   5. Run ``database.py create`` on the ELF file to generate a CSV token
      database. See `Managing token databases`_.
   6. Commit the token database to your repository. See notes in `Database
      management`_.
   7. Integrate a ``database.py add`` command to your build to automatically
-     update the committed token database. See `Update a database`_.
+     update the committed token database. In GN, use the
+     ``pw_tokenizer_database`` template to do this. See `Update a database`_.
   8. Integrate ``detokenize.py`` or the C++ detokenization library with your
      tools to decode tokenized logs. See `Detokenization`_.
 
diff --git a/pw_toolchain/generate_toolchain.gni b/pw_toolchain/generate_toolchain.gni
index 7f31541..7b19f2b 100644
--- a/pw_toolchain/generate_toolchain.gni
+++ b/pw_toolchain/generate_toolchain.gni
@@ -229,17 +229,10 @@
         _link_flags += [
           # Output a map file that shows symbols and their location.
           "-Wl,-Map,$_link_mapfile",
-        ]
 
-        # TODO(hepler): Re-add gc-sections to host when supported by tokenizer.
-        is_host_toolchain =
-            defined(invoker.is_host_toolchain) && invoker.is_host_toolchain
-        if (!is_host_toolchain) {
-          _link_flags += [
-            # Delete unreferenced sections. Helpful with -ffunction-sections.
-            "-Wl,--gc-sections",
-          ]
-        }
+          # Delete unreferenced sections. Helpful with -ffunction-sections.
+          "-Wl,--gc-sections",
+        ]
       }
 
       _link_group = defined(invoker.link_group) && invoker.link_group