{"id":1807,"date":"2026-05-24T15:21:23","date_gmt":"2026-05-24T22:21:23","guid":{"rendered":"https:\/\/nanzhou.cc\/?p=1807"},"modified":"2026-05-24T15:41:54","modified_gmt":"2026-05-24T22:41:54","slug":"bazel-select","status":"publish","type":"post","link":"https:\/\/nanzhou.cc\/index.php\/2026\/05\/24\/bazel-select\/","title":{"rendered":"Bazel: select"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Think of <code>select()<\/code> as a <strong>conditional expression<\/strong> that lives inside your build rules. It functions exactly like a <code>switch<\/code> or <code>if\/else<\/code> statement in a programming language, but it operates during the &#8220;analysis phase&#8221; of a Bazel build.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See the other <a href=\"https:\/\/nanzhou.cc\/index.php\/2026\/05\/24\/bazel-platforms\/\">post<\/a> for constraint_setting and constraint_values<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. The Core Purpose<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When you build code, you often have minor differences based on the environment. Maybe you need a specific header file on Windows, or a different compiler flag for ARM processors. Instead of creating different build files for every platform, you use <code>select()<\/code> to keep your build files clean and unified.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. How it works<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You use <code>select()<\/code> inside an attribute (like <code>srcs<\/code>, <code>deps<\/code>, <code>copts<\/code>, or <code>data<\/code>). It takes a dictionary where:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>The keys<\/strong> are <code>config_setting<\/code> targets (which contain your constraints).<\/li>\n\n\n\n<li><strong>The values<\/strong> are the actual data you want to use if that condition is met.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. A Practical Example<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine you are building a library that handles file paths. You need a different C++ source file depending on whether you are compiling for Windows or Linux.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">cc_library(\n    name = \"file_utils\",\n    srcs = select({\n        \"@platforms\/\/os:windows\": [\"path_win.cc\"],\n        \"@platforms\/\/os:linux\": [\"path_linux.cc\"],\n        \"\/\/conditions:default\": [\"path_generic.cc\"], # The \"else\" case\n    }),\n)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes a single <code>select()<\/code> key isn&#8217;t enough. What if you want to do something only on <strong>&#8220;Linux + x86&#8221;<\/strong>? You can use <code>config_setting<\/code> to group them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"># 1. Define a specific condition\nconfig_setting(\n    name = \"is_linux_x86\",\n    constraint_values = [\n        \"@platforms\/\/os:linux\",\n        \"@platforms\/\/cpu:x86_64\",\n    ],\n)\n\n# 2. Use that condition in a select\ncc_library(\n    name = \"optimized_lib\",\n    srcs = select({\n        \":is_linux_x86\": [\"optimized_x86.cc\"],\n        \"\/\/conditions:default\": [\"generic.cc\"],\n    }),\n)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Anatomy of the <code>select()<\/code><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@platforms\/\/os:windows<\/code><\/strong>: This is your condition. If the current <code>--platforms<\/code> flag results in an environment that has this <code>constraint_value<\/code>, this branch is chosen.<\/li>\n\n\n\n<li><strong><code>\"\/\/conditions:default\"<\/code><\/strong>: This is the <strong>required<\/strong> fallback. If none of your specific conditions match, Bazel uses this value. Your build will fail if you don&#8217;t provide this and no other condition matches.<\/li>\n\n\n\n<li><strong>Merging<\/strong>: If you use <code>select()<\/code> on an attribute that accepts lists (like <code>srcs<\/code>), you can even combine them with non-selected items:Python<code>srcs = [\"common.cc\"] + select({ ... }), <\/code><em>Bazel will automatically concatenate the lists.<\/em><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Why use <code>select()<\/code> instead of just writing two different targets?<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>DRY (Don&#8217;t Repeat Yourself)<\/strong>: You maintain one <code>cc_library<\/code> target instead of having separate <code>cc_library_win<\/code> and <code>cc_library_linux<\/code> targets.<\/li>\n\n\n\n<li><strong>Type Safety<\/strong>: Bazel validates that the constraints used in your <code>select<\/code> are valid <code>constraint_value<\/code> types.<\/li>\n\n\n\n<li><strong>Efficiency<\/strong>: Bazel only computes the graph for the specific path you have chosen. It doesn&#8217;t waste time analyzing the branches that aren&#8217;t relevant to your current build.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">In short, <code>select()<\/code> is the tool you reach for when you want your build logic to be <strong>flexible<\/strong> enough to handle different platforms without becoming a tangled mess of duplicated rules.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">platforms() and select()<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">The Big Picture<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Platforms<\/strong> describe the <strong>&#8220;Where&#8221;<\/strong> (the environment).<\/li>\n\n\n\n<li><strong><code>select()<\/code><\/strong> describes the <strong>&#8220;What&#8221;<\/strong> (the specific code or flags needed for that environment).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">1. Platforms (The Environment Orchestrator)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A <strong>Platform<\/strong> is a collection of <code>constraint_values<\/code> that defines a complete target hardware\/OS environment.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Role:<\/strong> Acts as the master configuration for your entire build.<\/li>\n\n\n\n<li><strong>Purpose:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>Toolchain Resolution:<\/strong> Tells Bazel exactly which compiler, linker, and standard library to use.<\/li>\n\n\n\n<li><strong>Compatibility:<\/strong> Defines what the environment <em>is<\/em> (e.g., &#8220;This is a 64-bit ARM Linux machine&#8221;).<\/li>\n\n\n\n<li><strong>Global Context:<\/strong> You set it once at the top level via the command line (e.g., <code>--platforms=\/\/platforms:my_custom_platform<\/code>), and the entire build graph adopts that context.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. <code>select()<\/code> (The Conditional Switch)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>select()<\/code> is a function used inside individual rules to perform <strong>conditional logic<\/strong>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Role:<\/strong> Acts as an <code>if\/else<\/code> or <code>switch<\/code> statement for specific build attributes.<\/li>\n\n\n\n<li><strong>Purpose:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>Code Variation:<\/strong> Swap source files (<code>srcs<\/code>), dependencies (<code>deps<\/code>), or compiler flags (<code>copts<\/code>) based on specific features.<\/li>\n\n\n\n<li><strong>Granularity:<\/strong> Allows a single target to be &#8220;smarter&#8221; about its requirements without needing separate rules for every platform.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>How it decides:<\/strong> It looks at the constraints provided by the active <code>platform<\/code>. If the active platform contains the constraint specified in your <code>select()<\/code> key, that branch is chosen.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Comparison Summary<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Feature<\/strong><\/td><td><strong>Platforms<\/strong><\/td><td><strong>select()<\/strong><\/td><\/tr><\/thead><tbody><tr><td><strong>Concept<\/strong><\/td><td>The &#8220;Environment&#8221;<\/td><td>The &#8220;Conditional Logic&#8221;<\/td><\/tr><tr><td><strong>Scope<\/strong><\/td><td>Global (entire build graph)<\/td><td>Local (specific target attributes)<\/td><\/tr><tr><td><strong>Function<\/strong><\/td><td>Identifies hardware\/OS capabilities<\/td><td>Swaps code\/flags based on those capabilities<\/td><\/tr><tr><td><strong>Command Line<\/strong><\/td><td>Set by <code>--platforms<\/code><\/td><td>Automatically reacts to <code>--platforms<\/code><\/td><\/tr><tr><td><strong>Best Analogy<\/strong><\/td><td>The OS running on a server<\/td><td>An <code>if<\/code> statement in your code<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">The Complete Cross-Platform Workflow<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>Define your Constraints:<\/strong> Create the <code>constraint_setting<\/code> and <code>constraint_value<\/code> targets (or just use the standard ones from <code>@platforms<\/code>).\n<ul class=\"wp-block-list\">\n<li><em>Example:<\/em> &#8220;I need to distinguish between Windows and Linux.&#8221;<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Define your Platform:<\/strong> Group those constraints into a <code>platform<\/code> target.\n<ul class=\"wp-block-list\">\n<li><em>Example:<\/em> &#8220;Create a <code>my_windows_machine<\/code> platform that includes <code>@platforms\/\/os:windows<\/code>.&#8221;<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Update your Targets (The crucial link!):<\/strong> Modify your existing <code>cc_library<\/code>, <code>cc_binary<\/code>, etc., to use <code>select()<\/code> on their attributes. This tells the rule <em>how<\/em> to change its behavior based on the constraints.\n<ul class=\"wp-block-list\">\n<li><em>Before:<\/em> <code>srcs = [\"default_file.cc\"]<\/code><\/li>\n\n\n\n<li><em>After:<\/em> <code>srcs = select({\"@platforms\/\/os:windows\": [\"win_file.cc\"], \"\/\/conditions:default\": [\"default_file.cc\"]})<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Build with the Platform:<\/strong> Run your build and tell Bazel which platform to act as.\n<ul class=\"wp-block-list\">\n<li><em>Example:<\/em> <code>bazel build \/\/my_app --platforms=\/\/:my_windows_machine<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Bazel Connects the Dots:<\/strong> Bazel sees the <code>--platforms<\/code> flag, checks the platform&#8217;s constraints, looks at your <code>cc_library<\/code>&#8216;s <code>select()<\/code> statement, and automatically picks <code>win_file.cc<\/code>.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Think of select() as a conditional expression that lives inside your build rules. It functions exactly like a switch or if\/else statement in a programming language, but it operates during the &#8220;analysis phase&#8221; of a Bazel build. See the other post for constraint_setting and constraint_values 1. The Core Purpose When you build code, you often&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"0","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[77],"tags":[],"class_list":["post-1807","post","type-post","status-publish","format-standard","hentry","category-Toolchain"],"_links":{"self":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/1807","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/comments?post=1807"}],"version-history":[{"count":3,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/1807\/revisions"}],"predecessor-version":[{"id":1810,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/posts\/1807\/revisions\/1810"}],"wp:attachment":[{"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/media?parent=1807"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/categories?post=1807"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nanzhou.cc\/index.php\/wp-json\/wp\/v2\/tags?post=1807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}