[{"data":1,"prerenderedAt":1618},["ShallowReactive",2],{"page-\u002Frust\u002F28-cargo-features":3},{"id":4,"title":5,"body":6,"description":16,"extension":1612,"meta":1613,"navigation":180,"path":1614,"seo":1615,"stem":1616,"__hash__":1617},"content\u002Frust\u002F28-cargo-features.md","28 — Cargo Features & Release Engineering",{"type":7,"value":8,"toc":1577},"minimark",[9,13,17,22,79,84,106,110,127,134,138,208,250,254,274,293,297,300,304,342,346,490,495,498,518,528,532,579,587,663,666,687,717,728,735,752,764,768,772,806,810,840,844,881,885,915,919,947,951,994,1008,1012,1026,1030,1269,1283,1287,1319,1326,1354,1360,1364,1398,1402,1408,1412,1429,1432,1473,1477,1552,1556,1570,1573],[10,11,5],"h1",{"id":12},"_28-cargo-features-release-engineering",[14,15,16],"p",{},"Cargo features are the standard mechanism for conditional compilation. Combined with profiles and CI, they form the release engineering story.",[18,19,21],"h2",{"id":20},"defining-features","Defining Features",[23,24,26],"code-wrapper",{"language":25},"toml",[27,28,32],"pre",{"className":29,"code":30,"language":25,"meta":31,"style":31},"language-toml shiki shiki-themes github-light github-dark","# Cargo.toml\n[features]\ndefault = [\"json\", \"csv\"]\njson = [\"dep:serde_json\"]          # optional dependency 'serde_json'\ncsv = [\"dep:csv\"]\nfull = [\"json\", \"csv\", \"yaml\"]\nyaml = []\n","",[33,34,35,43,49,55,61,67,73],"code",{"__ignoreMap":31},[36,37,40],"span",{"class":38,"line":39},"line",1,[36,41,42],{},"# Cargo.toml\n",[36,44,46],{"class":38,"line":45},2,[36,47,48],{},"[features]\n",[36,50,52],{"class":38,"line":51},3,[36,53,54],{},"default = [\"json\", \"csv\"]\n",[36,56,58],{"class":38,"line":57},4,[36,59,60],{},"json = [\"dep:serde_json\"]          # optional dependency 'serde_json'\n",[36,62,64],{"class":38,"line":63},5,[36,65,66],{},"csv = [\"dep:csv\"]\n",[36,68,70],{"class":38,"line":69},6,[36,71,72],{},"full = [\"json\", \"csv\", \"yaml\"]\n",[36,74,76],{"class":38,"line":75},7,[36,77,78],{},"yaml = []\n",[80,81,83],"h3",{"id":82},"feature-syntax-160","Feature Syntax (1.60+)",[85,86,87,94,100],"ul",{},[88,89,90,93],"li",{},[33,91,92],{},"dep:crate_name"," — enables an optional dependency without exposing a feature of the same name.",[88,95,96,99],{},[33,97,98],{},"dep_crate\u002Ffeature"," — enables a specific feature of a dependency.",[88,101,102,105],{},[33,103,104],{},"?dep_crate\u002Ffeature"," — only enables the dep's feature if it's already enabled by someone else.",[80,107,109],{"id":108},"optional-dependencies","Optional Dependencies",[23,111,112],{"language":25},[27,113,115],{"className":29,"code":114,"language":25,"meta":31,"style":31},"[dependencies]\nserde_json = { version = \"1.0\", optional = true }\n",[33,116,117,122],{"__ignoreMap":31},[36,118,119],{"class":38,"line":39},[36,120,121],{},"[dependencies]\n",[36,123,124],{"class":38,"line":45},[36,125,126],{},"serde_json = { version = \"1.0\", optional = true }\n",[14,128,129,130,133],{},"Optional deps implicitly create a feature of the same name (unless ",[33,131,132],{},"dep:"," is used).",[18,135,137],{"id":136},"using-features","Using Features",[23,139,141],{"language":140},"rust",[27,142,145],{"className":143,"code":144,"language":140,"meta":31,"style":31},"language-rust shiki shiki-themes github-light github-dark","#[cfg(feature = \"json\")]\nmod json;\n\n#[cfg(feature = \"json\")]\npub use json::parse_json;\n",[33,146,147,164,176,182,192],{"__ignoreMap":31},[36,148,149,153,157,161],{"class":38,"line":39},[36,150,152],{"class":151},"ssxIu","#[cfg(feature ",[36,154,156],{"class":155},"svdQ7","=",[36,158,160],{"class":159},"sJ6F3"," \"json\"",[36,162,163],{"class":151},")]\n",[36,165,166,169,173],{"class":38,"line":45},[36,167,168],{"class":155},"mod",[36,170,172],{"class":171},"sIsaT"," json",[36,174,175],{"class":151},";\n",[36,177,178],{"class":38,"line":51},[36,179,181],{"emptyLinePlaceholder":180},true,"\n",[36,183,184,186,188,190],{"class":38,"line":57},[36,185,152],{"class":151},[36,187,156],{"class":155},[36,189,160],{"class":159},[36,191,163],{"class":151},[36,193,194,197,200,202,205],{"class":38,"line":63},[36,195,196],{"class":155},"pub",[36,198,199],{"class":155}," use",[36,201,172],{"class":171},[36,203,204],{"class":155},"::",[36,206,207],{"class":151},"parse_json;\n",[23,209,211],{"language":210},"bash",[27,212,215],{"className":213,"code":214,"language":210,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","cargo build --no-default-features\ncargo build --features json,yaml\ncargo build --all-features\n",[33,216,217,229,241],{"__ignoreMap":31},[36,218,219,222,225],{"class":38,"line":39},[36,220,221],{"class":171},"cargo",[36,223,224],{"class":159}," build",[36,226,228],{"class":227},"snvgF"," --no-default-features\n",[36,230,231,233,235,238],{"class":38,"line":45},[36,232,221],{"class":171},[36,234,224],{"class":159},[36,236,237],{"class":227}," --features",[36,239,240],{"class":159}," json,yaml\n",[36,242,243,245,247],{"class":38,"line":51},[36,244,221],{"class":171},[36,246,224],{"class":159},[36,248,249],{"class":227}," --all-features\n",[18,251,253],{"id":252},"feature-unification","Feature Unification",[14,255,256,257,260,261,265,266,269,270,273],{},"Cargo unifies features across the dependency graph: if any crate enables ",[33,258,259],{},"serde\u002Fderive",", ",[262,263,264],"em",{},"every"," user of ",[33,267,268],{},"serde"," gets ",[33,271,272],{},"derive"," on. Design features accordingly:",[85,275,276,283,286],{},[88,277,278,282],{},[279,280,281],"strong",{},"Don't"," expose \"private\" features that change behavior of your crate depending on who else in the graph enabled them.",[88,284,285],{},"Use additive features (more code enabled), not subtractive.",[88,287,288,289,292],{},"Avoid ",[33,290,291],{},"default-features = false"," on transitive deps unless you understand the consequences.",[80,294,296],{"id":295},"additive-only-rule","Additive-Only Rule",[14,298,299],{},"Features should be strictly additive: enabling a feature adds capabilities, never removes them. If you need mutually-exclusive features, consider splitting crates.",[18,301,303],{"id":302},"common-feature-pitfalls","Common Feature Pitfalls",[85,305,306,319,325,333],{},[88,307,308,311,312,315,316,318],{},[279,309,310],{},"Exposing transitive features",": ",[33,313,314],{},"[\"serde\u002Fderive\"]"," from your crate forces all downstream users to also enable ",[33,317,259],{},".",[88,320,321,324],{},[279,322,323],{},"Cargo feature unification surprise",": if a dep is also enabled by another crate with extra features, you get them all.",[88,326,327,332],{},[279,328,329,331],{},[33,330,291],{}," on transitive deps",": hard to reason about; usually wrong.",[88,334,335,338,339,341],{},[279,336,337],{},"Negation",": features can't disable features. The only \"negation\" is ",[33,340,291],{}," when depending on a crate.",[18,343,345],{"id":344},"build-profiles","Build Profiles",[23,347,348],{"language":25},[27,349,351],{"className":29,"code":350,"language":25,"meta":31,"style":31},"[profile.dev]\nopt-level = 0\ndebug = true\nincremental = true\noverflow-checks = true\n\n[profile.release]\nopt-level = 3\ndebug = false\nlto = \"fat\"               # or \"thin\", or true\u002Ffalse\ncodegen-units = 1          # best optimization, slower compile\npanic = \"unwind\"           # or \"abort\"\nstrip = \"symbols\"\nopt-level = \"z\"            # optimize for size (vs \"s\" or numeric 0-3)\n\n[profile.release.package.\"*\"]\nopt-level = 2              # dependencies at lower opt level for faster compile\n\n[profile.bench]\ninherits = \"release\"\ndebug = true\n\n[profile.dist]\ninherits = \"release\"\nlto = \"thin\"\n",[33,352,353,358,363,368,373,378,382,387,393,399,405,411,417,423,429,434,440,446,451,457,463,468,473,479,484],{"__ignoreMap":31},[36,354,355],{"class":38,"line":39},[36,356,357],{},"[profile.dev]\n",[36,359,360],{"class":38,"line":45},[36,361,362],{},"opt-level = 0\n",[36,364,365],{"class":38,"line":51},[36,366,367],{},"debug = true\n",[36,369,370],{"class":38,"line":57},[36,371,372],{},"incremental = true\n",[36,374,375],{"class":38,"line":63},[36,376,377],{},"overflow-checks = true\n",[36,379,380],{"class":38,"line":69},[36,381,181],{"emptyLinePlaceholder":180},[36,383,384],{"class":38,"line":75},[36,385,386],{},"[profile.release]\n",[36,388,390],{"class":38,"line":389},8,[36,391,392],{},"opt-level = 3\n",[36,394,396],{"class":38,"line":395},9,[36,397,398],{},"debug = false\n",[36,400,402],{"class":38,"line":401},10,[36,403,404],{},"lto = \"fat\"               # or \"thin\", or true\u002Ffalse\n",[36,406,408],{"class":38,"line":407},11,[36,409,410],{},"codegen-units = 1          # best optimization, slower compile\n",[36,412,414],{"class":38,"line":413},12,[36,415,416],{},"panic = \"unwind\"           # or \"abort\"\n",[36,418,420],{"class":38,"line":419},13,[36,421,422],{},"strip = \"symbols\"\n",[36,424,426],{"class":38,"line":425},14,[36,427,428],{},"opt-level = \"z\"            # optimize for size (vs \"s\" or numeric 0-3)\n",[36,430,432],{"class":38,"line":431},15,[36,433,181],{"emptyLinePlaceholder":180},[36,435,437],{"class":38,"line":436},16,[36,438,439],{},"[profile.release.package.\"*\"]\n",[36,441,443],{"class":38,"line":442},17,[36,444,445],{},"opt-level = 2              # dependencies at lower opt level for faster compile\n",[36,447,449],{"class":38,"line":448},18,[36,450,181],{"emptyLinePlaceholder":180},[36,452,454],{"class":38,"line":453},19,[36,455,456],{},"[profile.bench]\n",[36,458,460],{"class":38,"line":459},20,[36,461,462],{},"inherits = \"release\"\n",[36,464,466],{"class":38,"line":465},21,[36,467,367],{},[36,469,471],{"class":38,"line":470},22,[36,472,181],{"emptyLinePlaceholder":180},[36,474,476],{"class":38,"line":475},23,[36,477,478],{},"[profile.dist]\n",[36,480,482],{"class":38,"line":481},24,[36,483,462],{},[36,485,487],{"class":38,"line":486},25,[36,488,489],{},"lto = \"thin\"\n",[80,491,493],{"id":492},"inherits",[33,494,492],{},[14,496,497],{},"Custom profiles can inherit from existing ones:",[23,499,500],{"language":25},[27,501,503],{"className":29,"code":502,"language":25,"meta":31,"style":31},"[profile.profiling]\ninherits = \"release\"\ndebug = true\n",[33,504,505,510,514],{"__ignoreMap":31},[36,506,507],{"class":38,"line":39},[36,508,509],{},"[profile.profiling]\n",[36,511,512],{"class":38,"line":45},[36,513,462],{},[36,515,516],{"class":38,"line":51},[36,517,367],{},[14,519,520,521,524,525,318],{},"Build with ",[33,522,523],{},"cargo build --profile profiling",". Output goes to ",[33,526,527],{},"target\u002Fprofiling",[80,529,531],{"id":530},"profile-pitfalls","Profile Pitfalls",[85,533,534,543,551,563],{},[88,535,536,542],{},[279,537,538,541],{},[33,539,540],{},"lto = \"fat\""," dramatically slows compile"," but produces smaller\u002Ffaster binaries. Use only in release.",[88,544,545,550],{},[279,546,547],{},[33,548,549],{},"codegen-units = 1"," is best for performance, slowest to compile.",[88,552,553,558,559,562],{},[279,554,555],{},[33,556,557],{},"panic = \"abort\""," breaks some code that relies on unwinding (and on catching panics via ",[33,560,561],{},"catch_unwind",").",[88,564,565,570,571,574,575,578],{},[279,566,567],{},[33,568,569],{},"opt-level = \"z\""," optimizes for binary size; ",[33,572,573],{},"\"s\""," for size + some speed; ",[33,576,577],{},"3"," for max speed.",[18,580,582,583,586],{"id":581},"build-scripts-buildrs","Build Scripts (",[33,584,585],{},"build.rs",")",[23,588,589],{"language":140},[27,590,592],{"className":143,"code":591,"language":140,"meta":31,"style":31},"\u002F\u002F build.rs\nfn main() {\n    println!(\"cargo:rustc-env=MY_VAR=value\");\n    println!(\"cargo:rerun-if-changed=some_file.txt\");\n    println!(\"cargo:rustc-link-lib=mylib\");\n    println!(\"cargo:rustc-link-search=vendor\u002Flib\");\n}\n",[33,593,594,600,611,625,636,647,658],{"__ignoreMap":31},[36,595,596],{"class":38,"line":39},[36,597,599],{"class":598},"sdCPZ","\u002F\u002F build.rs\n",[36,601,602,605,608],{"class":38,"line":45},[36,603,604],{"class":155},"fn",[36,606,607],{"class":171}," main",[36,609,610],{"class":151},"() {\n",[36,612,613,616,619,622],{"class":38,"line":51},[36,614,615],{"class":171},"    println!",[36,617,618],{"class":151},"(",[36,620,621],{"class":159},"\"cargo:rustc-env=MY_VAR=value\"",[36,623,624],{"class":151},");\n",[36,626,627,629,631,634],{"class":38,"line":57},[36,628,615],{"class":171},[36,630,618],{"class":151},[36,632,633],{"class":159},"\"cargo:rerun-if-changed=some_file.txt\"",[36,635,624],{"class":151},[36,637,638,640,642,645],{"class":38,"line":63},[36,639,615],{"class":171},[36,641,618],{"class":151},[36,643,644],{"class":159},"\"cargo:rustc-link-lib=mylib\"",[36,646,624],{"class":151},[36,648,649,651,653,656],{"class":38,"line":69},[36,650,615],{"class":171},[36,652,618],{"class":151},[36,654,655],{"class":159},"\"cargo:rustc-link-search=vendor\u002Flib\"",[36,657,624],{"class":151},[36,659,660],{"class":38,"line":75},[36,661,662],{"class":151},"}\n",[14,664,665],{},"Use for:",[85,667,668,675,678,684],{},[88,669,670,671,674],{},"Compiling C code (",[33,672,673],{},"cc"," crate).",[88,676,677],{},"Generating code (e.g., protobuf, SQL).",[88,679,680,681,318],{},"Setting env vars for ",[33,682,683],{},"env!()",[88,685,686],{},"Link configuration.",[14,688,689,690,260,693,260,696,260,699,260,702,260,705,260,708,260,711,260,714,318],{},"Read env vars set by Cargo: ",[33,691,692],{},"CARGO_PKG_VERSION",[33,694,695],{},"CARGO_MANIFEST_DIR",[33,697,698],{},"OUT_DIR",[33,700,701],{},"TARGET",[33,703,704],{},"HOST",[33,706,707],{},"OPT_LEVEL",[33,709,710],{},"PROFILE",[33,712,713],{},"DEBUG",[33,715,716],{},"NUM_JOBS",[14,718,719,720,723,724,727],{},"Use ",[33,721,722],{},"env!(\"VAR\")"," or ",[33,725,726],{},"option_env!(\"VAR\")"," in code to read build-time env vars.",[18,729,731,734],{"id":730},"links-key",[33,732,733],{},"links"," Key",[23,736,737],{"language":25},[27,738,740],{"className":29,"code":739,"language":25,"meta":31,"style":31},"[links]\nfoo = \"1.0\"\n",[33,741,742,747],{"__ignoreMap":31},[36,743,744],{"class":38,"line":39},[36,745,746],{},"[links]\n",[36,748,749],{"class":38,"line":45},[36,750,751],{},"foo = \"1.0\"\n",[14,753,754,756,757,760,761,763],{},[33,755,733],{}," declares that the crate links to a native library named ",[33,758,759],{},"foo",". Prevents two crates from both linking to ",[33,762,759],{}," with conflicting build scripts.",[18,765,767],{"id":766},"release-checklist","Release Checklist",[80,769,771],{"id":770},"code-quality","Code Quality",[85,773,774,779,788,794,800],{},[88,775,776],{},[33,777,778],{},"cargo fmt -- --check",[88,780,781,784,785,586],{},[33,782,783],{},"cargo clippy -- -D warnings"," (and ",[33,786,787],{},"--all-targets",[88,789,790,793],{},[33,791,792],{},"cargo deny check"," (licenses, advisories, bans)",[88,795,796,799],{},[33,797,798],{},"cargo audit"," (RustSec advisories)",[88,801,802,805],{},[33,803,804],{},"cargo machete"," (unused deps)",[80,807,809],{"id":808},"testing","Testing",[85,811,812,817,823,828,834],{},[88,813,814],{},[33,815,816],{},"cargo test --all-features",[88,818,819,822],{},[33,820,821],{},"cargo test --no-default-features"," (smoke)",[88,824,825],{},[33,826,827],{},"cargo test --workspace",[88,829,830,831],{},"Doc tests: ",[33,832,833],{},"cargo test --doc",[88,835,836,837],{},"Cross-compile: ",[33,838,839],{},"cargo build --target x86_64-unknown-linux-musl",[80,841,843],{"id":842},"performance","Performance",[85,845,846,856,868],{},[88,847,848,849,852,853],{},"Benchmarks: ",[33,850,851],{},"cargo bench"," (nightly) or ",[33,854,855],{},"criterion",[88,857,858,859,260,862,260,865],{},"Profile with ",[33,860,861],{},"cargo flamegraph",[33,863,864],{},"perf",[33,866,867],{},"samply",[88,869,870,871,260,874,877,878],{},"Check binary size: ",[33,872,873],{},"cargo bloat",[33,875,876],{},"cargo build --release"," then ",[33,879,880],{},"ls -lh",[80,882,884],{"id":883},"binary","Binary",[85,886,887,893,899,905],{},[88,888,889,890],{},"Strip symbols: ",[33,891,892],{},"strip = \"symbols\"",[88,894,895,896,898],{},"LTO: ",[33,897,540],{}," for final",[88,900,901,902,904],{},"Consider ",[33,903,557],{}," if you don't need unwinding",[88,906,907,908,260,910,260,912],{},"For size-critical: ",[33,909,569],{},[33,911,549],{},[33,913,914],{},"lto = true",[80,916,918],{"id":917},"versioning","Versioning",[85,920,921,927,937],{},[88,922,923,924],{},"Semver: ",[33,925,926],{},"MAJOR.MINOR.PATCH",[88,928,719,929,932,933,936],{},[33,930,931],{},"cargo release"," (",[33,934,935],{},"cargo install cargo-release",") to bump, tag, publish.",[88,938,939,940,943,944,318],{},"Set ",[33,941,942],{},"rust-version"," (MSRV) in ",[33,945,946],{},"Cargo.toml",[80,948,950],{"id":949},"publishing","Publishing",[23,952,953],{"language":210},[27,954,956],{"className":213,"code":955,"language":210,"meta":31,"style":31},"cargo login \u003Ctoken>\ncargo publish --dry-run\ncargo publish\n",[33,957,958,977,987],{"__ignoreMap":31},[36,959,960,962,965,968,971,974],{"class":38,"line":39},[36,961,221],{"class":171},[36,963,964],{"class":159}," login",[36,966,967],{"class":155}," \u003C",[36,969,970],{"class":159},"toke",[36,972,973],{"class":151},"n",[36,975,976],{"class":155},">\n",[36,978,979,981,984],{"class":38,"line":45},[36,980,221],{"class":171},[36,982,983],{"class":159}," publish",[36,985,986],{"class":227}," --dry-run\n",[36,988,989,991],{"class":38,"line":51},[36,990,221],{"class":171},[36,992,993],{"class":159}," publish\n",[85,995,996,999,1005],{},[88,997,998],{},"Crates.io is the public registry.",[88,1000,1001,1004],{},[33,1002,1003],{},"publish = false"," to prevent accidental publication.",[88,1006,1007],{},"Documentation is auto-built on docs.rs.",[80,1009,1011],{"id":1010},"changelog","Changelog",[14,1013,719,1014,260,1016,1019,1020,1023,1024,318],{},[33,1015,931],{},[33,1017,1018],{},"git-cliff",", or ",[33,1021,1022],{},"changesets"," to generate from commits\u002FPRs. Conventional Commits format works well with ",[33,1025,1018],{},[18,1027,1029],{"id":1028},"ci-github-actions","CI (GitHub Actions)",[23,1031,1033],{"language":1032},"yaml",[27,1034,1037],{"className":1035,"code":1036,"language":1032,"meta":31,"style":31},"language-yaml shiki shiki-themes github-light github-dark","name: CI\non: [push, pull_request]\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        rust: [stable, beta, nightly]\n        os: [ubuntu-latest, windows-latest, macos-latest]\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: dtolnay\u002Frust-toolchain@master\n        with: { toolchain: ${{ matrix.rust }}, components: clippy, rustfmt }\n      - run: cargo fmt -- --check\n      - run: cargo clippy --all-targets -- -D warnings\n      - run: cargo test --all-features\n      - run: cargo doc --no-deps\n",[33,1038,1039,1050,1069,1077,1084,1094,1101,1108,1130,1152,1159,1172,1183,1224,1236,1247,1258],{"__ignoreMap":31},[36,1040,1041,1045,1047],{"class":38,"line":39},[36,1042,1044],{"class":1043},"sk71V","name",[36,1046,311],{"class":151},[36,1048,1049],{"class":159},"CI\n",[36,1051,1052,1055,1058,1061,1063,1066],{"class":38,"line":45},[36,1053,1054],{"class":227},"on",[36,1056,1057],{"class":151},": [",[36,1059,1060],{"class":159},"push",[36,1062,260],{"class":151},[36,1064,1065],{"class":159},"pull_request",[36,1067,1068],{"class":151},"]\n",[36,1070,1071,1074],{"class":38,"line":51},[36,1072,1073],{"class":1043},"jobs",[36,1075,1076],{"class":151},":\n",[36,1078,1079,1082],{"class":38,"line":57},[36,1080,1081],{"class":1043},"  test",[36,1083,1076],{"class":151},[36,1085,1086,1089,1091],{"class":38,"line":63},[36,1087,1088],{"class":1043},"    runs-on",[36,1090,311],{"class":151},[36,1092,1093],{"class":159},"ubuntu-latest\n",[36,1095,1096,1099],{"class":38,"line":69},[36,1097,1098],{"class":1043},"    strategy",[36,1100,1076],{"class":151},[36,1102,1103,1106],{"class":38,"line":75},[36,1104,1105],{"class":1043},"      matrix",[36,1107,1076],{"class":151},[36,1109,1110,1113,1115,1118,1120,1123,1125,1128],{"class":38,"line":389},[36,1111,1112],{"class":1043},"        rust",[36,1114,1057],{"class":151},[36,1116,1117],{"class":159},"stable",[36,1119,260],{"class":151},[36,1121,1122],{"class":159},"beta",[36,1124,260],{"class":151},[36,1126,1127],{"class":159},"nightly",[36,1129,1068],{"class":151},[36,1131,1132,1135,1137,1140,1142,1145,1147,1150],{"class":38,"line":395},[36,1133,1134],{"class":1043},"        os",[36,1136,1057],{"class":151},[36,1138,1139],{"class":159},"ubuntu-latest",[36,1141,260],{"class":151},[36,1143,1144],{"class":159},"windows-latest",[36,1146,260],{"class":151},[36,1148,1149],{"class":159},"macos-latest",[36,1151,1068],{"class":151},[36,1153,1154,1157],{"class":38,"line":401},[36,1155,1156],{"class":1043},"    steps",[36,1158,1076],{"class":151},[36,1160,1161,1164,1167,1169],{"class":38,"line":407},[36,1162,1163],{"class":151},"      - ",[36,1165,1166],{"class":1043},"uses",[36,1168,311],{"class":151},[36,1170,1171],{"class":159},"actions\u002Fcheckout@v4\n",[36,1173,1174,1176,1178,1180],{"class":38,"line":413},[36,1175,1163],{"class":151},[36,1177,1166],{"class":1043},[36,1179,311],{"class":151},[36,1181,1182],{"class":159},"dtolnay\u002Frust-toolchain@master\n",[36,1184,1185,1188,1191,1194,1196,1199,1202,1205,1208,1211,1213,1216,1218,1221],{"class":38,"line":419},[36,1186,1187],{"class":1043},"        with",[36,1189,1190],{"class":151},": { ",[36,1192,1193],{"class":1043},"toolchain",[36,1195,311],{"class":151},[36,1197,1198],{"class":159},"$",[36,1200,1201],{"class":151},"{{ ",[36,1203,1204],{"class":159},"matrix.rust",[36,1206,1207],{"class":151}," }}, ",[36,1209,1210],{"class":1043},"components",[36,1212,311],{"class":151},[36,1214,1215],{"class":159},"clippy",[36,1217,260],{"class":151},[36,1219,1220],{"class":159},"rustfmt",[36,1222,1223],{"class":151}," }\n",[36,1225,1226,1228,1231,1233],{"class":38,"line":425},[36,1227,1163],{"class":151},[36,1229,1230],{"class":1043},"run",[36,1232,311],{"class":151},[36,1234,1235],{"class":159},"cargo fmt -- --check\n",[36,1237,1238,1240,1242,1244],{"class":38,"line":431},[36,1239,1163],{"class":151},[36,1241,1230],{"class":1043},[36,1243,311],{"class":151},[36,1245,1246],{"class":159},"cargo clippy --all-targets -- -D warnings\n",[36,1248,1249,1251,1253,1255],{"class":38,"line":436},[36,1250,1163],{"class":151},[36,1252,1230],{"class":1043},[36,1254,311],{"class":151},[36,1256,1257],{"class":159},"cargo test --all-features\n",[36,1259,1260,1262,1264,1266],{"class":38,"line":442},[36,1261,1163],{"class":151},[36,1263,1230],{"class":1043},[36,1265,311],{"class":151},[36,1267,1268],{"class":159},"cargo doc --no-deps\n",[14,1270,1271,1272,260,1275,1278,1279,1282],{},"Add ",[33,1273,1274],{},"cargo-deny",[33,1276,1277],{},"cargo-audit"," for security. Use ",[33,1280,1281],{},"cargo nextest run"," for faster test execution.",[18,1284,1286],{"id":1285},"cross-compilation","Cross-Compilation",[23,1288,1289],{"language":210},[27,1290,1292],{"className":213,"code":1291,"language":210,"meta":31,"style":31},"rustup target add x86_64-unknown-linux-musl\ncargo build --target x86_64-unknown-linux-musl\n",[33,1293,1294,1308],{"__ignoreMap":31},[36,1295,1296,1299,1302,1305],{"class":38,"line":39},[36,1297,1298],{"class":171},"rustup",[36,1300,1301],{"class":159}," target",[36,1303,1304],{"class":159}," add",[36,1306,1307],{"class":159}," x86_64-unknown-linux-musl\n",[36,1309,1310,1312,1314,1317],{"class":38,"line":45},[36,1311,221],{"class":171},[36,1313,224],{"class":159},[36,1315,1316],{"class":227}," --target",[36,1318,1307],{"class":159},[14,1320,1321,1322,1325],{},"For cross-platform, ",[33,1323,1324],{},"cross"," (Docker-based) is the easiest:",[23,1327,1328],{"language":210},[27,1329,1331],{"className":213,"code":1330,"language":210,"meta":31,"style":31},"cargo install cross\ncross build --target aarch64-unknown-linux-gnu\n",[33,1332,1333,1343],{"__ignoreMap":31},[36,1334,1335,1337,1340],{"class":38,"line":39},[36,1336,221],{"class":171},[36,1338,1339],{"class":159}," install",[36,1341,1342],{"class":159}," cross\n",[36,1344,1345,1347,1349,1351],{"class":38,"line":45},[36,1346,1324],{"class":171},[36,1348,224],{"class":159},[36,1350,1316],{"class":227},[36,1352,1353],{"class":159}," aarch64-unknown-linux-gnu\n",[14,1355,1356,1359],{},[33,1357,1358],{},"cargo-zigbuild"," uses Zig as a cross-linker (good for musl and Windows targets from Linux).",[18,1361,1363],{"id":1362},"binary-distribution","Binary Distribution",[85,1365,1366,1373,1387],{},[88,1367,1368,1369,1372],{},"Static linking with ",[33,1370,1371],{},"musl"," for portable Linux binaries.",[88,1374,1375,1376,1379,1380,1383,1384,318],{},"Universal binaries on macOS: build for both ",[33,1377,1378],{},"x86_64-apple-darwin"," and ",[33,1381,1382],{},"aarch64-apple-darwin",", combine with ",[33,1385,1386],{},"lipo",[88,1388,1389,1390,1393,1394,1397],{},"Windows: ",[33,1391,1392],{},"cargo build --target x86_64-pc-windows-gnu"," for portable static binaries (or use ",[33,1395,1396],{},"cargo-wix"," for MSI installers).",[18,1399,1401],{"id":1400},"workspace-releases","Workspace Releases",[14,1403,1404,1405,1407],{},"For multi-crate workspaces, ",[33,1406,931],{}," handles inter-crate version bumps and dependency updates.",[18,1409,1411],{"id":1410},"msrv","MSRV",[23,1413,1414],{"language":25},[27,1415,1417],{"className":29,"code":1416,"language":25,"meta":31,"style":31},"[package]\nrust-version = \"1.75\"\n",[33,1418,1419,1424],{"__ignoreMap":31},[36,1420,1421],{"class":38,"line":39},[36,1422,1423],{},"[package]\n",[36,1425,1426],{"class":38,"line":45},[36,1427,1428],{},"rust-version = \"1.75\"\n",[14,1430,1431],{},"CI must test with that version:",[23,1433,1434],{"language":1032},[27,1435,1437],{"className":1035,"code":1436,"language":1032,"meta":31,"style":31},"- run: rustup install 1.75\n- run: rustup override set 1.75\n- run: cargo build\n",[33,1438,1439,1451,1462],{"__ignoreMap":31},[36,1440,1441,1444,1446,1448],{"class":38,"line":39},[36,1442,1443],{"class":151},"- ",[36,1445,1230],{"class":1043},[36,1447,311],{"class":151},[36,1449,1450],{"class":159},"rustup install 1.75\n",[36,1452,1453,1455,1457,1459],{"class":38,"line":45},[36,1454,1443],{"class":151},[36,1456,1230],{"class":1043},[36,1458,311],{"class":151},[36,1460,1461],{"class":159},"rustup override set 1.75\n",[36,1463,1464,1466,1468,1470],{"class":38,"line":51},[36,1465,1443],{"class":151},[36,1467,1230],{"class":1043},[36,1469,311],{"class":151},[36,1471,1472],{"class":159},"cargo build\n",[18,1474,1476],{"id":1475},"edge-cases","Edge Cases",[85,1478,1479,1496,1508,1519,1531,1540],{},[88,1480,1481,1484,1485,1488,1489,1491,1492,1495],{},[279,1482,1483],{},"Feature unification breaking builds",": if your crate's ",[33,1486,1487],{},"cfg(feature = \"x\")"," only makes sense with another crate's feature, you can't express that without ",[33,1490,132],{},"\u002F",[33,1493,1494],{},"?dep\u002Ffeat"," syntax.",[88,1497,1498,1503,1504,1507],{},[279,1499,1500,1501],{},"Optional dep without ",[33,1502,132],{}," creates an implicit feature of the same name; sometimes you want this (so users can ",[33,1505,1506],{},"features = [\"serde_json\"]","), sometimes you don't.",[88,1509,1510,1515,1516,318],{},[279,1511,1512],{},[33,1513,1514],{},"cargo build --features \"\""," is sometimes needed to override ",[33,1517,1518],{},"default-features",[88,1520,1521,1526,1527,1530],{},[279,1522,1523,1525],{},[33,1524,585],{}," and feature interaction",": read ",[33,1528,1529],{},"CARGO_FEATURE_*"," env vars in build scripts.",[88,1532,1533,1536,1537,1539],{},[279,1534,1535],{},"Profile inheritance",": a custom profile that doesn't ",[33,1538,492],{}," from another starts empty (potentially wrong optimization).",[88,1541,1542,1546,1547,723,1549,1551],{},[279,1543,1544],{},[33,1545,569],{}," can be slower at runtime than ",[33,1548,573],{},[33,1550,577],{}," despite smaller binaries.",[18,1553,1555],{"id":1554},"summary","Summary",[14,1557,1558,1559,1379,1561,1563,1564,1566,1567,1569],{},"Features are additive conditional-compilation flags. Design them additive-only. Use ",[33,1560,132],{},[33,1562,1494],{}," for clean dep\u002Ffeature separation. Profiles control optimization and binary properties. ",[33,1565,585],{}," enables codegen and linking. CI should run fmt\u002Fclippy\u002Ftest\u002Fdoc and cross-compile. Use ",[33,1568,931],{}," for versioning and publishing. Set and test the MSRV.",[14,1571,1572],{},"Next: The deeper type system — variance, HRTBs, and tricky generics.",[1574,1575,1576],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .sk71V, html code.shiki .sk71V{--shiki-default:#22863A;--shiki-github-dark:#85E89D}",{"title":31,"searchDepth":45,"depth":45,"links":1578},[1579,1583,1584,1587,1588,1592,1594,1596,1605,1606,1607,1608,1609,1610,1611],{"id":20,"depth":45,"text":21,"children":1580},[1581,1582],{"id":82,"depth":51,"text":83},{"id":108,"depth":51,"text":109},{"id":136,"depth":45,"text":137},{"id":252,"depth":45,"text":253,"children":1585},[1586],{"id":295,"depth":51,"text":296},{"id":302,"depth":45,"text":303},{"id":344,"depth":45,"text":345,"children":1589},[1590,1591],{"id":492,"depth":51,"text":492},{"id":530,"depth":51,"text":531},{"id":581,"depth":45,"text":1593},"Build Scripts (build.rs)",{"id":730,"depth":45,"text":1595},"links Key",{"id":766,"depth":45,"text":767,"children":1597},[1598,1599,1600,1601,1602,1603,1604],{"id":770,"depth":51,"text":771},{"id":808,"depth":51,"text":809},{"id":842,"depth":51,"text":843},{"id":883,"depth":51,"text":884},{"id":917,"depth":51,"text":918},{"id":949,"depth":51,"text":950},{"id":1010,"depth":51,"text":1011},{"id":1028,"depth":45,"text":1029},{"id":1285,"depth":45,"text":1286},{"id":1362,"depth":45,"text":1363},{"id":1400,"depth":45,"text":1401},{"id":1410,"depth":45,"text":1411},{"id":1475,"depth":45,"text":1476},{"id":1554,"depth":45,"text":1555},"md",{},"\u002Frust\u002F28-cargo-features",{"title":5,"description":16},"rust\u002F28-cargo-features","RirtX1CdWQoJXAvv6lkC7U7m7HEgrAw9m4FgeYdF_o8",1785944093275]