| # Copyright 2018 The ChromiumOS Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| declare_args() { | |
| # The OS build is running on. | |
| OS = "" | |
| # Specifies pkg-config program to retrieve information about packages. | |
| pkg_config = "" | |
| # The logical root directory for headers and libraries. | |
| # Trailing slash should not be added (except root path). | |
| sysroot = "" | |
| # The libdir of the target board. e.g. /usr/lib64 | |
| libdir = "" | |
| # The path to the directory where build artifacts are located. | |
| build_root = "" | |
| # The path to src/platform2. | |
| platform2_root = "" | |
| # Libbase revision number read from BASE_VER variable or file. | |
| libbase_ver = "" | |
| # Set true to allow C++ code to use exceptions. | |
| enable_exceptions = false | |
| # Set true if clang is used for C compiler. | |
| clang_cc = false | |
| # Set true if clang is used for C++ compiler. | |
| clang_cxx = false | |
| # Additional flags for C compiler. | |
| external_cflags = [] | |
| # Additional flags for C++ compiler. | |
| external_cxxflags = [] | |
| # Additional flags for C and C++ preprocessor. | |
| external_cppflags = [] | |
| # Additional flags for C and C++ linker. | |
| external_ldflags = [] | |
| # Whether to link against libstdc++fs. Set this to true if the compiler | |
| # version requires -lstdc++fs to use std::filesystem. Useful when compiling | |
| # common-mk projects outside Chrome OS where there are many compiler | |
| # variations. | |
| link_stdcppfs = false | |
| # Set this to true if you want to activate the debug mode. | |
| is_debug = false | |
| # Subdir in platform2 where the package is located. | |
| # TODO(oka): This value is public because it is used in ap/ package for common | |
| # targets to use different default flags based on the package to be built. | |
| # This is hacky, so remove such usages and move this variable back to | |
| # gn_root/BUILD.gn . | |
| platform_subdir = "" | |
| } | |
| import("//common-mk/use.gni") | |
| assert(pkg_config != "", "pkg-config script path must be set") | |
| assert(libbase_ver != -1, "libbase_ver must be set") | |
| assert(libdir != "", "libdir must be set") | |
| if (target_os == "") { | |
| target_os = host_os | |
| } | |
| if (target_cpu == "") { | |
| target_cpu = host_cpu | |
| } | |
| if (current_cpu == "") { | |
| current_cpu = target_cpu | |
| } | |
| if (current_os == "") { | |
| current_os = target_os | |
| } | |
| # Practically sysroot is used as a prefix of paths, e.g. | |
| # "${sysroot}/usr/include". If sysroot is root (= "/"), it will be | |
| # "//usr/include". However, in GN, paths starting with "//" represents the path | |
| # to the GN root, rather than the file system root, which is unexpected. | |
| # To support that case, replace sysroot with "/.", if sysroot is "/". | |
| if (sysroot == "/") { | |
| sysroot = "/." | |
| } | |
| # All binary targets will get this list of configs by default. | |
| _binary_target_configs = [ | |
| "//common-mk:compiler_defaults", | |
| "//common-mk:lto_experiment", | |
| ] | |
| if (!enable_exceptions) { | |
| _binary_target_configs += [ "//common-mk:no_exceptions" ] | |
| } | |
| if (!clang_cc) { | |
| _binary_target_configs += [ "//common-mk:gcc_cflags_c" ] | |
| } | |
| if (!clang_cxx) { | |
| _binary_target_configs += [ "//common-mk:gcc_cflags_cc" ] | |
| } | |
| set_defaults("executable") { | |
| configs = _binary_target_configs | |
| configs += [ "//common-mk:pie" ] | |
| } | |
| set_defaults("static_library") { | |
| configs = _binary_target_configs | |
| configs += [ | |
| "//common-mk:pie", | |
| "//common-mk:use_thin_archive", | |
| ] | |
| } | |
| set_defaults("shared_library") { | |
| configs = _binary_target_configs | |
| configs += [ "//common-mk:pic" ] | |
| } | |
| set_defaults("source_set") { | |
| configs = _binary_target_configs | |
| } | |
| set_default_toolchain("//common-mk/toolchain") | |
| # In Chrome OS, pkg-config is commonly and widely used. | |
| # It is not natively supported by GN. Instead, here a few special fields are | |
| # injected to the executable, shared_library source_set, and static_library | |
| # targets to support pkg-config. | |
| # src_install and src_test settings are also written in the same way. | |
| # | |
| # install_path exports metadata for installing the file built by the target. | |
| # For example, | |
| # - executable("my_executable") # template invocation | |
| # is expanded to: | |
| # - executable("my_executable") # GN built-in function invocation | |
| # - install_config("my_executable-install_config") | |
| # In this case ":my_executable" is usually joined to the dependency chain from | |
| # the root (":all") by the BUILD.gn that uses this template. However, the | |
| # ":my_executable-install_config" is not. So we chain it by adding to deps. | |
| # ":all" --> ":my_executable" -(add this dep)-> ":my_executable-install_config" | |
| # | |
| # Args: | |
| # pkg_deps(optional): A list of package names to be depend. | |
| # A corresponding config is created, and then injected to |configs|. | |
| # public_pkg_deps(optional): Similart to pkg_deps, but injected to | |
| # |public_configs| instead. | |
| # all_dependent_pkg_deps(optional): Similar to pkg_deps, but injected to | |
| # |all_dependent_configs|. | |
| # run_test(optional): A boolean if this is a unittest program that should be | |
| # automatically run. A corresponding metadata is injected to itself. | |
| # test_config(optional): A scope of configs for tests. | |
| # A corresponding metadata is injected to itself. | |
| # install_path(optional): A path to install into. | |
| # A corresponding group is created, and then injected to |deps|. | |
| import("//common-mk/install_config.gni") | |
| import("//common-mk/pkg_config.gni") | |
| template("_generate_config_rule") { | |
| if (defined(invoker.pkg_deps) && invoker.pkg_deps != []) { | |
| _pkg_deps_name = "_${target_name}-pkg_deps-config" | |
| pkg_config(_pkg_deps_name) { | |
| pkg_deps = invoker.pkg_deps | |
| } | |
| } | |
| if (defined(invoker.public_pkg_deps) && invoker.public_pkg_deps != []) { | |
| _public_pkg_deps_name = "_${target_name}-public_pkg_deps-config" | |
| pkg_config(_public_pkg_deps_name) { | |
| pkg_deps = invoker.public_pkg_deps | |
| } | |
| } | |
| if (defined(invoker.all_dependent_pkg_deps) && | |
| invoker.all_dependent_pkg_deps != []) { | |
| _all_dependent_pkg_deps_name = | |
| "_${target_name}-all_dependent_pkg_deps-config" | |
| pkg_config(_all_dependent_pkg_deps_name) { | |
| pkg_deps = invoker.all_dependent_pkg_deps | |
| } | |
| } | |
| if (defined(invoker.install_path)) { | |
| _install_config_name = "_${target_name}-install_config" | |
| source_name = invoker.target_name | |
| if (defined(invoker.output_name)) { | |
| source_name = invoker.output_name | |
| } | |
| source_dir = invoker.root_build_dir | |
| if (defined(invoker.output_dir)) { | |
| source_dir = invoker.output_dir | |
| } | |
| install_config(_install_config_name) { | |
| if (defined(invoker.target_type)) { | |
| type = invoker.target_type | |
| } | |
| if (invoker.target_type == "shared_library") { | |
| sources = [ "${source_dir}/lib/${source_name}.so" ] | |
| } else if (invoker.target_type == "static_library") { | |
| sources = [ "${source_dir}/${source_name}.a" ] | |
| } else { | |
| sources = [ "${source_dir}/${source_name}" ] | |
| } | |
| install_path = invoker.install_path | |
| } | |
| } | |
| target(invoker.target_type, target_name) { | |
| forward_variables_from(invoker, | |
| "*", | |
| [ | |
| "all_dependent_pkg_deps", | |
| "install_path", | |
| "metadata", | |
| "pkg_deps", | |
| "public_pkg_deps", | |
| "run_test", | |
| "target_type", | |
| "test_config", | |
| ]) | |
| if (defined(_pkg_deps_name)) { | |
| if (!defined(configs)) { | |
| configs = [] | |
| } | |
| configs += [ ":${_pkg_deps_name}" ] | |
| } | |
| if (defined(_public_pkg_deps_name)) { | |
| if (!defined(public_configs)) { | |
| public_configs = [] | |
| } | |
| public_configs += [ ":${_public_pkg_deps_name}" ] | |
| } | |
| if (defined(_all_dependent_pkg_deps_name)) { | |
| if (!defined(all_dependent_configs)) { | |
| all_dependent_configs = [] | |
| } | |
| all_dependent_configs += [ ":${_all_dependent_pkg_deps_name}" ] | |
| } | |
| if (defined(_install_config_name)) { | |
| # Add deps to have install_config rule joined to the dependency chain. | |
| # The dependency direction is opposite to the real information flow, but | |
| # it does not matter here because the installation is done in the | |
| # src_install ebuild phase after all build is finished. | |
| if (!defined(deps)) { | |
| deps = [] | |
| } | |
| deps += [ ":${_install_config_name}" ] | |
| } | |
| _run_test = defined(invoker.run_test) && invoker.run_test | |
| if (defined(invoker.metadata) || _run_test) { | |
| metadata = { | |
| if (defined(invoker.metadata)) { | |
| forward_variables_from(invoker.metadata, "*") | |
| } | |
| if (_run_test) { | |
| _run_test = [ true ] | |
| if (defined(invoker.test_config)) { | |
| _test_config = [ invoker.test_config ] | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| # Add variables for exporting install configs of files generated by action targets. | |
| # | |
| # install_configs: | |
| # Optional list of scopes that specify installation configuration. | |
| # Each scope can contain these values: | |
| # path: Install destination. | |
| # files: Optional list of files to be installed. | |
| # This should be a subset of outputs. | |
| # When this is omitted, the enclosing install_configs can have only | |
| # one item, and all the files in the outputs are installed. | |
| # options: Optional string. Specifies the insopts. | |
| template("action") { | |
| if (defined(invoker.install_configs)) { | |
| _installs = [] | |
| _i = 0 | |
| _all_files = false | |
| foreach(c, invoker.install_configs) { | |
| _install_config_name = "_${target_name}-${_i}-install_config" | |
| install_config(_install_config_name) { | |
| if (defined(c.files)) { | |
| sources = c.files | |
| } else { | |
| sources = invoker.outputs | |
| } | |
| install_path = c.path | |
| if (defined(c.options)) { | |
| options = c.options | |
| } | |
| } | |
| _installs += [ ":${_install_config_name}" ] | |
| _i = _i + 1 | |
| if (!defined(c.files)) { | |
| _all_files = true | |
| } | |
| } | |
| # _i here is the length of invoker.intall_configs. | |
| # Note that GN does not provide a function to get a list length. | |
| assert( | |
| _i == 1 || !_all_files, | |
| "|install_configs| should have only one entry when |files| is omitted inside it.") | |
| } | |
| action(target_name) { | |
| forward_variables_from(invoker, "*", [ "install_configs" ]) | |
| if (defined(_installs)) { | |
| # Add deps so that data export is added to the dependency chain. | |
| # See the comments in _generate_config_rule. | |
| if (!defined(deps)) { | |
| deps = [] | |
| } | |
| deps += _installs | |
| } | |
| } | |
| } | |
| template("executable") { | |
| _generate_config_rule(target_name) { | |
| forward_variables_from(invoker, "*") | |
| target_type = "executable" | |
| } | |
| } | |
| template("shared_library") { | |
| _generate_config_rule(target_name) { | |
| forward_variables_from(invoker, "*") | |
| target_type = "shared_library" | |
| } | |
| } | |
| template("source_set") { | |
| _generate_config_rule(target_name) { | |
| forward_variables_from(invoker, "*") | |
| target_type = "source_set" | |
| } | |
| } | |
| template("static_library") { | |
| _generate_config_rule(target_name) { | |
| forward_variables_from(invoker, "*") | |
| target_type = "static_library" | |
| } | |
| } |