diff --git a/.gnfiles/build/feature/ten_package.gni b/.gnfiles/build/feature/ten_package.gni index 8875d40..00a8786 100644 --- a/.gnfiles/build/feature/ten_package.gni +++ b/.gnfiles/build/feature/ten_package.gni @@ -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 = @@ -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, [ @@ -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. @@ -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", [ @@ -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 . + # 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 . 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", [ @@ -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 @@ -266,8 +293,7 @@ template("ten_package") { ]) } - resource_targets += [ ":${resource_action_target}" ] - package_deps += [ ":${resource_action_target}" ] + package_deps += [ ":${unique_resource_action_target_name}" ] } } diff --git a/.gnfiles/build/feature/ten_package_test.gni b/.gnfiles/build/feature/ten_package_test.gni index 72a7b92..bbd47c2 100644 --- a/.gnfiles/build/feature/ten_package_test.gni +++ b/.gnfiles/build/feature/ten_package_test.gni @@ -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, [ @@ -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, diff --git a/.gnfiles/build/scripts/copy_fs_entry.py b/.gnfiles/build/scripts/copy_fs_entry.py index e1293a7..550faf9 100644 --- a/.gnfiles/build/scripts/copy_fs_entry.py +++ b/.gnfiles/build/scripts/copy_fs_entry.py @@ -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. """ @@ -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") @@ -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) diff --git a/.gnfiles/build/scripts/timestamp_proxy.py b/.gnfiles/build/scripts/timestamp_proxy.py index ab324bf..1597281 100644 --- a/.gnfiles/build/scripts/timestamp_proxy.py +++ b/.gnfiles/build/scripts/timestamp_proxy.py @@ -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" @@ -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: @@ -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)}")