pw_libc: Support llvm-libc
This commit adds build support (initially only gn) for
integrating llvm-libc into pigweeds build.
It adds support for testing llvm-libc functions both
on host and on target. At present, only the function
"abs" has been included, though there are many more
functions ready to be brought in.
Currently there are no dependencies on pw_libc, which
is a static archive which should be put on the linker
search path before libc.a to choose the llvm-libc
implementations first. libc.a will be empty if
dir_pw_third_party_llvm_libc is not defined.
Change-Id: I3e7ccc3d2f0d55e948874371f35062c5e6167fac
Original-Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/129470
Original-Reviewed-by: Prabhu Karthikeyan Rajasekaran <prabhukr@google.com>
Original-Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/llvm-integration/+/235116
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Commit-Queue: Prabhu Karthikeyan Rajasekaran <prabhukr@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_libc/BUILD.gn b/pw_libc/BUILD.gn
index 6b5c01f..df7acd7 100644
--- a/pw_libc/BUILD.gn
+++ b/pw_libc/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2019 The Pigweed Authors
+# Copyright 2023 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
@@ -16,6 +16,7 @@
import("$dir_pw_build/target_types.gni")
import("$dir_pw_docgen/docs.gni")
+import("$dir_pw_third_party/llvm_libc/llvm_libc.gni")
import("$dir_pw_unit_test/test.gni")
config("default_config") {
@@ -23,7 +24,10 @@
}
pw_test_group("tests") {
- tests = [ ":memset_test" ]
+ tests = [
+ ":llvm_libc_tests",
+ ":memset_test",
+ ]
}
pw_test("memset_test") {
@@ -31,6 +35,29 @@
deps = [ "$dir_pw_containers" ]
}
+# If dir_pw_third_party_llvm_libc is defined, use that directory to create a
+# pw_libc.a from llvm-libc. Otherwise, we create an empty pw_libc.a.
+if (dir_pw_third_party_llvm_libc != "") {
+ pw_libc_source_set("stdlib") {
+ functions = [ "abs" ]
+ }
+
+ pw_static_library("pw_libc") {
+ complete_static_lib = true
+ deps = [ ":stdlib" ]
+ }
+
+ pw_test_group("llvm_libc_tests") {
+ tests = [ ":stdlib_tests" ]
+ }
+} else {
+ pw_static_library("pw_libc") {
+ }
+
+ pw_test_group("llvm_libc_tests") {
+ }
+}
+
pw_doc_group("docs") {
sources = [ "docs.rst" ]
}
diff --git a/third_party/llvm_libc/BUILD.gn b/third_party/llvm_libc/BUILD.gn
new file mode 100644
index 0000000..3f49b2a
--- /dev/null
+++ b/third_party/llvm_libc/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2023 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("$dir_pw_docgen/docs.gni")
+
+pw_doc_group("docs") {
+ sources = [ "docs.rst" ]
+}
diff --git a/third_party/llvm_libc/docs.rst b/third_party/llvm_libc/docs.rst
new file mode 100644
index 0000000..4939600
--- /dev/null
+++ b/third_party/llvm_libc/docs.rst
@@ -0,0 +1,44 @@
+.. _module-pw_third_party_llvm_libc:
+
+=========
+LLVM libc
+=========
+The ``$dir_pw_third_party/llvm_libc/`` module provides various helpers to
+optionally use LLVM libc with :ref:`module-pw_libc`.
+
+------------------------
+Using upstream LLVM libc
+------------------------
+If you want to use LLVM libc, you must do the following:
+
+Submodule
+=========
+Add LLVM libc to your workspace with the following command.
+
+.. code-block:: sh
+
+ git submodule add https://llvm.googlesource.com/llvm-project/libc \
+ third_party/llvm_libc/src
+
+Note, this git repository is maintained by Google and is a slice of upstream
+LLVM including only the libc subdirectory.
+
+GN
+==
+* Set the GN var ``dir_pw_third_party_llvm_libc`` to the location of the LLVM
+ libc source. If you used the command above, this will be
+ ``//third_party/llvm_libc/src``
+
+ This can be set in your args.gn or .gn file like:
+ ``dir_pw_third_party_llvm_libc = "//third_party/llvm_libc_src"``
+
+------
+Status
+------
+Currently, pw_libc's llvm-libc integration only provides a pw_libc.a and is
+not suitable as a full replacement for libc. Not all functions used by
+projects are currently available to use from llvm-libc. Moreover, headers are
+provided from the sysroot libc. Startup files are also provided from the
+sysroot.
+
+In the future, we hope to be able to fully replace the sysroot libc.
diff --git a/third_party/llvm_libc/llvm_libc.gni b/third_party/llvm_libc/llvm_libc.gni
new file mode 100644
index 0000000..be5f997
--- /dev/null
+++ b/third_party/llvm_libc/llvm_libc.gni
@@ -0,0 +1,65 @@
+# Copyright 2023 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("//build_overrides/pigweed.gni")
+
+import("$dir_pw_build/target_types.gni")
+import("$dir_pw_unit_test/test.gni")
+
+declare_args() {
+ # This variable is set to the path of llvm-libc. If set, pw_libc.a will
+ # be created using llvm-libc sources.
+ dir_pw_third_party_llvm_libc = ""
+}
+
+template("pw_libc_source_set") {
+ source_set_target_name = target_name
+
+ target_dir = "$dir_pw_third_party_llvm_libc/src/$source_set_target_name"
+
+ pw_source_set(target_name) {
+ dir = target_dir
+
+ include_dirs = [ dir_pw_third_party_llvm_libc ]
+
+ defines = [
+ "LIBC_COPT_PUBLIC_PACKAGING=1",
+ "LLVM_LIBC_FUNCTION_ATTR=[[gnu::visibility(\"default\")]]",
+ "LIBC_INLINE=inline",
+ ]
+
+ public = []
+ sources = []
+
+ foreach(function, invoker.functions) {
+ public += [ "$dir/$function.h" ]
+ sources += [ "$dir/$function.cpp" ]
+ }
+ }
+
+ pw_test("${source_set_target_name}_tests") {
+ dir = "$dir_pw_third_party_llvm_libc/test/src/$source_set_target_name"
+
+ include_dirs = [ dir_pw_third_party_llvm_libc ]
+ defines = [ "LIBC_COPT_TEST_USE_PIGWEED" ]
+
+ sources = []
+
+ foreach(function, invoker.functions) {
+ sources += [ "$dir/${function}_test.cpp" ]
+ }
+
+ deps = [ ":$source_set_target_name" ]
+ }
+}