Create an `intern_string` function accessible to rust This function will be used to intern paths to allow fast comparison and fast hashing by pointer equality, improving the performance of depset operations. See the child CL's file.rs for usage. In order to resolve a compile error on mac, we also patch in my changes to cxx.h from: https://github.com/dtolnay/cxx/pull/1723 https://github.com/dtolnay/cxx/pull/1724 Hopefully they will be available upstream by the time we actually vendor. Otherwise we'll just use a patched version of the crate like we have for starlark-rs. Bug: 528225104 Change-Id: I4f631049633dc5bd4c35a4f0125847566a6a6964 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/23260 Reviewed-by: Takuto Ikuta <tikuta@google.com> Commit-Queue: Matt Stark <msta@google.com>
diff --git a/build/gen.py b/build/gen.py index c95b57e..675402b 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -347,7 +347,9 @@ return escape_path_ninja('%s' % os.path.splitext(path)[0] + object_ext) def library_to_a(library): - return '%s%s' % (library, library_ext) + if platform.is_msvc(): + return '%s%s' % (library, library_ext) + return 'lib%s%s' % (library, library_ext) ninja_lines = [] def build_source(src_file, settings): @@ -445,6 +447,7 @@ libflags = os.environ.get('LIBFLAGS', '').split() include_dirs = [ os.path.relpath(os.path.join(REPO_ROOT, 'src'), os.path.dirname(path)), + os.path.relpath(os.path.join(REPO_ROOT, 'src/gn/starlark/vendor/cxx/include'), os.path.dirname(path)), '.', ] if platform.is_zos(): @@ -535,6 +538,9 @@ # flags not supported by gcc/g++. else: cflags.extend(['-Wrange-loop-analysis', '-Wextra-semi-stmt']) + # We use "extern C" to communicate with rust, not C. So it doesn't matter + # if the return type is an invalid C type. + cflags.append('-Wno-return-type-c-linkage') if platform.is_linux() or platform.is_mingw() or platform.is_msys(): ldflags.append('-Wl,--as-needed') @@ -618,6 +624,7 @@ '/wd4099', '/wd4100', '/wd4127', + '/wd4190', '/wd4244', '/wd4267', '/wd4505', @@ -665,6 +672,10 @@ 'src/base/value_iterators.cc', 'src/base/values.cc', ]}, + 'string_atom': {'sources': [ + 'src/gn/string_atom.cc', + 'src/gn/ffi/intern_string.cc', + ]}, 'gn_lib': {'sources': [ 'src/gn/action_target_generator.cc', 'src/gn/action_values.cc', @@ -797,7 +808,6 @@ 'src/gn/source_dir.cc', 'src/gn/source_file.cc', 'src/gn/standard_out.cc', - 'src/gn/string_atom.cc', 'src/gn/string_output_buffer.cc', 'src/gn/string_utils.cc', 'src/gn/substitution_list.cc',
diff --git a/src/gn/ffi/intern_string.cc b/src/gn/ffi/intern_string.cc new file mode 100644 index 0000000..bd31cd4 --- /dev/null +++ b/src/gn/ffi/intern_string.cc
@@ -0,0 +1,19 @@ +// Copyright 2026 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string_view> + +#include "cxx.h" +#include "gn/string_atom.h" + +// `intern_string` is located in its own translation unit (`intern_string.cc`) +// to prevent link-time dependencies on the `ctx` crate for standalone cargo +// unit tests. +// +// By isolating `intern_string` in its own object file (`intern_string.o`), the +// linker only pulls in this file and does not pull in `cxx_api.o`. +extern "C" rust::Str intern_string(rust::Str s) { + StringAtom atom(std::string_view{s}); + return rust::Str(atom.str()); +}
diff --git a/src/gn/starlark/vendor/cxx/include/cxx.h b/src/gn/starlark/vendor/cxx/include/cxx.h index 4e261a3..1c97580 100644 --- a/src/gn/starlark/vendor/cxx/include/cxx.h +++ b/src/gn/starlark/vendor/cxx/include/cxx.h
@@ -124,6 +124,9 @@ Str(const std::string &); Str(const char *); Str(const char *, std::size_t); +#if __cplusplus >= 201703L + Str(std::string_view s) : Str(s.data(), s.size()) {} +#endif Str &operator=(const Str &) & noexcept = default; @@ -243,6 +246,7 @@ using iterator_category = std::random_access_iterator_tag; #endif using value_type = T; + using element_type = T; using difference_type = std::ptrdiff_t; using pointer = typename std::add_pointer<T>::type; using reference = typename std::add_lvalue_reference<T>::type;