diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java index 6bcc7c128b9910..375104ed4699ff 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java @@ -15,6 +15,8 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedSet; import com.google.devtools.build.lib.actions.FileValue; @@ -44,6 +46,8 @@ import com.google.devtools.build.lib.vfs.Root; import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CompilationMode; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CompilationModeFlags; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.ToolPath; import com.google.devtools.build.skyframe.SkyFunction.Environment; @@ -64,14 +68,152 @@ public class AndroidNdkRepositoryFunction extends AndroidRepositoryFunction { private static final ImmutableList PATH_ENV_VAR_AS_LIST = ImmutableList.of(PATH_ENV_VAR); - private static final class CrosstoolStlPair { + private static String getDefaultCrosstool(Integer majorRevision) { + // From NDK 17, libc++ replaces gnu-libstdc++ as the default STL. + return majorRevision <= 16 ? GnuLibStdCppStlImpl.NAME : LibCppStlImpl.NAME; + } - private final CrosstoolRelease crosstoolRelease; - private final StlImpl stlImpl; + private static PathFragment getAndroidNdkHomeEnvironmentVar( + Path workspace, Map env) { + return workspace.getRelative(PathFragment.create(env.get(PATH_ENV_VAR))).asFragment(); + } - private CrosstoolStlPair(CrosstoolRelease crosstoolRelease, StlImpl stlImpl) { - this.crosstoolRelease = crosstoolRelease; - this.stlImpl = stlImpl; + private static String createBuildFile( + String ruleName, String defaultCrosstool, List crosstools) { + + String buildFileTemplate = getTemplate("android_ndk_build_file_template.txt"); + String ccToolchainSuiteTemplate = getTemplate("android_ndk_cc_toolchain_suite_template.txt"); + String ccToolchainTemplate = getTemplate("android_ndk_cc_toolchain_template.txt"); + String stlFilegroupTemplate = getTemplate("android_ndk_stl_filegroup_template.txt"); + String miscLibrariesTemplate = getTemplate("android_ndk_misc_libraries_template.txt"); + + StringBuilder ccToolchainSuites = new StringBuilder(); + StringBuilder ccToolchainRules = new StringBuilder(); + StringBuilder stlFilegroups = new StringBuilder(); + for (CrosstoolStlPair crosstoolStlPair : crosstools) { + + // Create the cc_toolchain_suite rule + CrosstoolRelease crosstool = crosstoolStlPair.crosstoolRelease; + + StringBuilder toolchainMap = new StringBuilder(); + for (CToolchain toolchain : crosstool.getToolchainList()) { + toolchainMap.append( + String.format( + " '%s': ':%s',\n '%s|%s': ':%s',\n", + toolchain.getTargetCpu(), + toolchain.getToolchainIdentifier(), + toolchain.getTargetCpu(), + toolchain.getCompiler(), + toolchain.getToolchainIdentifier())); + } + + String toolchainName = createToolchainName(crosstoolStlPair.stlImpl.getName()); + + ccToolchainSuites.append( + ccToolchainSuiteTemplate + .replace("%toolchainName%", toolchainName) + .replace("%toolchainMap%", toolchainMap.toString().trim()) + .replace("%crosstoolReleaseProto%", crosstool.toString())); + + // Create the cc_toolchain rules + for (CToolchain toolchain : crosstool.getToolchainList()) { + ccToolchainRules.append( + createCcToolchainRule( + ccToolchainTemplate, crosstoolStlPair.stlImpl.getName(), toolchain)); + } + + // Create the STL file group rules + for (Map.Entry entry : + crosstoolStlPair.stlImpl.getFilegroupNamesAndFilegroupFileGlobPatterns().entrySet()) { + + stlFilegroups.append( + stlFilegroupTemplate + .replace("%name%", entry.getKey()) + .replace("%fileGlobPattern%", entry.getValue())); + } + } + + return buildFileTemplate + .replace("%ruleName%", ruleName) + .replace("%defaultCrosstool%", "//:toolchain-" + defaultCrosstool) + .replace("%ccToolchainSuites%", ccToolchainSuites) + .replace("%ccToolchainRules%", ccToolchainRules) + .replace("%stlFilegroups%", stlFilegroups) + .replace("%miscLibraries%", miscLibrariesTemplate); + } + + static String createToolchainName(String stlName) { + return TOOLCHAIN_NAME_PREFIX + stlName; + } + + private static String createCcToolchainRule( + String ccToolchainTemplate, String version, CToolchain toolchain) { + + // TODO(bazel-team): It's unfortunate to have to extract data from a CToolchain proto like this. + // It would be better to have a higher-level construction (like an AndroidToolchain class) + // from which the CToolchain proto and rule information needed here can be created. + // Alternatively it would be nicer to just be able to glob the entire NDK and add that one glob + // to each cc_toolchain rule, and then the complexities in the method and the templates can + // go away, but globbing the entire NDK takes ~60 seconds, mostly because of MD5ing all the + // binary files in the NDK (eg the .so / .a / .o files). + + // This also includes the files captured with cxx_builtin_include_directory. + // Use gcc specifically because clang toolchains will have both gcc and llvm toolchain paths, + // but the gcc tool will actually be clang. + ToolPath gcc = null; + for (ToolPath toolPath : toolchain.getToolPathList()) { + if ("gcc".equals(toolPath.getName())) { + gcc = toolPath; + } + } + checkNotNull(gcc, "gcc not found in crosstool toolpaths"); + String toolchainDirectory = NdkPaths.getToolchainDirectoryFromToolPath(gcc.getPath()); + + // Create file glob patterns for the various files that the toolchain references. + + String androidPlatformIncludes = + NdkPaths.stripRepositoryPrefix(toolchain.getBuiltinSysroot()) + "/**/*"; + + List toolchainFileGlobPatterns = new ArrayList<>(); + toolchainFileGlobPatterns.add(androidPlatformIncludes); + + for (String cxxFlag : toolchain.getUnfilteredCxxFlagList()) { + if (!cxxFlag.startsWith("-")) { // Skip flag names + toolchainFileGlobPatterns.add(NdkPaths.stripRepositoryPrefix(cxxFlag) + "/**/*"); + } + } + + // For NDK 15 and up. Unfortunately, the toolchain does not encode the NDK revision number. + toolchainFileGlobPatterns.add("ndk/sysroot/**/*"); + + // If this is a clang toolchain, also add the corresponding gcc toolchain to the globs. + int gccToolchainIndex = toolchain.getCompilerFlagList().indexOf("-gcc-toolchain"); + if (gccToolchainIndex > -1) { + String gccToolchain = toolchain.getCompilerFlagList().get(gccToolchainIndex + 1); + toolchainFileGlobPatterns.add(NdkPaths.stripRepositoryPrefix(gccToolchain) + "/**/*"); + } + + StringBuilder toolchainFileGlobs = new StringBuilder(); + for (String toolchainFileGlobPattern : toolchainFileGlobPatterns) { + toolchainFileGlobs.append(String.format(" \"%s\",\n", toolchainFileGlobPattern)); + } + + return ccToolchainTemplate + .replace("%toolchainName%", toolchain.getToolchainIdentifier()) + .replace("%cpu%", toolchain.getTargetCpu()) + .replace("%compiler%", toolchain.getCompiler()) + .replace("%version%", version) + .replace("%dynamicRuntimeLibs%", toolchain.getDynamicRuntimesFilegroup()) + .replace("%staticRuntimeLibs%", toolchain.getStaticRuntimesFilegroup()) + .replace("%toolchainDirectory%", toolchainDirectory) + .replace("%toolchainFileGlobs%", toolchainFileGlobs.toString().trim()); + } + + private static String getTemplate(String templateFile) { + try { + return ResourceFileLoader.loadResource(AndroidNdkRepositoryFunction.class, templateFile); + } catch (IOException e) { + throw new IllegalStateException(e); } } @@ -224,150 +366,122 @@ public RepositoryDirectoryValue.Builder fetch( String defaultCrosstool = getDefaultCrosstool(ndkRelease.majorRevision); - String buildFile = createBuildFile(ruleName, defaultCrosstool, crosstoolsAndStls.build()); + ImmutableList crosstoolStlPairs = crosstoolsAndStls.build(); + String buildFile = createBuildFile(ruleName, defaultCrosstool, crosstoolStlPairs); writeBuildFile(outputDirectory, buildFile); + ImmutableList.Builder bigConditional = ImmutableList.builder(); + for (CrosstoolStlPair pair : crosstoolStlPairs) { + for (CToolchain toolchain : pair.crosstoolRelease.getToolchainList()) { + bigConditional.addAll(generateBzlConfigFor(pair.stlImpl.getName(), toolchain)); + } + } + writeFile( + outputDirectory, + "cc_toolchain_config.bzl", + getTemplate("android_ndk_cc_toolchain_config_template.txt") + .replaceAll( + "%big_conditional_populating_variables%", + Joiner.on("\n" + " ").join(bigConditional.build()))); return RepositoryDirectoryValue.builder().setPath(outputDirectory); } - @Override - public Class getRuleDefinition() { - return AndroidNdkRepositoryRule.class; - } - - private static String getDefaultCrosstool(Integer majorRevision) { - // From NDK 17, libc++ replaces gnu-libstdc++ as the default STL. - return majorRevision <= 16 ? GnuLibStdCppStlImpl.NAME : LibCppStlImpl.NAME; - } - - private static PathFragment getAndroidNdkHomeEnvironmentVar( - Path workspace, Map env) { - return workspace.getRelative(PathFragment.create(env.get(PATH_ENV_VAR))).asFragment(); - } - - private static String createBuildFile( - String ruleName, String defaultCrosstool, List crosstools) { - - String buildFileTemplate = getTemplate("android_ndk_build_file_template.txt"); - String ccToolchainSuiteTemplate = getTemplate("android_ndk_cc_toolchain_suite_template.txt"); - String ccToolchainTemplate = getTemplate("android_ndk_cc_toolchain_template.txt"); - String stlFilegroupTemplate = getTemplate("android_ndk_stl_filegroup_template.txt"); - String miscLibrariesTemplate = getTemplate("android_ndk_misc_libraries_template.txt"); - - StringBuilder ccToolchainSuites = new StringBuilder(); - StringBuilder ccToolchainRules = new StringBuilder(); - StringBuilder stlFilegroups = new StringBuilder(); - for (CrosstoolStlPair crosstoolStlPair : crosstools) { - - // Create the cc_toolchain_suite rule - CrosstoolRelease crosstool = crosstoolStlPair.crosstoolRelease; - - StringBuilder toolchainMap = new StringBuilder(); - for (CToolchain toolchain : crosstool.getToolchainList()) { - toolchainMap.append( - String.format( - " '%s': ':%s',\n '%s|%s': ':%s',\n", - toolchain.getTargetCpu(), - toolchain.getToolchainIdentifier(), - toolchain.getTargetCpu(), - toolchain.getCompiler(), - toolchain.getToolchainIdentifier())); - } - - String toolchainName = createToolchainName(crosstoolStlPair.stlImpl.getName()); - - ccToolchainSuites.append( - ccToolchainSuiteTemplate - .replace("%toolchainName%", toolchainName) - .replace("%toolchainMap%", toolchainMap.toString().trim()) - .replace("%crosstoolReleaseProto%", crosstool.toString())); - - // Create the cc_toolchain rules - for (CToolchain toolchain : crosstool.getToolchainList()) { - ccToolchainRules.append(createCcToolchainRule(ccToolchainTemplate, toolchain)); - } - - // Create the STL file group rules - for (Map.Entry entry : - crosstoolStlPair.stlImpl.getFilegroupNamesAndFilegroupFileGlobPatterns().entrySet()) { - - stlFilegroups.append( - stlFilegroupTemplate - .replace("%name%", entry.getKey()) - .replace("%fileGlobPattern%", entry.getValue())); + private ImmutableList generateBzlConfigFor(String version, CToolchain toolchain) { + ImmutableList.Builder bigConditional = ImmutableList.builder(); + String cpu = toolchain.getTargetCpu(); + String compiler = toolchain.getCompiler(); + + Preconditions.checkArgument( + toolchain.getLinkingModeFlagsCount() == 0, "linking_mode_flags not supported."); + Preconditions.checkArgument( + toolchain.getActionConfigCount() == 0, "action_configs not supported."); + Preconditions.checkArgument(toolchain.getFeatureCount() == 0, "features not supported."); + Preconditions.checkArgument(toolchain.getArFlagCount() == 0, "ar_flags not supported."); + Preconditions.checkArgument( + toolchain.getArtifactNamePatternCount() == 0, "artifact_name_patterns not supported."); + Preconditions.checkArgument(toolchain.getCxxFlagCount() == 0, "cxx_flags not supported."); + Preconditions.checkArgument( + toolchain.getDynamicLibraryLinkerFlagCount() == 0, + "dynamic_library_linker_flags not supported."); + Preconditions.checkArgument( + toolchain.getLdEmbedFlagCount() == 0, "ld_embed_flags not supported."); + Preconditions.checkArgument( + toolchain.getObjcopyEmbedFlagCount() == 0, "objcopy_embed_flags not supported."); + Preconditions.checkArgument( + toolchain.getMakeVariableCount() == 0, "make_variables not supported."); + Preconditions.checkArgument( + toolchain.getTestOnlyLinkerFlagCount() == 0, "test_only_linker_flags not supported."); + + CompilationModeFlags fastbuild = null; + CompilationModeFlags dbg = null; + CompilationModeFlags opt = null; + for (CompilationModeFlags flags : toolchain.getCompilationModeFlagsList()) { + Preconditions.checkArgument( + flags.getCxxFlagCount() == 0, "compilation_mode_flags.cxx_flags not supported."); + Preconditions.checkArgument( + flags.getLinkerFlagCount() == 0, "compilation_mode_flags.linker_flags not supported."); + if (flags.getMode().equals(CompilationMode.FASTBUILD)) { + fastbuild = flags; + } else if (flags.getMode().equals(CompilationMode.DBG)) { + dbg = flags; + } else if (flags.getMode().equals(CompilationMode.OPT)) { + opt = flags; } } - return buildFileTemplate - .replace("%ruleName%", ruleName) - .replace("%defaultCrosstool%", "//:toolchain-" + defaultCrosstool) - .replace("%ccToolchainSuites%", ccToolchainSuites) - .replace("%ccToolchainRules%", ccToolchainRules) - .replace("%stlFilegroups%", stlFilegroups) - .replace("%miscLibraries%", miscLibrariesTemplate); + bigConditional.add( + String.format( + "if cpu == '%s' and compiler == '%s' and version == '%s':", cpu, compiler, version), + String.format( + " default_compile_flags = [%s]", + toSequenceOfStarlarkStrings(toolchain.getCompilerFlagList())), + String.format( + " unfiltered_compile_flags = [%s]", + toSequenceOfStarlarkStrings(toolchain.getUnfilteredCxxFlagList())), + String.format( + " default_link_flags = [%s]", + toSequenceOfStarlarkStrings(toolchain.getLinkerFlagList())), + String.format( + " default_fastbuild_flags = [%s]", + toSequenceOfStarlarkStrings( + fastbuild != null ? fastbuild.getCompilerFlagList() : ImmutableList.of())), + String.format( + " default_dbg_flags = [%s]", + toSequenceOfStarlarkStrings( + dbg != null ? dbg.getCompilerFlagList() : ImmutableList.of())), + String.format( + " default_opt_flags = [%s]", + toSequenceOfStarlarkStrings( + opt != null ? opt.getCompilerFlagList() : ImmutableList.of())), + String.format( + " cxx_builtin_include_directories = [%s]", + toSequenceOfStarlarkStrings(toolchain.getCxxBuiltinIncludeDirectoryList())), + String.format(" target_cpu = '%s'", toolchain.getTargetCpu()), + String.format(" toolchain_identifier = '%s'", toolchain.getToolchainIdentifier()), + String.format(" host_system_name = '%s'", toolchain.getHostSystemName()), + String.format(" target_system_name = '%s'", toolchain.getTargetSystemName()), + String.format(" target_libc = '%s'", toolchain.getTargetLibc()), + String.format(" target_compiler = '%s'", toolchain.getCompiler()), + String.format(" abi_version = '%s'", toolchain.getAbiVersion()), + String.format(" abi_libc_version = '%s'", toolchain.getAbiLibcVersion()), + String.format(" builtin_sysroot = '%s'", toolchain.getBuiltinSysroot())); + bigConditional.addAll( + toolchain.getToolPathList().stream() + .map( + tp -> + String.format( + " %s_path = '%s'", + tp.getName().toLowerCase().replaceAll("-", "_"), tp.getPath())) + .collect(ImmutableList.toImmutableList())); + return bigConditional.add("").build(); } - static String createToolchainName(String stlName) { - return TOOLCHAIN_NAME_PREFIX + stlName; + private String toSequenceOfStarlarkStrings(Iterable flags) { + return "'" + Joiner.on("', '").join(flags) + "'"; } - private static String createCcToolchainRule(String ccToolchainTemplate, CToolchain toolchain) { - - // TODO(bazel-team): It's unfortunate to have to extract data from a CToolchain proto like this. - // It would be better to have a higher-level construction (like an AndroidToolchain class) - // from which the CToolchain proto and rule information needed here can be created. - // Alternatively it would be nicer to just be able to glob the entire NDK and add that one glob - // to each cc_toolchain rule, and then the complexities in the method and the templates can - // go away, but globbing the entire NDK takes ~60 seconds, mostly because of MD5ing all the - // binary files in the NDK (eg the .so / .a / .o files). - - // This also includes the files captured with cxx_builtin_include_directory. - // Use gcc specifically because clang toolchains will have both gcc and llvm toolchain paths, - // but the gcc tool will actually be clang. - ToolPath gcc = null; - for (ToolPath toolPath : toolchain.getToolPathList()) { - if ("gcc".equals(toolPath.getName())) { - gcc = toolPath; - } - } - checkNotNull(gcc, "gcc not found in crosstool toolpaths"); - String toolchainDirectory = NdkPaths.getToolchainDirectoryFromToolPath(gcc.getPath()); - - // Create file glob patterns for the various files that the toolchain references. - - String androidPlatformIncludes = - NdkPaths.stripRepositoryPrefix(toolchain.getBuiltinSysroot()) + "/**/*"; - - List toolchainFileGlobPatterns = new ArrayList<>(); - toolchainFileGlobPatterns.add(androidPlatformIncludes); - - for (String cxxFlag : toolchain.getUnfilteredCxxFlagList()) { - if (!cxxFlag.startsWith("-")) { // Skip flag names - toolchainFileGlobPatterns.add(NdkPaths.stripRepositoryPrefix(cxxFlag) + "/**/*"); - } - } - - // For NDK 15 and up. Unfortunately, the toolchain does not encode the NDK revision number. - toolchainFileGlobPatterns.add("ndk/sysroot/**/*"); - - // If this is a clang toolchain, also add the corresponding gcc toolchain to the globs. - int gccToolchainIndex = toolchain.getCompilerFlagList().indexOf("-gcc-toolchain"); - if (gccToolchainIndex > -1) { - String gccToolchain = toolchain.getCompilerFlagList().get(gccToolchainIndex + 1); - toolchainFileGlobPatterns.add(NdkPaths.stripRepositoryPrefix(gccToolchain) + "/**/*"); - } - - StringBuilder toolchainFileGlobs = new StringBuilder(); - for (String toolchainFileGlobPattern : toolchainFileGlobPatterns) { - toolchainFileGlobs.append(String.format(" \"%s\",\n", toolchainFileGlobPattern)); - } - - return ccToolchainTemplate - .replace("%toolchainName%", toolchain.getToolchainIdentifier()) - .replace("%cpu%", toolchain.getTargetCpu()) - .replace("%dynamicRuntimeLibs%", toolchain.getDynamicRuntimesFilegroup()) - .replace("%staticRuntimeLibs%", toolchain.getStaticRuntimesFilegroup()) - .replace("%toolchainDirectory%", toolchainDirectory) - .replace("%toolchainFileGlobs%", toolchainFileGlobs.toString().trim()); + @Override + public Class getRuleDefinition() { + return AndroidNdkRepositoryRule.class; } private NdkRelease getNdkRelease(Path directory, Environment env) @@ -402,14 +516,6 @@ private NdkRelease getNdkRelease(Path directory, Environment env) return NdkRelease.create(releaseFileContent.trim()); } - private static String getTemplate(String templateFile) { - try { - return ResourceFileLoader.loadResource(AndroidNdkRepositoryFunction.class, templateFile); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - @Override protected void throwInvalidPathException(Path path, Exception e) throws RepositoryFunctionException { @@ -423,4 +529,15 @@ protected void throwInvalidPathException(Path path, Exception e) e), Transience.PERSISTENT); } + + private static final class CrosstoolStlPair { + + private final CrosstoolRelease crosstoolRelease; + private final StlImpl stlImpl; + + private CrosstoolStlPair(CrosstoolRelease crosstoolRelease, StlImpl stlImpl) { + this.crosstoolRelease = crosstoolRelease; + this.stlImpl = stlImpl; + } + } } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_build_file_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_build_file_template.txt index 6612d278907542..0d0fbb45652c6f 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_build_file_template.txt +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_build_file_template.txt @@ -15,6 +15,8 @@ # This build file was automatically generated for the # android_ndk_repository rule "%ruleName%" +load(":cc_toolchain_config.bzl", "cc_toolchain_config") + package(default_visibility = ["//visibility:public"]) filegroup( diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_config_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_config_template.txt new file mode 100644 index 00000000000000..98e1afb6b5859a --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_config_template.txt @@ -0,0 +1,274 @@ +"""Definition of cc_toolchain_config for one NDK version. + +Cc_toolchain depends on targets of this rule to construct the command lines +and to detect which C++ features are supported by this toolchain. +""" +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "action_config", + "artifact_name_pattern", + "env_entry", + "env_set", + "feature", + "feature_set", + "flag_group", + "flag_set", + "make_variable", + "tool", + "tool_path", + "variable_with_value", + "with_feature_set", +) +load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") + +def _impl(ctx): + cpu = ctx.attr.cpu + compiler = ctx.attr.compiler + version = ctx.attr.version + all_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, + ACTION_NAMES.lto_backend, + ] + + all_link_actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ] + + opt_feature = feature(name = "opt") + fastbuild_feature = feature(name = "fastbuild") + dbg_feature = feature(name = "dbg") + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + supports_pic_feature = feature(name = "supports_pic", enabled = True) + static_link_cpp_runtimes_feature = feature(name = "static_link_cpp_runtimes", enabled = True) + + + default_compile_flags = [] + unfiltered_compile_flags = [] + default_link_flags = [] + default_fastbuild_flags = [] + default_dbg_flags = [] + default_opt_flags = [] + cxx_builtin_include_directories = [] + target_cpu = None + toolchain_identifier = None + host_system_name = None + target_system_name = None + abi_version = None + abi_libc_version = None + target_libc = None + target_compiler = None + abi_version = None + builtin_sysroot = None + ar_path = None + cpp_path = None + dwp_path = None + gcc_path = None + gcov_path = None + gcov_tool_path = None + ld_path = None + nm_path = None + objcopy_path = None + objdump_path = None + strip_path = None + llvm_profdata_path = None + + %big_conditional_populating_variables% + + default_compile_flag_sets = [] + if default_compile_flags: + default_compile_flag_sets.append( + flag_set( + actions = all_compile_actions, + flag_groups = [ + flag_group( + flags = default_compile_flags, + ), + ], + ), + ) + if default_fastbuild_flags: + default_compile_flag_sets.append( + flag_set( + actions = all_compile_actions, + flag_groups = [flag_group(flags = default_fastbuild_flags)], + with_features = [with_feature_set(features = ["fastbuild"])], + ), + ) + if default_dbg_flags: + default_compile_flag_sets.append( + flag_set( + actions = all_compile_actions, + flag_groups = [flag_group(flags = default_dbg_flags)], + with_features = [with_feature_set(features = ["dbg"])], + ), + ) + if default_opt_flags: + default_compile_flag_sets.append( + flag_set( + actions = all_compile_actions, + flag_groups = [flag_group(flags = default_opt_flags)], + with_features = [with_feature_set(features = ["opt"])], + ), + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = default_compile_flag_sets, + ) + + default_link_flag_sets = [] + if default_link_flags: + default_link_flag_sets.append( + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = default_link_flags, + ), + ], + ), + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = default_link_flag_sets, + ) + + user_compile_flags_feature = feature( + name = "user_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_compile_actions, + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + sysroot_feature = feature( + name = "sysroot", + enabled = True, + flag_sets = [ + flag_set( + actions = all_compile_actions + all_link_actions, + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + unfiltered_compile_flag_sets = [] + if unfiltered_compile_flags: + unfiltered_compile_flag_sets.append( + flag_set( + actions = all_compile_actions, + flag_groups = [ + flag_group( + flags = unfiltered_compile_flags, + ), + ], + )) + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + enabled = True, + flag_sets = unfiltered_compile_flag_sets, + ) + + features = [ + default_compile_flags_feature, + default_link_flags_feature, + supports_dynamic_linker_feature, + supports_pic_feature, + static_link_cpp_runtimes_feature, + fastbuild_feature, + dbg_feature, + opt_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + ] + + tool_paths = [] + if ar_path: + tool_paths.append(tool_path(name = "ar", path = ar_path)) + if cpp_path: + tool_paths.append(tool_path(name = "cpp", path = cpp_path)) + if dwp_path: + tool_paths.append(tool_path(name = "dwp", path = dwp_path)) + if gcc_path: + tool_paths.append(tool_path(name = "gcc", path = gcc_path)) + if gcov_path: + tool_paths.append(tool_path(name = "gcov", path = gcov_path)) + if gcov_tool_path: + tool_paths.append(tool_path(name = "gcov", path = gcov_tool_path)) + if ld_path: + tool_paths.append(tool_path(name = "ld", path = ld_path)) + if nm_path: + tool_paths.append(tool_path(name = "nm", path = nm_path)) + if objcopy_path: + tool_paths.append(tool_path(name = "objcopy", path = objcopy_path)) + if objdump_path: + tool_paths.append(tool_path(name = "objdump", path = objdump_path)) + if strip_path: + tool_paths.append(tool_path(name = "strip", path = strip_path)) + if llvm_profdata_path: + tool_paths.append(tool_path(name = "llvm_profdata", path = llvm_profdata_path)) + + out = ctx.actions.declare_file(ctx.label.name) + ctx.actions.write(out, "Fake executable") + return [ + cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = [], + artifact_name_patterns = [], + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = target_compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = [], + builtin_sysroot = builtin_sysroot, + ), + DefaultInfo( + executable = out, + ), + ] + +cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "cpu": attr.string(mandatory = True), + "compiler": attr.string(mandatory = True), + "version": attr.string(mandatory = True), + }, + provides = [CcToolchainConfigInfo], + executable = True, +) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_suite_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_suite_template.txt index 81bfabc28165b5..dee033d90f0c79 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_suite_template.txt +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_suite_template.txt @@ -3,7 +3,5 @@ cc_toolchain_suite( toolchains = { %toolchainMap% }, - proto = """ -%crosstoolReleaseProto% -""") +) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt index ce8488dcd0b25a..d9bd1521568b41 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt @@ -8,7 +8,6 @@ cc_toolchain( ar_files = ":%toolchainName%-all_files", as_files = ":%toolchainName%-all_files", compiler_files = ":%toolchainName%-all_files", - cpu = "%cpu%", dwp_files = ":%toolchainName%-all_files", dynamic_runtime_lib = ":%dynamicRuntimeLibs%", linker_files = ":%toolchainName%-all_files", @@ -17,6 +16,14 @@ cc_toolchain( strip_files = ":%toolchainName%-all_files", supports_param_files = 0, toolchain_identifier = "%toolchainName%", + toolchain_config = ":%toolchainName%-config", +) + +cc_toolchain_config( + name = "%toolchainName%-config", + cpu = "%cpu%", + compiler = "%compiler%", + version = "%version%", ) filegroup( diff --git a/src/test/java/com/google/devtools/build/lib/bazel/BUILD b/src/test/java/com/google/devtools/build/lib/bazel/BUILD index 259d5ebab868c1..88f336d6060f65 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/BUILD +++ b/src/test/java/com/google/devtools/build/lib/bazel/BUILD @@ -37,6 +37,8 @@ java_test( srcs = glob(["rules/**/*.java"]), resources = [ "//tools/android:android_sdk_repository_template.bzl", + "//tools/build_defs/cc:action_names.bzl", + "//tools/cpp:cc_toolchain_config_lib.bzl", ] + glob(["rules/**/*.txt"]), tags = ["rules"], test_class = "com.google.devtools.build.lib.AllTests", diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java index 1620d2935d0a8b..c75bad7eb217d4 100644 --- a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java +++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java @@ -23,8 +23,11 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.packages.AttributeContainer; import com.google.devtools.build.lib.packages.BuildFileNotFoundException; +import com.google.devtools.build.lib.packages.util.BazelMockCcSupport; +import com.google.devtools.build.lib.packages.util.ResourceLoader; import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData; import com.google.devtools.build.lib.testutil.MoreAsserts; +import com.google.devtools.build.lib.testutil.TestConstants; import com.google.devtools.build.lib.testutil.TestRuleClassProvider; import com.google.devtools.build.lib.vfs.FileSystemUtils; import org.junit.Before; @@ -44,10 +47,18 @@ protected ConfiguredRuleClassProvider getRuleClassProvider() { @Before public void setup() throws Exception { - scratch.file( - "/ndk/source.properties", - "Pkg.Desc = Android NDK", - "Pkg.Revision = 13.1.3345770"); + BazelMockCcSupport.INSTANCE.setup(mockToolsConfig); + scratch.overwriteFile("/bazel_tools_workspace/tools/build_defs/cc/BUILD"); + scratch.overwriteFile( + "/bazel_tools_workspace/tools/build_defs/cc/action_names.bzl", + ResourceLoader.readFromResources( + TestConstants.BAZEL_REPO_PATH + "tools/build_defs/cc/action_names.bzl")); + + scratch.overwriteFile( + "/bazel_tools_workspace/tools/cpp/cc_toolchain_config_lib.bzl", + ResourceLoader.readFromResources( + TestConstants.BAZEL_REPO_PATH + "tools/cpp/cc_toolchain_config_lib.bzl")); + scratch.file("/ndk/source.properties", "Pkg.Desc = Android NDK", "Pkg.Revision = 13.1.3345770"); } private void scratchPlatformsDirectories(String arch, int... apiLevels) throws Exception { @@ -63,6 +74,7 @@ public void testApiLevelHighestVersionDetection() throws Exception { scratchPlatformsDirectories("arch-x86", 19, 20, 22, 24); FileSystemUtils.appendIsoLatin1( scratch.resolve("WORKSPACE"), + "local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')", "android_ndk_repository(", " name = 'androidndk',", " path = '/ndk',", @@ -86,6 +98,7 @@ public void testInvalidNdkReleaseTxt() throws Exception { scratchPlatformsDirectories("arch-x86", 24); FileSystemUtils.appendIsoLatin1( scratch.resolve("WORKSPACE"), + "local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')", "android_ndk_repository(", " name = 'androidndk',", " path = '/ndk',", @@ -110,6 +123,7 @@ public void testInvalidNdkSourceProperties() throws Exception { scratchPlatformsDirectories("arch-x86", 24); FileSystemUtils.appendIsoLatin1( scratch.resolve("WORKSPACE"), + "local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')", "android_ndk_repository(", " name = 'androidndk',", " path = '/ndk',", @@ -136,6 +150,7 @@ public void testUnsupportedNdkVersion() throws Exception { scratchPlatformsDirectories("arch-x86", 24); FileSystemUtils.appendIsoLatin1( scratch.resolve("WORKSPACE"), + "local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')", "android_ndk_repository(", " name = 'androidndk',", " path = '/ndk',", @@ -162,6 +177,7 @@ public void testMiscLibraries() throws Exception { scratch.file(String.format("/ndk/sources/android/cpufeatures/cpu-features.h")); FileSystemUtils.appendIsoLatin1( scratch.resolve("WORKSPACE"), + "local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')", "android_ndk_repository(", " name = 'androidndk',", " path = '/ndk',", @@ -184,6 +200,7 @@ public void testMiscLibraries() throws Exception { public void testMissingPlatformsDirectory() throws Exception { FileSystemUtils.appendIsoLatin1( scratch.resolve("WORKSPACE"), + "local_repository(name = 'bazel_tools', path = '/bazel_tools_workspace')", "android_ndk_repository(", " name = 'androidndk',", " path = '/ndk',",