Skip to content

Commit

Permalink
feat: refine C++ extension standalone test building
Browse files Browse the repository at this point in the history
  • Loading branch information
halajohn committed Jan 12, 2025
1 parent 40a58f3 commit e5019ae
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 47 deletions.
100 changes: 63 additions & 37 deletions .gnfiles/build/feature/ten_package.gni
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ template("ten_package") {
#
# The main purpose of this is to quickly find the desired package in the out
# folder without making the out folder too cluttered. And different types of
# packages can have the same name, so splitting subfolders based on type to
# packages can have the same name, so splitting sub-folders based on type to
# create a namespace-like effect is also relatively appropriate.
if (invoker.package_kind == "app") {
package_output_root_dir =
Expand Down Expand Up @@ -54,19 +54,34 @@ template("ten_package") {
build_type = "shared_library"
}

output_name = _target_name
build_output_name = _target_name
if (defined(invoker.output_name) && invoker.output_name != "") {
output_name = invoker.output_name
build_output_name = invoker.output_name
}

build_target_name = "${_target_name}_${build_type}"
if (build_type == "shared_library") {
output_dir_related_to_package_output_root_dir = "lib"

target(build_type, build_target_name) {
if (build_type == "shared_library") {
output_dir = "${package_output_root_dir}/lib"
} else {
output_dir = "${package_output_root_dir}/bin"
if (is_linux || is_mac) {
real_build_output_file_name = "lib${build_output_name}.so"
} else if (is_win) {
real_build_output_file_name = "${build_output_name}.dll"
}
} else {
output_dir_related_to_package_output_root_dir = "bin"

if (is_linux || is_mac) {
real_build_output_file_name = "${build_output_name}"
} else if (is_win) {
real_build_output_file_name = "${build_output_name}.exe"
}
}
build_output_dir = "${package_output_root_dir}/${output_dir_related_to_package_output_root_dir}"

unique_build_target_name = "${_target_name}_${build_type}"
target(build_type, unique_build_target_name) {
output_name = "${build_output_name}"
output_dir = "${build_output_dir}"

forward_variables_from(invoker,
[
Expand Down Expand Up @@ -123,6 +138,7 @@ template("ten_package") {
ldflags += invoker.ldflags
}

# Setup the shared library search path.
if (is_linux) {
ldflags += [
# Enable the binary to look in the same folder for shared libraries.
Expand Down Expand Up @@ -168,8 +184,10 @@ template("ten_package") {
}
} else {
pkg_base_dir = get_path_info(_target_name, "dir")

app_base_dir = "${pkg_base_dir}/../../../"

# =-=-= extension 的话应该要切到 .ten/app/ 下面做编译, 需要补一个 BUILD.gn, 直接用 default_app_cpp?
used_system_pkgs =
exec_script("//.gnfiles/build/scripts/get_used_ten_pkgs.py",
[
Expand All @@ -186,39 +204,47 @@ template("ten_package") {
}

app_base_dir = "${pkg_base_dir}/.ten/app/"

used_system_pkgs = []
used_system_pkgs =
exec_script("//.gnfiles/build/scripts/get_used_ten_pkgs.py",
[
"--pkg-base-dir",
rebase_path("${pkg_base_dir}"),
"--app-base-dir",
rebase_path("${app_base_dir}"),
"--pkg-type",
"system",
],
"list lines")
foreach(used_pkg, used_system_pkgs) {
configs += [
"${app_base_dir}${used_pkg}:config_for_standalone_ten_packages",
]
}
}
}

package_deps += [ ":${build_target_name}" ]
# Copy the build results to the final destination.
unique_copy_build_result_target_name = "${_target_name}_copy_build_result"
unique_copy_build_result_timestamp_proxy_file =
"${target_gen_dir}/${unique_copy_build_result_target_name}"
action("${unique_copy_build_result_target_name}") {
script = "//.gnfiles/build/scripts/copy_fs_entry.py"

inputs = [ "${build_output_dir}/${real_build_output_file_name}" ]
outputs = [ "${unique_copy_build_result_timestamp_proxy_file}" ]

target_dir = get_label_info(":${unique_build_target_name}", "dir")

args = [
"--source",
rebase_path("${build_output_dir}/${real_build_output_file_name}"),
"--destination",
rebase_path(
"${target_dir}/${output_dir_related_to_package_output_root_dir}/${real_build_output_file_name}"),
"--tg-timestamp-proxy-file",
rebase_path(unique_copy_build_result_timestamp_proxy_file),
]

deps = [ ":${unique_build_target_name}" ]
}

package_deps += [ ":${unique_copy_build_result_target_name}" ]
}

# Handle resources
#
# The destination folder of 'resources' is <package_output_root_dir>.
# The basic function of resources is simply to copy — copying from specified
# sources to specified destinations. All the destination folders of
# 'resources' are based on <package_output_root_dir>.
if (defined(invoker.resources) && invoker.resources != []) {
resource_targets = []

foreach(resource, invoker.resources) {
resource_info = {
}

resource_info =
exec_script("//.gnfiles/build/scripts/get_src_and_dest_file.py",
[
Expand All @@ -235,12 +261,13 @@ template("ten_package") {
resource_src_paths = resource_info.sources
resource_dest_path = resource_info.destination

resource_dest_filename = string_replace(resource_dest_path, "/", "_")
resource_dest_str = string_replace(resource_dest_path, "/", "_")

resource_action_target =
"${_target_name}_resource_${resource_dest_filename}"
unique_resource_action_target_name =
"${_target_name}_copy_resource_to_${resource_dest_str}"

action("${resource_action_target}") {
# The only task handled by resources is copying.
action("${unique_resource_action_target_name}") {
script = "//.gnfiles/build/scripts/copy_fs_entry.py"

inputs = resource_src_paths
Expand All @@ -266,8 +293,7 @@ template("ten_package") {
])
}

resource_targets += [ ":${resource_action_target}" ]
package_deps += [ ":${resource_action_target}" ]
package_deps += [ ":${unique_resource_action_target_name}" ]
}
}

Expand Down
48 changes: 42 additions & 6 deletions .gnfiles/build/feature/ten_package_test.gni
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,26 @@ template("ten_package_test") {
_target_name = target_name
package_deps = []

output_name = _target_name
build_output_name = _target_name
if (defined(invoker.output_name) && invoker.output_name != "") {
output_name = invoker.output_name
build_output_name = invoker.output_name
}

build_target_name = "${_target_name}_executable"
if (is_linux || is_mac) {
real_build_output_file_name = "${build_output_name}"
} else if (is_win) {
real_build_output_file_name = "${build_output_name}.exe"
}

output_dir_related_to_package_output_root_dir = "bin"
build_output_dir =
"${root_out_dir}/${output_dir_related_to_package_output_root_dir}"

unique_build_target_name = "${_target_name}_executable"

executable(build_target_name) {
output_dir = "${root_out_dir}/tests"
executable(unique_build_target_name) {
output_dir = "${build_output_dir}"
output_name = "${build_output_name}"

forward_variables_from(invoker,
[
Expand Down Expand Up @@ -98,7 +109,32 @@ template("ten_package_test") {
}
}

package_deps += [ ":${build_target_name}" ]
# Copy the build results to the final destination.
unique_copy_build_result_target_name = "${_target_name}_copy_build_result"
unique_copy_build_result_timestamp_proxy_file =
"${target_gen_dir}/${unique_copy_build_result_target_name}"
action("${unique_copy_build_result_target_name}") {
script = "//.gnfiles/build/scripts/copy_fs_entry.py"

inputs = [ "${build_output_dir}/${real_build_output_file_name}" ]
outputs = [ "${unique_copy_build_result_timestamp_proxy_file}" ]

target_dir = get_label_info(":${unique_build_target_name}", "dir")

args = [
"--source",
rebase_path("${build_output_dir}/${real_build_output_file_name}"),
"--destination",
rebase_path(
"${target_dir}/${output_dir_related_to_package_output_root_dir}/${real_build_output_file_name}"),
"--tg-timestamp-proxy-file",
rebase_path(unique_copy_build_result_timestamp_proxy_file),
]

deps = [ ":${unique_build_target_name}" ]
}

package_deps += [ ":${unique_copy_build_result_target_name}" ]

group(_target_name) {
forward_variables_from(invoker,
Expand Down
7 changes: 4 additions & 3 deletions .gnfiles/build/scripts/copy_fs_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from typing import Optional
from build.scripts import fs_utils, timestamp_proxy

""" Copy from the paths of the 1st to N-1 arguments to the path of the Nth
argument.
"""
Copy from the paths of the 1st to N-1 arguments to the path of the Nth argument.
"""


Expand Down Expand Up @@ -44,7 +44,7 @@ def main():
dst = args.destination

try:
# Check all the sources are existed.
# Check if all the sources are existed.
for src in src_paths:
if not os.path.exists(src):
raise Exception(f"{src} does not exist")
Expand All @@ -58,6 +58,7 @@ def main():

for src in src_paths:
if src.endswith(timestamp_proxy.TG_TIMESTAMP_PROXY_EXTENSION):
# This special timestamp file does not need to be copied.
continue
try:
fs_utils.copy(src, dst)
Expand Down
24 changes: 23 additions & 1 deletion .gnfiles/build/scripts/timestamp_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from typing import Optional
from build.scripts import touch

# A unique file extension is used to significantly reduce the likelihood of name
# conflicts between timestamp files and non-timestamp files.
TG_TIMESTAMP_PROXY_EXTENSION = ".tg_timestamp_proxy"


Expand All @@ -19,6 +21,15 @@ def _gen_timestamp_proxy_path(path: Optional[str]) -> Optional[str]:


def touch_timestamp_proxy_file(path: Optional[str]) -> None:
"""
A timestamp file is typically one of a target's outputs, and the act of
creating or updating the timestamp file ensures that GN, during the next
build, recognizes that the timestamp file is up-to-date and therefore
determines that the target does not need to be re-executed.
Args:
path (Optional[str]): The timestamp file path.
"""
path = _gen_timestamp_proxy_path(path)

if path:
Expand All @@ -29,7 +40,18 @@ def touch_timestamp_proxy_file(path: Optional[str]) -> None:


def remove_timestamp_proxy_file(path: Optional[str]) -> None:
"""
A timestamp file is typically one of a target's outputs, and deleting the
timestamp file effectively causes GN to determine during the next build that
the target associated with that timestamp file needs to be executed again.
Args:
path (Optional[str]): The timestamp file path.
"""
path = _gen_timestamp_proxy_path(path)

if path and os.path.exists(path):
os.remove(path)
try:
os.remove(path)
except Exception as e:
raise Exception(f"Failed to remove timestamp proxy file: {str(e)}")

0 comments on commit e5019ae

Please sign in to comment.