diff --git a/crate2nix/Cargo.nix b/crate2nix/Cargo.nix index 21209692..9ce144e7 100644 --- a/crate2nix/Cargo.nix +++ b/crate2nix/Cargo.nix @@ -109,6 +109,7 @@ rec { crateName = "ansi_term"; version = "0.11.0"; edition = "2015"; + crateBin = []; sha256 = "16wpvrghvd0353584i1idnsgm0r3vchg8fyrm0x8ayv1rgvbljgf"; authors = [ "ogham@bsago.me" @@ -129,6 +130,7 @@ rec { crateName = "anyhow"; version = "1.0.41"; edition = "2018"; + crateBin = []; sha256 = "0qaa0vgsa7ybq7wqk57508l52l1lr3sbx49vk9hf43w9yql2dbqm"; authors = [ "David Tolnay " @@ -143,6 +145,7 @@ rec { crateName = "atty"; version = "0.2.14"; edition = "2015"; + crateBin = []; sha256 = "1s7yslcs6a28c5vz7jwj63lkfgyx8mx99fdirlhi9lbhhzhrpcyr"; authors = [ "softprops " @@ -229,6 +232,7 @@ rec { crateName = "bstr"; version = "0.2.16"; edition = "2018"; + crateBin = []; sha256 = "0y8jy9kcqn1myzxjx7c73rbv4amfw08n936ycqz3glrsc66jqs4h"; authors = [ "Andrew Gallant " @@ -266,6 +270,7 @@ rec { crateName = "byteorder"; version = "1.4.3"; edition = "2018"; + crateBin = []; sha256 = "0456lv9xi1a5bcm32arknf33ikv76p3fr9yzki4lb2897p2qkh8l"; authors = [ "Andrew Gallant " @@ -278,6 +283,7 @@ rec { crateName = "camino"; version = "1.0.4"; edition = "2018"; + crateBin = []; sha256 = "1a91b5i4n6ikg7p5pgvj3hjac1gnwjmdqsi3k83al2d701nqqr6l"; authors = [ "Without Boats " @@ -303,6 +309,7 @@ rec { crateName = "cargo-platform"; version = "0.1.1"; edition = "2018"; + crateBin = []; sha256 = "1mzi60pf0z83qkzqp7jwd61xnqz2b5ydsj7rnnikbgyicd5989h2"; authors = [ "The Cargo Project Developers" @@ -320,6 +327,7 @@ rec { crateName = "cargo_metadata"; version = "0.14.0"; edition = "2018"; + crateBin = []; sha256 = "16hhak3gips08lqp0x7s9wnfm139hy0a3nm0k4pman7m6lqvv5y2"; authors = [ "Oliver Schneider " @@ -360,6 +368,7 @@ rec { crateName = "cfg-if"; version = "1.0.0"; edition = "2018"; + crateBin = []; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; authors = [ "Alex Crichton " @@ -435,6 +444,7 @@ rec { crateName = "colored-diff"; version = "0.2.2"; edition = "2015"; + crateBin = []; sha256 = "1zbfjkp7w1wjcxb1p19dd21mn9xkj6nr2s5pav8b16whzh52cvsi"; authors = [ "Christopher Durham " @@ -464,6 +474,21 @@ rec { { name = "crate2nix"; path = "src/main.rs"; + kind = "bin"; + test = true; + # TODO (when cargo merges metadata): + # harness + # bench + requiredFeatures = [ ]; + } + { + name = "self_build_up_to_date"; + path = "tests/self_build_up_to_date.rs"; + kind = "test"; + test = true; + # TODO (when cargo merges metadata): + # harness + # bench requiredFeatures = [ ]; } ]; @@ -565,6 +590,7 @@ rec { crateName = "crossbeam-utils"; version = "0.8.8"; edition = "2018"; + crateBin = []; sha256 = "0f6b3xrbyc3yx0qa1digmy48mxmh58359kv34qy6ws5p433j9w8b"; dependencies = [ { @@ -660,6 +686,7 @@ rec { crateName = "fs_extra"; version = "1.2.0"; edition = "2015"; + crateBin = []; sha256 = "151k6dr35mhq5d8pc8krhw55ajhkyiv0pm14s7zzlc5bc9fp28i0"; authors = [ "Denis Kurilenko " @@ -680,6 +707,7 @@ rec { crateName = "generic-array"; version = "0.12.4"; edition = "2015"; + crateBin = []; sha256 = "1gfpay78vijl9vrwl1k9v7fbvbhkhcmnrk4kfg9l6x24y4s9zpzz"; libName = "generic_array"; authors = [ @@ -700,6 +728,7 @@ rec { crateName = "globset"; version = "0.4.8"; edition = "2018"; + crateBin = []; sha256 = "1gdzphnjjc0wdaawsq3n1nnypv9ja4prhca2n66hcahay2gksihh"; authors = [ "Andrew Gallant " @@ -739,6 +768,7 @@ rec { crateName = "globwalk"; version = "0.8.1"; edition = "2015"; + crateBin = []; sha256 = "1k6xwkydr7igvwjn3xkwjywk4213lcs53f576ilqz1h84jaazqwk"; authors = [ "Gilad Naaman " @@ -801,6 +831,7 @@ rec { crateName = "hex"; version = "0.4.3"; edition = "2018"; + crateBin = []; sha256 = "0w1a4davm1lgzpamwnba907aysmlrnygbqmfis2mqjx5m552a93z"; authors = [ "KokaKiwi " @@ -816,6 +847,7 @@ rec { crateName = "idna"; version = "0.1.5"; edition = "2015"; + crateBin = []; sha256 = "0kl4gs5kaydn4v07c6ka33spm9qdh2np0x7iw7g5zd8z1c7rxw1q"; authors = [ "The rust-url developers" @@ -840,6 +872,7 @@ rec { crateName = "ignore"; version = "0.4.18"; edition = "2018"; + crateBin = []; sha256 = "07bmnv96msggqb040z6xqp1p7s8ys0f97b731hp6mybkjc9ingvi"; authors = [ "Andrew Gallant " @@ -895,6 +928,7 @@ rec { crateName = "itertools"; version = "0.7.11"; edition = "2015"; + crateBin = []; sha256 = "03cpsj26xmyamcalclqzr1i700vwx8hnbgxbpjvs354f8mnr8iqd"; authors = [ "bluss" @@ -914,6 +948,7 @@ rec { crateName = "itertools"; version = "0.9.0"; edition = "2018"; + crateBin = []; sha256 = "0jyml7ygr7kijkcjdl3fk5f34y5h5jsavclim7l13zjiavw1hkr8"; authors = [ "bluss" @@ -934,6 +969,7 @@ rec { crateName = "itoa"; version = "0.4.7"; edition = "2015"; + crateBin = []; sha256 = "0di7fggbknwfjcw8cgzm1dnm3ik32l2m1f7nmyh8ipmh45h069fx"; authors = [ "David Tolnay " @@ -946,6 +982,7 @@ rec { crateName = "lazy_static"; version = "1.4.0"; edition = "2015"; + crateBin = []; sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; authors = [ "Marvin Löbel " @@ -959,6 +996,7 @@ rec { crateName = "libc"; version = "0.2.98"; edition = "2015"; + crateBin = []; sha256 = "144728k6d98k3hplzklqn18a134nq6nw0jzdxy1s98sx2xvzw31j"; authors = [ "The Rust Project Developers" @@ -975,6 +1013,7 @@ rec { crateName = "log"; version = "0.4.14"; edition = "2015"; + crateBin = []; sha256 = "04175hv0v62shd82qydq58a48k3bjijmk54v38zgqlbxqkkbpfai"; authors = [ "The Rust Project Developers" @@ -999,6 +1038,7 @@ rec { crateName = "maplit"; version = "1.0.2"; edition = "2015"; + crateBin = []; sha256 = "07b5kjnhrrmfhgqm9wprjw8adx6i225lqp49gasgqg74lahnabiy"; authors = [ "bluss" @@ -1009,6 +1049,7 @@ rec { crateName = "matches"; version = "0.1.8"; edition = "2015"; + crateBin = []; sha256 = "020axl4q7rk9vz90phs7f8jas4imxal9y9kxl4z4v7a6719mrz3z"; libPath = "lib.rs"; authors = [ @@ -1046,6 +1087,7 @@ rec { crateName = "once_cell"; version = "1.8.0"; edition = "2018"; + crateBin = []; sha256 = "0mkbbxg6416z11r2yzsq91cqrkj9w1iyx5hakq15h5sbnriwnbv9"; authors = [ "Aleksey Kladov " @@ -1093,6 +1135,7 @@ rec { crateName = "pest"; version = "2.1.3"; edition = "2015"; + crateBin = []; sha256 = "0lry80bm90x47nq71wxq83kjrm9ashpz4kbm92p90ysdx4m8gx0h"; authors = [ "Dragoș Tiselice " @@ -1113,6 +1156,7 @@ rec { crateName = "pest_derive"; version = "2.1.0"; edition = "2015"; + crateBin = []; sha256 = "1l5jfa6ril71cw5nsiw0r45br54dd8cj2r1nc2d1wq6wb3jilgc3"; procMacro = true; authors = [ @@ -1193,6 +1237,7 @@ rec { crateName = "proc-macro-error"; version = "1.0.4"; edition = "2018"; + crateBin = []; sha256 = "1373bhxaf0pagd8zkyd03kkx6bchzf6g0dkwrwzsnal9z47lj9fs"; authors = [ "CreepySkeleton " @@ -1261,6 +1306,7 @@ rec { crateName = "proc-macro2"; version = "1.0.27"; edition = "2018"; + crateBin = []; sha256 = "0f3h0zl5w5090ajmmvpmhkpr4iwqnn5rip3afacabhc657vwmn7h"; authors = [ "Alex Crichton " @@ -1281,6 +1327,7 @@ rec { crateName = "quote"; version = "1.0.9"; edition = "2018"; + crateBin = []; sha256 = "19rjmfqzk26rxbgxy5j2ckqc2v12sw2xw8l4gi8bzpn2bmsbkl63"; authors = [ "David Tolnay " @@ -1302,6 +1349,7 @@ rec { crateName = "rand"; version = "0.4.6"; edition = "2015"; + crateBin = []; sha256 = "14qjfv3gggzhnma20k0sc1jf8y6pplsaq7n1j9ls5c8kf2wl0a2m"; authors = [ "The Rust Project Developers" @@ -1386,6 +1434,7 @@ rec { crateName = "rdrand"; version = "0.4.0"; edition = "2015"; + crateBin = []; sha256 = "1cjq0kwx1bk7jx3kzyciiish5gqsj7620dm43dc52sr8fzmm9037"; authors = [ "Simonas Kazlauskas " @@ -1406,6 +1455,7 @@ rec { crateName = "regex"; version = "1.5.6"; edition = "2018"; + crateBin = []; sha256 = "1wczbykw6fas7359j9lhkkv13dplhiphzrf2ii6dmg5xjiyi4gyq"; authors = [ "The Rust Project Developers" @@ -1450,6 +1500,7 @@ rec { crateName = "regex-syntax"; version = "0.6.26"; edition = "2018"; + crateBin = []; sha256 = "0r6vplrklxq7yx7x4zqf04apr699swbsn6ipv8bk82nwqngdxcs9"; authors = [ "The Rust Project Developers" @@ -1482,6 +1533,7 @@ rec { crateName = "ryu"; version = "1.0.5"; edition = "2018"; + crateBin = []; sha256 = "0vpqv1dj7fksa6hm3zpk5rbsjs0ifbfy7xwzsyyil0rx37a03lvi"; authors = [ "David Tolnay " @@ -1494,6 +1546,7 @@ rec { crateName = "same-file"; version = "1.0.6"; edition = "2018"; + crateBin = []; sha256 = "00h5j1w87dmhnvbv9l8bic3y7xxsnjmssvifw2ayvgx9mb1ivz4k"; authors = [ "Andrew Gallant " @@ -1511,6 +1564,7 @@ rec { crateName = "semver"; version = "1.0.3"; edition = "2018"; + crateBin = []; sha256 = "1gna1p10i86sf1pqfqndkwl0wks35x84yvjw77c74ckzxrbsqfjz"; authors = [ "David Tolnay " @@ -1624,6 +1678,7 @@ rec { crateName = "sha-1"; version = "0.8.2"; edition = "2015"; + crateBin = []; sha256 = "1pv387q0r7llk2cqzyq0nivzvkgqgzsiygqzlv7b68z9xl5lvngp"; libName = "sha1"; authors = [ @@ -1667,6 +1722,7 @@ rec { crateName = "strsim"; version = "0.8.0"; edition = "2015"; + crateBin = []; sha256 = "0sjsm7hrvjdifz661pjxq5w4hf190hx53fra8dfvamacvff139cf"; authors = [ "Danny Guo " @@ -1677,6 +1733,7 @@ rec { crateName = "structopt"; version = "0.3.22"; edition = "2018"; + crateBin = []; sha256 = "0wadrsmkvab04dkbs670hcyl41l89kj7nvky6356l8k7rg6l3c39"; authors = [ "Guillaume Pinot " @@ -1751,6 +1808,7 @@ rec { crateName = "syn"; version = "1.0.73"; edition = "2018"; + crateBin = []; sha256 = "1ixw4lscc7009ibaic8g5bvnc94hdcr62ksjk3jjl38363zqj57p"; authors = [ "David Tolnay " @@ -1785,6 +1843,7 @@ rec { crateName = "tempdir"; version = "0.3.7"; edition = "2015"; + crateBin = []; sha256 = "1n5n86zxpgd85y0mswrp5cfdisizq2rv3la906g6ipyc03xvbwhm"; authors = [ "The Rust Project Developers" @@ -1859,6 +1918,7 @@ rec { crateName = "textwrap"; version = "0.11.0"; edition = "2015"; + crateBin = []; sha256 = "0q5hky03ik3y50s9sz25r438bc4nwhqc6dqwynv4wylc807n29nk"; authors = [ "Martin Geisler " @@ -1878,6 +1938,7 @@ rec { crateName = "thread_local"; version = "1.1.4"; edition = "2018"; + crateBin = []; sha256 = "1001bvz6a688wf3izcrh3jqrkiqaarf44wf08azm071ig1xw45jm"; authors = [ "Amanieu d'Antras " @@ -1896,6 +1957,7 @@ rec { crateName = "tinyvec"; version = "1.2.0"; edition = "2018"; + crateBin = []; sha256 = "0hn3fkpb9nca9nf9znz2dxlp4ccv37hnbh67aczpzpmpbgq20ljv"; authors = [ "Lokathor " @@ -1928,6 +1990,7 @@ rec { crateName = "toml"; version = "0.5.8"; edition = "2018"; + crateBin = []; sha256 = "1apcmjrrjw429pjw7mqlmdwwd67g8305vwqy4kw3swr612bl44d3"; authors = [ "Alex Crichton " @@ -1948,6 +2011,7 @@ rec { crateName = "typenum"; version = "1.13.0"; edition = "2018"; + crateBin = []; sha256 = "01lbbspn4080yg8wp6y7q3xcqih1c1dmkkx4pwax4z1a9436k7w7"; build = "build/main.rs"; authors = [ @@ -1961,6 +2025,7 @@ rec { crateName = "ucd-trie"; version = "0.1.3"; edition = "2018"; + crateBin = []; sha256 = "072cblf8v3wzyaz3lhbpzgil4s03dpzg1ppy3gqx2l4v622y3pjn"; authors = [ "Andrew Gallant " @@ -1974,6 +2039,7 @@ rec { crateName = "unic-char-property"; version = "0.9.0"; edition = "2018"; + crateBin = []; sha256 = "08g21dn3wwix3ycfl0vrbahn0835nv2q3swm8wms0vwvgm07mid8"; authors = [ "The UNIC Project Developers" @@ -1990,6 +2056,7 @@ rec { crateName = "unic-char-range"; version = "0.9.0"; edition = "2018"; + crateBin = []; sha256 = "1g0z7iwvjhqspi6194zsff8vy6i3921hpqcrp3v1813hbwnh5603"; authors = [ "The UNIC Project Developers" @@ -2016,6 +2083,7 @@ rec { crateName = "unic-segment"; version = "0.9.0"; edition = "2018"; + crateBin = []; sha256 = "08wgz2q6vrdvmbd23kf9pbg8cyzm5q8hq9spc4blzy2ppqk5vvg4"; authors = [ "The UNIC Project Developers" @@ -2032,6 +2100,7 @@ rec { crateName = "unic-ucd-segment"; version = "0.9.0"; edition = "2018"; + crateBin = []; sha256 = "0027lczcg0r401g6fnzm2bq9fxhgxvri1nlryhhv8192lqic2y90"; authors = [ "The UNIC Project Developers" @@ -2056,6 +2125,7 @@ rec { crateName = "unic-ucd-version"; version = "0.9.0"; edition = "2018"; + crateBin = []; sha256 = "1i5hnzpfnxkp4ijfk8kvhpvj84bij575ybqx1b6hyigy6wi2zgcn"; authors = [ "The UNIC Project Developers" @@ -2096,6 +2166,7 @@ rec { crateName = "unicode-normalization"; version = "0.1.19"; edition = "2018"; + crateBin = []; sha256 = "1yabhmg8zlcksda3ajly9hpbzqgbhknxwch8dwkfkaa1569r0ifm"; authors = [ "kwantam " @@ -2117,6 +2188,7 @@ rec { crateName = "unicode-segmentation"; version = "1.8.0"; edition = "2018"; + crateBin = []; sha256 = "0nrqfgxkh00wb5dhl0874z20789i2yjimp6ndgh4ay4yjjd895c8"; authors = [ "kwantam " @@ -2146,6 +2218,7 @@ rec { crateName = "unicode-xid"; version = "0.2.2"; edition = "2015"; + crateBin = []; sha256 = "1wrkgcw557v311dkdb6n2hrix9dm2qdsb1zpw7pn79l03zb85jwc"; authors = [ "erick.tryzelaar " @@ -2160,6 +2233,7 @@ rec { crateName = "url"; version = "1.7.2"; edition = "2015"; + crateBin = []; sha256 = "0nim1c90mxpi9wgdw2xh8dqd72vlklwlzam436akcrhjac6pqknx"; authors = [ "The rust-url developers" @@ -2422,112 +2496,34 @@ rec { || baseName == "tests.nix" ); - /* Returns a crate which depends on successful test execution - of crate given as the second argument. - - testCrateFlags: list of flags to pass to the test exectuable - testInputs: list of packages that should be available during test execution - */ - crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: - assert builtins.typeOf testCrateFlags == "list"; - assert builtins.typeOf testInputs == "list"; - assert builtins.typeOf testPreRun == "string"; - assert builtins.typeOf testPostRun == "string"; - let - # override the `crate` so that it will build and execute tests instead of - # building the actual lib and bin targets We just have to pass `--test` - # to rustc and it will do the right thing. We execute the tests and copy - # their log and the test executables to $out for later inspection. - test = - let - drv = testCrate.override - ( - _: { - buildTests = true; - } - ); - # If the user hasn't set any pre/post commands, we don't want to - # insert empty lines. This means that any existing users of crate2nix - # don't get a spurious rebuild unless they set these explicitly. - testCommand = pkgs.lib.concatStringsSep "\n" - (pkgs.lib.filter (s: s != "") [ - testPreRun - "$f $testCrateFlags 2>&1 | tee -a $out" - testPostRun - ]); - in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -ex - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - ${pkgs.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; - in - pkgs.runCommand "${crate.name}-linked" - { - inherit (crate) outputs crateName; - passthru = (crate.passthru or { }) // { - inherit test; - }; - } '' - echo tested by ${test} - ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} - ''; - /* A restricted overridable version of builtRustCratesWithFeatures. */ buildRustCrateWithFeatures = { packageId , features ? rootFeatures , crateOverrides ? defaultCrateOverrides , buildRustCrateForPkgsFunc ? null - , runTests ? false - , testCrateFlags ? [ ] - , testInputs ? [ ] - # Any command to run immediatelly before a test is executed. - , testPreRun ? "" - # Any command run immediatelly after a test is executed. - , testPostRun ? "" + # Available: [ "lib" "bin" ] or ["test" "bench" "example"] + , buildKinds ? [ "lib" "bin" ] }: lib.makeOverridable ( { features , crateOverrides - , runTests - , testCrateFlags - , testInputs - , testPreRun - , testPostRun + , buildKinds }: let + isDevBuild = + let + inherit (pkgs.buildRustCrateHelpers.kinds) isLib isBin isExample isTest isBench; + + notDev = builtins.any (k: isLib k || isBin k) buildKinds; + isDev = builtins.any (k: isBench k || isExample k || isTest k) buildKinds; + in + assert (buildKinds != [ ]); + # Can't have build dev and non dev kinds + assert (notDev != isDev); + isDev; + buildRustCrateForPkgsFuncOverriden = if buildRustCrateForPkgsFunc != null then buildRustCrateForPkgsFunc @@ -2540,31 +2536,16 @@ rec { defaultCrateOverrides = crateOverrides; } ); + builtRustCrates = builtRustCratesWithFeatures { - inherit packageId features; + inherit packageId features buildKinds isDevBuild; buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = false; }; - builtTestRustCrates = builtRustCratesWithFeatures { - inherit packageId features; - buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = true; - }; - drv = builtRustCrates.crates.${packageId}; - testDrv = builtTestRustCrates.crates.${packageId}; - derivation = - if runTests then - crateWithTest - { - crate = drv; - testCrate = testDrv; - inherit testCrateFlags testInputs testPreRun testPostRun; - } - else drv; + in - derivation + builtRustCrates.crates.${packageId} ) - { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + { inherit features crateOverrides buildKinds; }; /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc for the corresponding crate. @@ -2574,21 +2555,24 @@ rec { , features , crateConfigs ? crates , buildRustCrateForPkgsFunc - , runTests + , buildKinds + , isDevBuild , makeTarget ? makeDefaultTarget } @ args: assert (builtins.isAttrs crateConfigs); assert (builtins.isString packageId); assert (builtins.isList features); assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); + assert (builtins.isList buildKinds); let rootPackageId = packageId; mergedFeatures = mergePackageFeatures ( args // { inherit rootPackageId; - target = makeTarget stdenv.hostPlatform // { test = runTests; }; + # What does test do for target? + target = makeTarget stdenv.hostPlatform // { test = false; }; } ); # Memoize built packages so that reappearing packages are only built once. @@ -2610,7 +2594,7 @@ rec { builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; devDependencies = lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig'.devDependencies or [ ]); dependencies = dependencyDerivations { @@ -2684,6 +2668,7 @@ rec { } ); extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + buildKinds = if (packageId == rootPackageId) then buildKinds else [ "lib" ]; inherit features dependencies buildDependencies crateRenames release; } ); @@ -2805,7 +2790,7 @@ rec { , featuresByPackageId ? { } , target # Adds devDependencies to the crate with rootPackageId. - , runTests ? false + , isDevBuild ? false , ... } @ args: assert (builtins.isAttrs crateConfigs); @@ -2815,7 +2800,7 @@ rec { assert (builtins.isList dependencyPath); assert (builtins.isAttrs featuresByPackageId); assert (builtins.isAttrs target); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); let crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); expandedFeatures = expandFeatures (crateConfig.features or { }) features; @@ -2850,7 +2835,7 @@ rec { mergePackageFeatures { features = combinedFeatures; featuresByPackageId = cache; - inherit crateConfigs packageId target runTests rootPackageId; + inherit crateConfigs packageId target isDevBuild rootPackageId; } ); cacheWithSelf = @@ -2866,7 +2851,7 @@ rec { ( crateConfig.dependencies or [ ] ++ lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig.devDependencies or [ ]) ); cacheWithAll = diff --git a/crate2nix/src/resolve.rs b/crate2nix/src/resolve.rs index e8ff2c41..b14e984c 100644 --- a/crate2nix/src/resolve.rs +++ b/crate2nix/src/resolve.rs @@ -1,6 +1,6 @@ //! Resolve dependencies and other data for CrateDerivation. - use anyhow::format_err; +use anyhow::Context; use anyhow::Error; use cargo_metadata::Node; use cargo_metadata::Package; @@ -141,11 +141,16 @@ impl CrateDerivation { .iter() .any(|t| t.kind.iter().any(|k| k == "proc-macro")); + // Binaries have one kind: + // https://github.com/rust-lang/cargo/blob/94394ebf2a6b6f1c1d6c160b48865a06e54d5f30/src/cargo/core/manifest.rs#L126 let binaries = package .targets .iter() .filter_map(|t| { - if t.kind.iter().any(|k| k == "bin") { + if t.kind + .iter() + .any(|k| k == "bin" || k == "example" || k == "bench" || k == "test") + { BuildTarget::new(&t, &package_path).ok() } else { None @@ -333,23 +338,33 @@ pub fn double_crate_with_rename() { pub struct BuildTarget { /// The name of the build target. pub name: String, + /// The kind of the build target. + pub kind: String, /// The relative path of the target source file. pub src_path: PathBuf, /// The crate's features that need to be enabled for this target to be compiled. /// Otherwise, this target is ignored. pub required_features: Vec, + /// Whether to test this binary + pub test: bool, } impl BuildTarget { pub fn new(target: &Target, package_path: impl AsRef) -> Result { Ok(BuildTarget { name: target.name.clone(), + kind: target + .kind + .first() + .context("Target shouuld have kind")? + .to_string(), src_path: target .src_path .canonicalize()? .strip_prefix(&package_path)? .to_path_buf(), required_features: target.required_features.clone(), + test: target.test, }) } } diff --git a/crate2nix/templates/Cargo.nix.tera b/crate2nix/templates/Cargo.nix.tera index 893739ed..ff810742 100644 --- a/crate2nix/templates/Cargo.nix.tera +++ b/crate2nix/templates/Cargo.nix.tera @@ -106,6 +106,11 @@ rec { { name = {{ bin.name }}; path = {{ bin.src_path }}; + kind = {{ bin.kind }}; + test = {{ bin.test }}; + # TODO (when cargo merges metadata): + # harness + # bench requiredFeatures = [ {% for feature in bin.required_features %}{{feature}} {% endfor %}]; } {%- endfor %} diff --git a/crate2nix/templates/nix/crate2nix/default.nix b/crate2nix/templates/nix/crate2nix/default.nix index 4eefda8c..3c97ad37 100644 --- a/crate2nix/templates/nix/crate2nix/default.nix +++ b/crate2nix/templates/nix/crate2nix/default.nix @@ -89,112 +89,34 @@ rec { || baseName == "tests.nix" ); - /* Returns a crate which depends on successful test execution - of crate given as the second argument. - - testCrateFlags: list of flags to pass to the test exectuable - testInputs: list of packages that should be available during test execution - */ - crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: - assert builtins.typeOf testCrateFlags == "list"; - assert builtins.typeOf testInputs == "list"; - assert builtins.typeOf testPreRun == "string"; - assert builtins.typeOf testPostRun == "string"; - let - # override the `crate` so that it will build and execute tests instead of - # building the actual lib and bin targets We just have to pass `--test` - # to rustc and it will do the right thing. We execute the tests and copy - # their log and the test executables to $out for later inspection. - test = - let - drv = testCrate.override - ( - _: { - buildTests = true; - } - ); - # If the user hasn't set any pre/post commands, we don't want to - # insert empty lines. This means that any existing users of crate2nix - # don't get a spurious rebuild unless they set these explicitly. - testCommand = pkgs.lib.concatStringsSep "\n" - (pkgs.lib.filter (s: s != "") [ - testPreRun - "$f $testCrateFlags 2>&1 | tee -a $out" - testPostRun - ]); - in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -ex - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - ${pkgs.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; - in - pkgs.runCommand "${crate.name}-linked" - { - inherit (crate) outputs crateName; - passthru = (crate.passthru or { }) // { - inherit test; - }; - } '' - echo tested by ${test} - ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} - ''; - /* A restricted overridable version of builtRustCratesWithFeatures. */ buildRustCrateWithFeatures = { packageId , features ? rootFeatures , crateOverrides ? defaultCrateOverrides , buildRustCrateForPkgsFunc ? null - , runTests ? false - , testCrateFlags ? [ ] - , testInputs ? [ ] - # Any command to run immediatelly before a test is executed. - , testPreRun ? "" - # Any command run immediatelly after a test is executed. - , testPostRun ? "" + # Available: [ "lib" "bin" ] or ["test" "bench" "example"] + , buildKinds ? [ "lib" "bin" ] }: lib.makeOverridable ( { features , crateOverrides - , runTests - , testCrateFlags - , testInputs - , testPreRun - , testPostRun + , buildKinds }: let + isDevBuild = + let + inherit (pkgs.buildRustCrateHelpers.kinds) isLib isBin isExample isTest isBench; + + notDev = builtins.any (k: isLib k || isBin k) buildKinds; + isDev = builtins.any (k: isBench k || isExample k || isTest k) buildKinds; + in + assert (buildKinds != [ ]); + # Can't have build dev and non dev kinds + assert (notDev != isDev); + isDev; + buildRustCrateForPkgsFuncOverriden = if buildRustCrateForPkgsFunc != null then buildRustCrateForPkgsFunc @@ -207,31 +129,16 @@ rec { defaultCrateOverrides = crateOverrides; } ); + builtRustCrates = builtRustCratesWithFeatures { - inherit packageId features; + inherit packageId features buildKinds isDevBuild; buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = false; }; - builtTestRustCrates = builtRustCratesWithFeatures { - inherit packageId features; - buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = true; - }; - drv = builtRustCrates.crates.${packageId}; - testDrv = builtTestRustCrates.crates.${packageId}; - derivation = - if runTests then - crateWithTest - { - crate = drv; - testCrate = testDrv; - inherit testCrateFlags testInputs testPreRun testPostRun; - } - else drv; + in - derivation + builtRustCrates.crates.${packageId} ) - { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + { inherit features crateOverrides buildKinds; }; /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc for the corresponding crate. @@ -241,21 +148,24 @@ rec { , features , crateConfigs ? crates , buildRustCrateForPkgsFunc - , runTests + , buildKinds + , isDevBuild , makeTarget ? makeDefaultTarget } @ args: assert (builtins.isAttrs crateConfigs); assert (builtins.isString packageId); assert (builtins.isList features); assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); + assert (builtins.isList buildKinds); let rootPackageId = packageId; mergedFeatures = mergePackageFeatures ( args // { inherit rootPackageId; - target = makeTarget stdenv.hostPlatform // { test = runTests; }; + # What does test do for target? + target = makeTarget stdenv.hostPlatform // { test = false; }; } ); # Memoize built packages so that reappearing packages are only built once. @@ -277,7 +187,7 @@ rec { builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; devDependencies = lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig'.devDependencies or [ ]); dependencies = dependencyDerivations { @@ -351,6 +261,7 @@ rec { } ); extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + buildKinds = if (packageId == rootPackageId) then buildKinds else [ "lib" ]; inherit features dependencies buildDependencies crateRenames release; } ); @@ -472,7 +383,7 @@ rec { , featuresByPackageId ? { } , target # Adds devDependencies to the crate with rootPackageId. - , runTests ? false + , isDevBuild ? false , ... } @ args: assert (builtins.isAttrs crateConfigs); @@ -482,7 +393,7 @@ rec { assert (builtins.isList dependencyPath); assert (builtins.isAttrs featuresByPackageId); assert (builtins.isAttrs target); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); let crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); expandedFeatures = expandFeatures (crateConfig.features or { }) features; @@ -517,7 +428,7 @@ rec { mergePackageFeatures { features = combinedFeatures; featuresByPackageId = cache; - inherit crateConfigs packageId target runTests rootPackageId; + inherit crateConfigs packageId target isDevBuild rootPackageId; } ); cacheWithSelf = @@ -533,7 +444,7 @@ rec { ( crateConfig.dependencies or [ ] ++ lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig.devDependencies or [ ]) ); cacheWithAll = diff --git a/crate2nix/templates/nix/crate2nix/tests/packageFeatures.nix b/crate2nix/templates/nix/crate2nix/tests/packageFeatures.nix index 9e760bbc..ee786409 100644 --- a/crate2nix/templates/nix/crate2nix/tests/packageFeatures.nix +++ b/crate2nix/templates/nix/crate2nix/tests/packageFeatures.nix @@ -88,7 +88,6 @@ let crate2nix.mergePackageFeatures { target = crate2nix.makeDefaultTarget (stdenv.hostPlatform); - runTests = false; rootPackageId = packageId; inherit crateConfigs packageId features; }; diff --git a/default.nix b/default.nix index 96200a31..95cb11cc 100644 --- a/default.nix +++ b/default.nix @@ -19,9 +19,6 @@ let in !(baseName == "templates" && type == "directory"); crate2nix = cargoNix.rootCrate.build.override { - testCrateFlags = [ - "--skip nix_integration_tests" - ]; crateOverrides = defaultCrateOverrides // { crate2nix = { src, ... }: { src = diff --git a/nix/sources.json b/nix/sources.json index c63711f1..f479a9de 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -48,15 +48,15 @@ "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs": { - "branch": "nixos-unstable", - "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", - "homepage": "https://github.com/NixOS/nixpkgs", - "owner": "NixOS", + "branch": "brc-kinds", + "description": "Nix Packages collection", + "homepage": "", + "owner": "jordanisaacs", "repo": "nixpkgs", - "rev": "0c4800d579af4ed98ecc47d464a5e7b0870c4b1f", - "sha256": "00gx09447gzgxlzwih4hdj51sdg62xanikkgr4bv4y7fpm98qirq", + "rev": "812079dcb5dbbe5f89a02f107b840704f7bcb441", + "sha256": "16p1mh1xvvdnsrfr8ha1310zxvh6yfg0n1yhxs19rvax6c2xw9wv", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/0c4800d579af4ed98ecc47d464a5e7b0870c4b1f.tar.gz", + "url": "https://github.com/jordanisaacs/nixpkgs/archive/812079dcb5dbbe5f89a02f107b840704f7bcb441.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs-mozilla": { diff --git a/sample_projects/bin_with_git_submodule_dep/Cargo.nix b/sample_projects/bin_with_git_submodule_dep/Cargo.nix index a8a06f19..94f4bf9e 100644 --- a/sample_projects/bin_with_git_submodule_dep/Cargo.nix +++ b/sample_projects/bin_with_git_submodule_dep/Cargo.nix @@ -109,6 +109,7 @@ rec { crateName = "ansi_term"; version = "0.11.0"; edition = "2015"; + crateBin = []; sha256 = "16wpvrghvd0353584i1idnsgm0r3vchg8fyrm0x8ayv1rgvbljgf"; authors = [ "ogham@bsago.me" @@ -129,6 +130,7 @@ rec { crateName = "atty"; version = "0.2.13"; edition = "2015"; + crateBin = []; sha256 = "140sswp1bwqwc4zk80bxkbnfb3g936hgrb77g9g0k1zcld3wc0qq"; authors = [ "softprops " @@ -153,6 +155,7 @@ rec { crateName = "backtrace"; version = "0.3.40"; edition = "2018"; + crateBin = []; sha256 = "1skpshz0gszhpmj51p35ci9nf4nmd79s899cfrfs570dgxcpck4j"; authors = [ "The Rust Project Developers" @@ -234,6 +237,11 @@ rec { { name = "bin_with_git_submodule_dep"; path = "src/main.rs"; + kind = "bin"; + test = true; + # TODO (when cargo merges metadata): + # harness + # bench requiredFeatures = [ ]; } ]; @@ -367,6 +375,7 @@ rec { crateName = "byteorder"; version = "1.3.2"; edition = "2015"; + crateBin = []; sha256 = "1xbwjlmq2ziqjmjvkqxdx1yh136xxhilxd40bky1w4d7hn4xvhx7"; authors = [ "Andrew Gallant " @@ -408,6 +417,7 @@ rec { crateName = "cexpr"; version = "0.3.6"; edition = "2015"; + crateBin = []; sha256 = "07fdfj4ff2974y33yixrb657riq9zl9b9h9lr0h7ridhhvxvbrgw"; authors = [ "Jethro Beekman " @@ -425,6 +435,7 @@ rec { crateName = "cfg-if"; version = "0.1.10"; edition = "2018"; + crateBin = []; sha256 = "08h80ihs74jcyp24cd75wwabygbbdgl05k6p5dmq8akbr78vv1a7"; authors = [ "Alex Crichton " @@ -439,6 +450,7 @@ rec { crateName = "clang-sys"; version = "0.28.1"; edition = "2015"; + crateBin = []; sha256 = "0ls8zcqi5bmmrvrk3b6r1ym4wlivinbv590d2dvg2xn9f44mbpl1"; authors = [ "Kyle Mayes " @@ -545,6 +557,7 @@ rec { crateName = "env_logger"; version = "0.6.2"; edition = "2015"; + crateBin = []; sha256 = "1lx2s5nk96xx4i3m4zc4ghqgi8kb07dsnyiv8jk2clhax42dxz5a"; authors = [ "The Rust Project Developers" @@ -589,6 +602,7 @@ rec { crateName = "failure"; version = "0.1.6"; edition = "2015"; + crateBin = []; sha256 = "1nay5c2cgi40kp84rbiir1dgwlh9aap9jazbnxfmqrkpr49ky9zq"; authors = [ "Without Boats " @@ -613,6 +627,7 @@ rec { crateName = "fxhash"; version = "0.2.1"; edition = "2015"; + crateBin = []; sha256 = "037mb9ichariqi45xm6mz0b11pa92gj38ba0409z3iz239sns6y3"; libPath = "lib.rs"; authors = [ @@ -630,6 +645,7 @@ rec { crateName = "getrandom"; version = "0.1.13"; edition = "2018"; + crateBin = []; sha256 = "01zlzhdbg8y6d1zrlihvm93s421g0nldiq7f1hch3kfl9slprnz7"; authors = [ "The Rand Project Developers" @@ -665,6 +681,7 @@ rec { crateName = "glob"; version = "0.3.0"; edition = "2015"; + crateBin = []; sha256 = "0x25wfr7vg3mzxc9x05dcphvd3nwlcmbnxrvwcvrrdwplcrrk4cv"; authors = [ "The Rust Project Developers" @@ -697,6 +714,7 @@ rec { crateName = "humantime"; version = "1.3.0"; edition = "2015"; + crateBin = []; sha256 = "0krwgbf35pd46xvkqg14j070vircsndabahahlv3rwhflpy4q06z"; authors = [ "Paul Colomiets " @@ -713,6 +731,7 @@ rec { crateName = "jobserver"; version = "0.1.17"; edition = "2015"; + crateBin = []; sha256 = "0q61p39nw0bdx6w0wkjv1kcha5mbhcfdl4z1hxrhpcskyhpd9cgj"; authors = [ "Alex Crichton " @@ -739,6 +758,7 @@ rec { crateName = "lazy_static"; version = "1.4.0"; edition = "2015"; + crateBin = []; sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; authors = [ "Marvin Löbel " @@ -752,6 +772,7 @@ rec { crateName = "libc"; version = "0.2.66"; edition = "2015"; + crateBin = []; sha256 = "0n0mwry21fxfwc063k33mvxk8xj7ia5ar8m42c9ymbam2ksb25fm"; authors = [ "The Rust Project Developers" @@ -768,6 +789,7 @@ rec { crateName = "libloading"; version = "0.5.2"; edition = "2015"; + crateBin = []; sha256 = "0lyply8rcqc8agajzxs7bq6ivba9dnn1i68kgb9z2flnfjh13cgj"; authors = [ "Simonas Kazlauskas " @@ -792,6 +814,7 @@ rec { crateName = "librocksdb-sys"; version = "6.2.4"; edition = "2015"; + crateBin = []; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/rust-rocksdb/rust-rocksdb"; @@ -832,6 +855,7 @@ rec { crateName = "log"; version = "0.4.8"; edition = "2015"; + crateBin = []; sha256 = "1xz18ixccl5c6np4linv3ypc7hpmmgpc5zzd2ymp2ssfx0mhbdhl"; authors = [ "The Rust Project Developers" @@ -868,6 +892,7 @@ rec { crateName = "nom"; version = "4.2.3"; edition = "2015"; + crateBin = []; sha256 = "1mkvby8b4m61p4g1px0pwr58yfkphyp1jcfbp4qfp7l6iqdaklia"; authors = [ "contact@geoffroycouprie.com" @@ -900,6 +925,7 @@ rec { crateName = "num_cpus"; version = "1.11.1"; edition = "2015"; + crateBin = []; sha256 = "0wlxs00cpg16z09fwchj1gdz1jxnf5dgg1cbidvq0sc75bnwbnkn"; authors = [ "Sean McArthur " @@ -931,6 +957,7 @@ rec { crateName = "proc-macro2"; version = "0.4.30"; edition = "2015"; + crateBin = []; sha256 = "0nd71fl24sys066jrha6j7i34nfkjv44yzw8yww9742wmc8j0gfg"; authors = [ "Alex Crichton " @@ -949,6 +976,7 @@ rec { crateName = "quick-error"; version = "1.2.2"; edition = "2015"; + crateBin = []; sha256 = "1w6kgwwv7p7zr0yyg5rb315lkk24bimywklwx7fsvsbwi10bjx4j"; authors = [ "Paul Colomiets " @@ -960,6 +988,7 @@ rec { crateName = "quote"; version = "0.6.13"; edition = "2015"; + crateBin = []; sha256 = "1qgqq48jymp5h4y082aanf25hrw6bpb678xh3zw993qfhxmkpqkc"; authors = [ "David Tolnay " @@ -980,6 +1009,7 @@ rec { crateName = "regex"; version = "1.3.1"; edition = "2015"; + crateBin = []; sha256 = "1g8wp160vzxgralyd4imydd0xsxq6yh25zhs229z1s6w7g9hn8nw"; authors = [ "The Rust Project Developers" @@ -1031,6 +1061,7 @@ rec { crateName = "regex-syntax"; version = "0.6.12"; edition = "2015"; + crateBin = []; sha256 = "05pplicvzvgkb2wb4i98p2mrpgc8gws6vdl8xlpyyr6f3h6y59qi"; authors = [ "The Rust Project Developers" @@ -1045,6 +1076,7 @@ rec { crateName = "rocksdb"; version = "0.13.0"; edition = "2015"; + crateBin = []; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/rust-rocksdb/rust-rocksdb"; @@ -1102,6 +1134,7 @@ rec { crateName = "strsim"; version = "0.8.0"; edition = "2015"; + crateBin = []; sha256 = "0sjsm7hrvjdifz661pjxq5w4hf190hx53fra8dfvamacvff139cf"; authors = [ "Danny Guo " @@ -1129,6 +1162,7 @@ rec { crateName = "textwrap"; version = "0.11.0"; edition = "2015"; + crateBin = []; sha256 = "0q5hky03ik3y50s9sz25r438bc4nwhqc6dqwynv4wylc807n29nk"; authors = [ "Martin Geisler " @@ -1148,6 +1182,7 @@ rec { crateName = "thread_local"; version = "0.3.6"; edition = "2015"; + crateBin = []; sha256 = "06rzik99p8c5js8238yhc8rk6np543ylb1dy9nrw5v80j0r3xdf6"; authors = [ "Amanieu d'Antras " @@ -1437,112 +1472,34 @@ rec { || baseName == "tests.nix" ); - /* Returns a crate which depends on successful test execution - of crate given as the second argument. - - testCrateFlags: list of flags to pass to the test exectuable - testInputs: list of packages that should be available during test execution - */ - crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: - assert builtins.typeOf testCrateFlags == "list"; - assert builtins.typeOf testInputs == "list"; - assert builtins.typeOf testPreRun == "string"; - assert builtins.typeOf testPostRun == "string"; - let - # override the `crate` so that it will build and execute tests instead of - # building the actual lib and bin targets We just have to pass `--test` - # to rustc and it will do the right thing. We execute the tests and copy - # their log and the test executables to $out for later inspection. - test = - let - drv = testCrate.override - ( - _: { - buildTests = true; - } - ); - # If the user hasn't set any pre/post commands, we don't want to - # insert empty lines. This means that any existing users of crate2nix - # don't get a spurious rebuild unless they set these explicitly. - testCommand = pkgs.lib.concatStringsSep "\n" - (pkgs.lib.filter (s: s != "") [ - testPreRun - "$f $testCrateFlags 2>&1 | tee -a $out" - testPostRun - ]); - in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -ex - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - ${pkgs.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; - in - pkgs.runCommand "${crate.name}-linked" - { - inherit (crate) outputs crateName; - passthru = (crate.passthru or { }) // { - inherit test; - }; - } '' - echo tested by ${test} - ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} - ''; - /* A restricted overridable version of builtRustCratesWithFeatures. */ buildRustCrateWithFeatures = { packageId , features ? rootFeatures , crateOverrides ? defaultCrateOverrides , buildRustCrateForPkgsFunc ? null - , runTests ? false - , testCrateFlags ? [ ] - , testInputs ? [ ] - # Any command to run immediatelly before a test is executed. - , testPreRun ? "" - # Any command run immediatelly after a test is executed. - , testPostRun ? "" + # Available: [ "lib" "bin" ] or ["test" "bench" "example"] + , buildKinds ? [ "lib" "bin" ] }: lib.makeOverridable ( { features , crateOverrides - , runTests - , testCrateFlags - , testInputs - , testPreRun - , testPostRun + , buildKinds }: let + isDevBuild = + let + inherit (pkgs.buildRustCrateHelpers.kinds) isLib isBin isExample isTest isBench; + + notDev = builtins.any (k: isLib k || isBin k) buildKinds; + isDev = builtins.any (k: isBench k || isExample k || isTest k) buildKinds; + in + assert (buildKinds != [ ]); + # Can't have build dev and non dev kinds + assert (notDev != isDev); + isDev; + buildRustCrateForPkgsFuncOverriden = if buildRustCrateForPkgsFunc != null then buildRustCrateForPkgsFunc @@ -1555,31 +1512,16 @@ rec { defaultCrateOverrides = crateOverrides; } ); + builtRustCrates = builtRustCratesWithFeatures { - inherit packageId features; + inherit packageId features buildKinds isDevBuild; buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = false; }; - builtTestRustCrates = builtRustCratesWithFeatures { - inherit packageId features; - buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = true; - }; - drv = builtRustCrates.crates.${packageId}; - testDrv = builtTestRustCrates.crates.${packageId}; - derivation = - if runTests then - crateWithTest - { - crate = drv; - testCrate = testDrv; - inherit testCrateFlags testInputs testPreRun testPostRun; - } - else drv; + in - derivation + builtRustCrates.crates.${packageId} ) - { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + { inherit features crateOverrides buildKinds; }; /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc for the corresponding crate. @@ -1589,21 +1531,24 @@ rec { , features , crateConfigs ? crates , buildRustCrateForPkgsFunc - , runTests + , buildKinds + , isDevBuild , makeTarget ? makeDefaultTarget } @ args: assert (builtins.isAttrs crateConfigs); assert (builtins.isString packageId); assert (builtins.isList features); assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); + assert (builtins.isList buildKinds); let rootPackageId = packageId; mergedFeatures = mergePackageFeatures ( args // { inherit rootPackageId; - target = makeTarget stdenv.hostPlatform // { test = runTests; }; + # What does test do for target? + target = makeTarget stdenv.hostPlatform // { test = false; }; } ); # Memoize built packages so that reappearing packages are only built once. @@ -1625,7 +1570,7 @@ rec { builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; devDependencies = lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig'.devDependencies or [ ]); dependencies = dependencyDerivations { @@ -1699,6 +1644,7 @@ rec { } ); extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + buildKinds = if (packageId == rootPackageId) then buildKinds else [ "lib" ]; inherit features dependencies buildDependencies crateRenames release; } ); @@ -1820,7 +1766,7 @@ rec { , featuresByPackageId ? { } , target # Adds devDependencies to the crate with rootPackageId. - , runTests ? false + , isDevBuild ? false , ... } @ args: assert (builtins.isAttrs crateConfigs); @@ -1830,7 +1776,7 @@ rec { assert (builtins.isList dependencyPath); assert (builtins.isAttrs featuresByPackageId); assert (builtins.isAttrs target); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); let crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); expandedFeatures = expandFeatures (crateConfig.features or { }) features; @@ -1865,7 +1811,7 @@ rec { mergePackageFeatures { features = combinedFeatures; featuresByPackageId = cache; - inherit crateConfigs packageId target runTests rootPackageId; + inherit crateConfigs packageId target isDevBuild rootPackageId; } ); cacheWithSelf = @@ -1881,7 +1827,7 @@ rec { ( crateConfig.dependencies or [ ] ++ lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig.devDependencies or [ ]) ); cacheWithAll = diff --git a/sample_projects/cfg-test/test.nix b/sample_projects/cfg-test/test.nix index 398cd45d..7c76ae47 100644 --- a/sample_projects/cfg-test/test.nix +++ b/sample_projects/cfg-test/test.nix @@ -1,10 +1,10 @@ { pkgs ? import ../../nix/nixpkgs.nix { config = { }; } , generatedCargoNix ? ./Cargo.nix { } +, tools ? pkgs.callPackage ../../tools.nix { } }: let instantiatedBuild = pkgs.callPackage generatedCargoNix { }; + + crate = instantiatedBuild.rootCrate.build; in -instantiatedBuild.rootCrate.build.override { - runTests = true; - testInputs = [ pkgs.cowsay ]; -} +tools.crateWithTest { inherit crate; testInputs = [ pkgs.cowsay ]; } diff --git a/sample_projects/codegen/Cargo.nix b/sample_projects/codegen/Cargo.nix index 4a055101..ba7cac20 100644 --- a/sample_projects/codegen/Cargo.nix +++ b/sample_projects/codegen/Cargo.nix @@ -87,6 +87,7 @@ rec { crateName = "ansi_term"; version = "0.11.0"; edition = "2015"; + crateBin = []; sha256 = "16wpvrghvd0353584i1idnsgm0r3vchg8fyrm0x8ayv1rgvbljgf"; authors = [ "ogham@bsago.me" @@ -107,6 +108,7 @@ rec { crateName = "atty"; version = "0.2.13"; edition = "2015"; + crateBin = []; sha256 = "140sswp1bwqwc4zk80bxkbnfb3g936hgrb77g9g0k1zcld3wc0qq"; authors = [ "softprops " @@ -131,6 +133,7 @@ rec { crateName = "bitflags"; version = "0.7.0"; edition = "2015"; + crateBin = []; sha256 = "0v8hh6wdkpk9my8z8442g4hqrqf05h0qj53dsay6mv18lqvqklda"; authors = [ "The Rust Project Developers" @@ -218,6 +221,11 @@ rec { { name = "codegen"; path = "src/main.rs"; + kind = "bin"; + test = true; + # TODO (when cargo merges metadata): + # harness + # bench requiredFeatures = [ ]; } ]; @@ -247,6 +255,7 @@ rec { crateName = "dbus"; version = "0.7.1"; edition = "2018"; + crateBin = []; workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/diwic/dbus-rs.git"; @@ -303,6 +312,7 @@ rec { crateName = "libc"; version = "0.2.66"; edition = "2015"; + crateBin = []; sha256 = "0n0mwry21fxfwc063k33mvxk8xj7ia5ar8m42c9ymbam2ksb25fm"; authors = [ "The Rust Project Developers" @@ -340,6 +350,7 @@ rec { crateName = "pkg-config"; version = "0.3.17"; edition = "2015"; + crateBin = []; sha256 = "0xynnaxdv0gzadlw4h79j855k0q7rj4zb9xb1vk00nc6ss559nh5"; authors = [ "Alex Crichton " @@ -350,6 +361,7 @@ rec { crateName = "strsim"; version = "0.8.0"; edition = "2015"; + crateBin = []; sha256 = "0sjsm7hrvjdifz661pjxq5w4hf190hx53fra8dfvamacvff139cf"; authors = [ "Danny Guo " @@ -360,6 +372,7 @@ rec { crateName = "textwrap"; version = "0.11.0"; edition = "2015"; + crateBin = []; sha256 = "0q5hky03ik3y50s9sz25r438bc4nwhqc6dqwynv4wylc807n29nk"; authors = [ "Martin Geisler " @@ -569,112 +582,34 @@ rec { || baseName == "tests.nix" ); - /* Returns a crate which depends on successful test execution - of crate given as the second argument. - - testCrateFlags: list of flags to pass to the test exectuable - testInputs: list of packages that should be available during test execution - */ - crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: - assert builtins.typeOf testCrateFlags == "list"; - assert builtins.typeOf testInputs == "list"; - assert builtins.typeOf testPreRun == "string"; - assert builtins.typeOf testPostRun == "string"; - let - # override the `crate` so that it will build and execute tests instead of - # building the actual lib and bin targets We just have to pass `--test` - # to rustc and it will do the right thing. We execute the tests and copy - # their log and the test executables to $out for later inspection. - test = - let - drv = testCrate.override - ( - _: { - buildTests = true; - } - ); - # If the user hasn't set any pre/post commands, we don't want to - # insert empty lines. This means that any existing users of crate2nix - # don't get a spurious rebuild unless they set these explicitly. - testCommand = pkgs.lib.concatStringsSep "\n" - (pkgs.lib.filter (s: s != "") [ - testPreRun - "$f $testCrateFlags 2>&1 | tee -a $out" - testPostRun - ]); - in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -ex - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - ${pkgs.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; - in - pkgs.runCommand "${crate.name}-linked" - { - inherit (crate) outputs crateName; - passthru = (crate.passthru or { }) // { - inherit test; - }; - } '' - echo tested by ${test} - ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} - ''; - /* A restricted overridable version of builtRustCratesWithFeatures. */ buildRustCrateWithFeatures = { packageId , features ? rootFeatures , crateOverrides ? defaultCrateOverrides , buildRustCrateForPkgsFunc ? null - , runTests ? false - , testCrateFlags ? [ ] - , testInputs ? [ ] - # Any command to run immediatelly before a test is executed. - , testPreRun ? "" - # Any command run immediatelly after a test is executed. - , testPostRun ? "" + # Available: [ "lib" "bin" ] or ["test" "bench" "example"] + , buildKinds ? [ "lib" "bin" ] }: lib.makeOverridable ( { features , crateOverrides - , runTests - , testCrateFlags - , testInputs - , testPreRun - , testPostRun + , buildKinds }: let + isDevBuild = + let + inherit (pkgs.buildRustCrateHelpers.kinds) isLib isBin isExample isTest isBench; + + notDev = builtins.any (k: isLib k || isBin k) buildKinds; + isDev = builtins.any (k: isBench k || isExample k || isTest k) buildKinds; + in + assert (buildKinds != [ ]); + # Can't have build dev and non dev kinds + assert (notDev != isDev); + isDev; + buildRustCrateForPkgsFuncOverriden = if buildRustCrateForPkgsFunc != null then buildRustCrateForPkgsFunc @@ -687,31 +622,16 @@ rec { defaultCrateOverrides = crateOverrides; } ); + builtRustCrates = builtRustCratesWithFeatures { - inherit packageId features; - buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = false; - }; - builtTestRustCrates = builtRustCratesWithFeatures { - inherit packageId features; + inherit packageId features buildKinds isDevBuild; buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = true; }; - drv = builtRustCrates.crates.${packageId}; - testDrv = builtTestRustCrates.crates.${packageId}; - derivation = - if runTests then - crateWithTest - { - crate = drv; - testCrate = testDrv; - inherit testCrateFlags testInputs testPreRun testPostRun; - } - else drv; + in - derivation + builtRustCrates.crates.${packageId} ) - { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + { inherit features crateOverrides buildKinds; }; /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc for the corresponding crate. @@ -721,21 +641,24 @@ rec { , features , crateConfigs ? crates , buildRustCrateForPkgsFunc - , runTests + , buildKinds + , isDevBuild , makeTarget ? makeDefaultTarget } @ args: assert (builtins.isAttrs crateConfigs); assert (builtins.isString packageId); assert (builtins.isList features); assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); + assert (builtins.isList buildKinds); let rootPackageId = packageId; mergedFeatures = mergePackageFeatures ( args // { inherit rootPackageId; - target = makeTarget stdenv.hostPlatform // { test = runTests; }; + # What does test do for target? + target = makeTarget stdenv.hostPlatform // { test = false; }; } ); # Memoize built packages so that reappearing packages are only built once. @@ -757,7 +680,7 @@ rec { builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; devDependencies = lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig'.devDependencies or [ ]); dependencies = dependencyDerivations { @@ -831,6 +754,7 @@ rec { } ); extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + buildKinds = if (packageId == rootPackageId) then buildKinds else [ "lib" ]; inherit features dependencies buildDependencies crateRenames release; } ); @@ -952,7 +876,7 @@ rec { , featuresByPackageId ? { } , target # Adds devDependencies to the crate with rootPackageId. - , runTests ? false + , isDevBuild ? false , ... } @ args: assert (builtins.isAttrs crateConfigs); @@ -962,7 +886,7 @@ rec { assert (builtins.isList dependencyPath); assert (builtins.isAttrs featuresByPackageId); assert (builtins.isAttrs target); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); let crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); expandedFeatures = expandFeatures (crateConfig.features or { }) features; @@ -997,7 +921,7 @@ rec { mergePackageFeatures { features = combinedFeatures; featuresByPackageId = cache; - inherit crateConfigs packageId target runTests rootPackageId; + inherit crateConfigs packageId target isDevBuild rootPackageId; } ); cacheWithSelf = @@ -1013,7 +937,7 @@ rec { ( crateConfig.dependencies or [ ] ++ lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig.devDependencies or [ ]) ); cacheWithAll = diff --git a/sample_projects/integration_test/test.nix b/sample_projects/integration_test/test.nix index 580ae503..c5fab55f 100644 --- a/sample_projects/integration_test/test.nix +++ b/sample_projects/integration_test/test.nix @@ -1,9 +1,10 @@ { pkgs ? import ../../nix/nixpkgs.nix { config = { }; } , generatedCargoNix ? ./Cargo.nix { } +, tools ? pkgs.callPackage ../../tools.nix { } }: let instantiatedBuild = pkgs.callPackage generatedCargoNix { }; + + crate = instantiatedBuild.rootCrate.build; in -instantiatedBuild.rootCrate.build.override { - runTests = true; -} +tools.crateWithTest { inherit crate; } diff --git a/sample_projects/renamed_dev_deps/test.nix b/sample_projects/renamed_dev_deps/test.nix index 580ae503..c5fab55f 100644 --- a/sample_projects/renamed_dev_deps/test.nix +++ b/sample_projects/renamed_dev_deps/test.nix @@ -1,9 +1,10 @@ { pkgs ? import ../../nix/nixpkgs.nix { config = { }; } , generatedCargoNix ? ./Cargo.nix { } +, tools ? pkgs.callPackage ../../tools.nix { } }: let instantiatedBuild = pkgs.callPackage generatedCargoNix { }; + + crate = instantiatedBuild.rootCrate.build; in -instantiatedBuild.rootCrate.build.override { - runTests = true; -} +tools.crateWithTest { inherit crate; } diff --git a/sample_projects/sub_dir_crates/Cargo.nix b/sample_projects/sub_dir_crates/Cargo.nix index 9eaa102a..d03bcdcd 100644 --- a/sample_projects/sub_dir_crates/Cargo.nix +++ b/sample_projects/sub_dir_crates/Cargo.nix @@ -121,6 +121,11 @@ rec { { name = "sub_dir_crates"; path = "src/main.rs"; + kind = "bin"; + test = true; + # TODO (when cargo merges metadata): + # harness + # bench requiredFeatures = [ ]; } ]; @@ -221,112 +226,34 @@ rec { || baseName == "tests.nix" ); - /* Returns a crate which depends on successful test execution - of crate given as the second argument. - - testCrateFlags: list of flags to pass to the test exectuable - testInputs: list of packages that should be available during test execution - */ - crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: - assert builtins.typeOf testCrateFlags == "list"; - assert builtins.typeOf testInputs == "list"; - assert builtins.typeOf testPreRun == "string"; - assert builtins.typeOf testPostRun == "string"; - let - # override the `crate` so that it will build and execute tests instead of - # building the actual lib and bin targets We just have to pass `--test` - # to rustc and it will do the right thing. We execute the tests and copy - # their log and the test executables to $out for later inspection. - test = - let - drv = testCrate.override - ( - _: { - buildTests = true; - } - ); - # If the user hasn't set any pre/post commands, we don't want to - # insert empty lines. This means that any existing users of crate2nix - # don't get a spurious rebuild unless they set these explicitly. - testCommand = pkgs.lib.concatStringsSep "\n" - (pkgs.lib.filter (s: s != "") [ - testPreRun - "$f $testCrateFlags 2>&1 | tee -a $out" - testPostRun - ]); - in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -ex - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - ${pkgs.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; - in - pkgs.runCommand "${crate.name}-linked" - { - inherit (crate) outputs crateName; - passthru = (crate.passthru or { }) // { - inherit test; - }; - } '' - echo tested by ${test} - ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} - ''; - /* A restricted overridable version of builtRustCratesWithFeatures. */ buildRustCrateWithFeatures = { packageId , features ? rootFeatures , crateOverrides ? defaultCrateOverrides , buildRustCrateForPkgsFunc ? null - , runTests ? false - , testCrateFlags ? [ ] - , testInputs ? [ ] - # Any command to run immediatelly before a test is executed. - , testPreRun ? "" - # Any command run immediatelly after a test is executed. - , testPostRun ? "" + # Available: [ "lib" "bin" ] or ["test" "bench" "example"] + , buildKinds ? [ "lib" "bin" ] }: lib.makeOverridable ( { features , crateOverrides - , runTests - , testCrateFlags - , testInputs - , testPreRun - , testPostRun + , buildKinds }: let + isDevBuild = + let + inherit (pkgs.buildRustCrateHelpers.kinds) isLib isBin isExample isTest isBench; + + notDev = builtins.any (k: isLib k || isBin k) buildKinds; + isDev = builtins.any (k: isBench k || isExample k || isTest k) buildKinds; + in + assert (buildKinds != [ ]); + # Can't have build dev and non dev kinds + assert (notDev != isDev); + isDev; + buildRustCrateForPkgsFuncOverriden = if buildRustCrateForPkgsFunc != null then buildRustCrateForPkgsFunc @@ -339,31 +266,16 @@ rec { defaultCrateOverrides = crateOverrides; } ); + builtRustCrates = builtRustCratesWithFeatures { - inherit packageId features; + inherit packageId features buildKinds isDevBuild; buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = false; }; - builtTestRustCrates = builtRustCratesWithFeatures { - inherit packageId features; - buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; - runTests = true; - }; - drv = builtRustCrates.crates.${packageId}; - testDrv = builtTestRustCrates.crates.${packageId}; - derivation = - if runTests then - crateWithTest - { - crate = drv; - testCrate = testDrv; - inherit testCrateFlags testInputs testPreRun testPostRun; - } - else drv; + in - derivation + builtRustCrates.crates.${packageId} ) - { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + { inherit features crateOverrides buildKinds; }; /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc for the corresponding crate. @@ -373,21 +285,24 @@ rec { , features , crateConfigs ? crates , buildRustCrateForPkgsFunc - , runTests + , buildKinds + , isDevBuild , makeTarget ? makeDefaultTarget } @ args: assert (builtins.isAttrs crateConfigs); assert (builtins.isString packageId); assert (builtins.isList features); assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); + assert (builtins.isList buildKinds); let rootPackageId = packageId; mergedFeatures = mergePackageFeatures ( args // { inherit rootPackageId; - target = makeTarget stdenv.hostPlatform // { test = runTests; }; + # What does test do for target? + target = makeTarget stdenv.hostPlatform // { test = false; }; } ); # Memoize built packages so that reappearing packages are only built once. @@ -409,7 +324,7 @@ rec { builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; devDependencies = lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig'.devDependencies or [ ]); dependencies = dependencyDerivations { @@ -483,6 +398,7 @@ rec { } ); extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + buildKinds = if (packageId == rootPackageId) then buildKinds else [ "lib" ]; inherit features dependencies buildDependencies crateRenames release; } ); @@ -604,7 +520,7 @@ rec { , featuresByPackageId ? { } , target # Adds devDependencies to the crate with rootPackageId. - , runTests ? false + , isDevBuild ? false , ... } @ args: assert (builtins.isAttrs crateConfigs); @@ -614,7 +530,7 @@ rec { assert (builtins.isList dependencyPath); assert (builtins.isAttrs featuresByPackageId); assert (builtins.isAttrs target); - assert (builtins.isBool runTests); + assert (builtins.isBool isDevBuild); let crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); expandedFeatures = expandFeatures (crateConfig.features or { }) features; @@ -649,7 +565,7 @@ rec { mergePackageFeatures { features = combinedFeatures; featuresByPackageId = cache; - inherit crateConfigs packageId target runTests rootPackageId; + inherit crateConfigs packageId target isDevBuild rootPackageId; } ); cacheWithSelf = @@ -665,7 +581,7 @@ rec { ( crateConfig.dependencies or [ ] ++ lib.optionals - (runTests && packageId == rootPackageId) + (isDevBuild && packageId == rootPackageId) (crateConfig.devDependencies or [ ]) ); cacheWithAll = diff --git a/sample_projects/test_flag_passing/test.nix b/sample_projects/test_flag_passing/test.nix index 6dba50ec..6f1c6ba5 100644 --- a/sample_projects/test_flag_passing/test.nix +++ b/sample_projects/test_flag_passing/test.nix @@ -1,11 +1,14 @@ { pkgs ? import ../../nix/nixpkgs.nix { config = { }; } , generatedCargoNix ? ./Cargo.nix { } +, tools ? pkgs.callPackage ../../tools.nix { } }: let instantiatedBuild = pkgs.callPackage generatedCargoNix { }; + + crate = instantiatedBuild.rootCrate.build; in -instantiatedBuild.rootCrate.build.override { - runTests = true; +tools.crateWithTest { + inherit crate; testCrateFlags = [ "--skip" "this_must_be_skipped" diff --git a/tools.nix b/tools.nix index cdcae0d7..7d2db996 100644 --- a/tools.nix +++ b/tools.nix @@ -136,6 +136,95 @@ rec { "crate2nix/tools.nix: generated deprecated since 0.7. Use appliedCargoNix in instead." appliedCargoNix; + /* Returns a crate which depends on successful test execution + of crate given as the second argument. + + , testPreRun ? "" + , testPostRun ? "" + */ + crateWithTest = + # crate: normal crate + { crate + # testCrate: crate with the test binaries + , testCrate ? crate.override { buildKinds = [ "test" ]; } + # testCrateFlags: list of flags to pass to the test exectuable + , testCrateFlags ? [ ] + # testInputs: list of packages that should be available during test execution + , testInputs ? [ ] + # Any command to run immediatelly before a test is executed. + , testPreRun ? "" + # Any command to run immediatelly after a test is executed. + , testPostRun ? "" + }: + assert builtins.typeOf testCrateFlags == "list"; + assert builtins.typeOf testInputs == "list"; + assert builtins.typeOf testPreRun == "string"; + assert builtins.typeOf testPostRun == "string"; + let + # override the `crate` so that it will build and execute tests instead of + # building the actual lib and bin targets We just have to pass `--test` + # to rustc and it will do the right thing. We execute the tests and copy + # their log and the test executables to $out for later inspection. + test = + let + # If the user hasn't set any pre/post commands, we don't want to + # insert empty lines. This means that any existing users of crate2nix + # don't get a spurious rebuild unless they set these explicitly. + testCommand = pkgs.lib.concatStringsSep "\n" + (pkgs.lib.filter (s: s != "") [ + testPreRun + "$f $testCrateFlags 2>&1 | tee -a $out" + testPostRun + ]); + in + pkgs.runCommand "run-tests-${testCrate.name}" + { + inherit testCrateFlags; + buildInputs = testInputs; + } '' + set -ex + + export RUST_BACKTRACE=1 + + # recreate a file hierarchy as when running tests with cargo + + # the source for test data + ${pkgs.xorg.lndir}/bin/lndir ${crate.src} + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${testCrate}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + in + pkgs.runCommand "${crate.name}-linked" + { + inherit (crate) outputs crateName; + passthru = (crate.passthru or { }) // { + inherit test; + }; + } '' + echo tested by ${test} + ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} + ''; + + internal = rec { # Unpack sources and add a .cargo-checksum.json file to make cargo happy. unpacked = { sha256, src }: