Refactor label conversion to handle source dirs that aren't labels as well. Bug: 528225104 Change-Id: I325db854da2020842930a272f566f04e6a6a6964 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/23620 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 392249f..c539995 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -631,6 +631,9 @@ '/wd4838', '/wd4996', '/std:c++23preview', + # Enable __cplusplus macro to report the correct C++ standard version, + # otherwise it defaults to C++98. + '/Zc:__cplusplus', '/GR-', '/D_HAS_EXCEPTIONS=0', ]) @@ -1011,7 +1014,6 @@ '-lshlwapi', ]) - libs.extend(options.link_libs) # we just build static libraries that GN needs
diff --git a/src/gn/ffi/label.cc b/src/gn/ffi/label.cc index c0ddbdb..3818d4c 100644 --- a/src/gn/ffi/label.cc +++ b/src/gn/ffi/label.cc
@@ -7,12 +7,16 @@ extern "C" { -rust::Str GetLabelDir(const Label& label) { - return label.dir().value(); +const SourceDir& GetLabelDir(const Label& label) { + return label.dir(); } rust::Str GetLabelName(const Label& label) { return label.name(); } +rust::Str GetSourceDirValue(const SourceDir& dir) { + return dir.SourceWithNoTrailingSlash(); +} + } // extern "C"
diff --git a/src/gn/starlark/crates/ffi/src/label.rs b/src/gn/starlark/crates/ffi/src/label.rs index b1eedf6..df3c42b 100644 --- a/src/gn/starlark/crates/ffi/src/label.rs +++ b/src/gn/starlark/crates/ffi/src/label.rs
@@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use crate::declare_opaque_type; use types::{LabelRef, PackageRef}; +use crate::declare_opaque_type; declare_opaque_type!(pub Label); impl Label { /// Returns the directory part of the label (the package path). pub fn package(&self) -> &PackageRef { extern "C" { - fn GetLabelDir(label: &Label) -> &str; + fn GetLabelDir(label: &Label) -> &SourceDir; } - // Safety: GetLabelDir is guarunteed to return a string that starts with "//". - unsafe { PackageRef::new_unchecked(GetLabelDir(self)) } + // Safety: Just an FFI function. + unsafe { GetLabelDir(self) }.as_rust() } /// Returns the name part of the label. @@ -22,11 +22,31 @@ extern "C" { fn GetLabelName(label: &Label) -> &str; } + // Safety: Just an FFI function. unsafe { GetLabelName(self) } } /// Returns a `LabelRef` referencing the directory and name of this label. - pub fn as_ref<'a>(&'a self) -> LabelRef<'a> { + pub fn as_ref(&self) -> LabelRef<'_> { LabelRef::new(self.package(), self.name()) } } + +declare_opaque_type!(pub SourceDir); + +impl SourceDir { + pub fn as_rust(&self) -> &types::PackageRef { + extern "C" { + fn GetSourceDirValue(dir: &SourceDir) -> &str; + } + // Safety: Just an FFI function. + let s = unsafe { GetSourceDirValue(self) }; + // While source dirs aren't guarunteed to start with "//" (they may be + // absolute), we only convert source dirs to rust for either labels or + // BUILD.gn directories, both of which are guarunteed to be + // source-relative. + debug_assert!(s.starts_with("//")); + // Safety: Guarunteed to be a valid package. + unsafe { types::PackageRef::new_unchecked(s) } + } +}
diff --git a/src/gn/starlark/crates/ffi/src/lib.rs b/src/gn/starlark/crates/ffi/src/lib.rs index 15f108e..f4abc9c 100644 --- a/src/gn/starlark/crates/ffi/src/lib.rs +++ b/src/gn/starlark/crates/ffi/src/lib.rs
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -//! Low-level FFI bindings and opaque types for interoperating between the C++ GN -//! codebase and the Rust Starlark interpreter crates. +//! Low-level FFI bindings and opaque types for interoperating between the C++ +//! GN codebase and the Rust Starlark interpreter crates. //! //! **Type Equivalence** //! @@ -11,14 +11,18 @@ //! rust type signatures. This means that if you change the signature of a //! function on one side, you *might* get a link error, or might just get UB. //! -//! As long as C++ and rust see a type identically, we don't care how it works under the hood. +//! As long as C++ and rust see a type identically, we don't care how it works +//! under the hood. //! * Most custom types will need to be passed by reference //! * C++ &T is just a non-null pointer. //! * Rust references are just non-null pointers //! * Rust Option<&T> are pointers -//! * If you define a struct in C++ and a #[repr(C)] one in rust, you can pass by value instead of by reference. -//! * cxx.h does this for some rust types in C++ (rust::*, eg. rust::Str = &str) -//! * cxx.h does this for some C++ types in rust (cxx::*, eg. cxx::CxxVector<T> = std::vector<T>) +//! * If you define a struct in C++ and a #[repr(C)] one in rust, you can pass +//! by value instead of by reference. +//! * cxx.h does this for some rust types in C++ (rust::*, eg. rust::Str = +//! &str) +//! * cxx.h does this for some C++ types in rust (cxx::*, eg. +//! cxx::CxxVector<T> = std::vector<T>) //! //! **Exposing rust functions to C++** //! @@ -62,4 +66,4 @@ pub mod label; pub mod opaque; -pub use label::Label; +pub use label::{Label, SourceDir};