2022-08-12 12:06:08 +00:00
{ lib , stdenv
2024-07-01 15:47:52 +00:00
, mkRustcDepArgs , mkRustcFeatureArgs , needUnstableCLI , rustc
2022-08-12 12:06:08 +00:00
} :
2020-04-24 23:36:52 +00:00
{ crateName ,
dependencies ,
crateFeatures , crateRenames , libName , release , libPath ,
crateType , metadata , crateBin , hasCrateBin ,
extraRustcOpts , verbose , colors ,
2022-04-27 09:35:20 +00:00
buildTests ,
codegenUnits
2020-04-24 23:36:52 +00:00
} :
let
baseRustcOpts =
2021-04-08 16:26:57 +00:00
[
( if release then " - C o p t - l e v e l = 3 " else " - C d e b u g i n f o = 2 " )
2022-04-27 09:35:20 +00:00
" - C c o d e g e n - u n i t s = ${ toString codegenUnits } "
2021-04-08 16:26:57 +00:00
" - - r e m a p - p a t h - p r e f i x = $ N I X _ B U I L D _ T O P = / "
( mkRustcDepArgs dependencies crateRenames )
( mkRustcFeatureArgs crateFeatures )
2021-10-07 14:46:35 +00:00
] ++ lib . optionals ( stdenv . hostPlatform != stdenv . buildPlatform ) [
2023-11-16 04:20:00 +00:00
" - - t a r g e t " stdenv . hostPlatform . rust . rustcTargetSpec
2022-08-12 12:06:08 +00:00
] ++ lib . optionals ( needUnstableCLI dependencies ) [
" - Z " " u n s t a b l e - o p t i o n s "
2021-04-08 16:26:57 +00:00
] ++ extraRustcOpts
2020-04-24 23:36:52 +00:00
# since rustc 1.42 the "proc_macro" crate is part of the default crate prelude
# https://github.com/rust-lang/cargo/commit/4d64eb99a4#diff-7f98585dbf9d30aa100c8318e2c77e79R1021-R1022
++ lib . optional ( lib . elem " p r o c - m a c r o " crateType ) " - - e x t e r n p r o c _ m a c r o "
2024-09-19 14:19:46 +00:00
++ lib . optional ( stdenv . hostPlatform . linker == " l l d " && rustc ? llvmPackages . lld ) # Needed when building for targets that use lld. e.g. 'wasm32-unknown-unknown'
2024-07-01 15:47:52 +00:00
" - C l i n k e r = ${ rustc . llvmPackages . lld } / b i n / l l d "
++ lib . optional ( stdenv . hasCC && stdenv . hostPlatform . linker != " l l d " )
" - C l i n k e r = ${ stdenv . cc } / b i n / ${ stdenv . cc . targetPrefix } c c "
2020-04-24 23:36:52 +00:00
;
rustcMeta = " - C m e t a d a t a = ${ metadata } - C e x t r a - f i l e n a m e = - ${ metadata } " ;
# build the final rustc arguments that can be different between different
# crates
libRustcOpts = lib . concatStringsSep " " (
baseRustcOpts
++ [ rustcMeta ]
++ ( map ( x : " - - c r a t e - t y p e ${ x } " ) crateType )
) ;
2024-07-01 15:47:52 +00:00
binRustcOpts = lib . concatStringsSep " " baseRustcOpts ;
2020-04-24 23:36:52 +00:00
build_bin = if buildTests then " b u i l d _ b i n _ t e s t " else " b u i l d _ b i n " ;
in ''
runHook preBuild
2020-08-20 17:08:02 +00:00
2020-04-24 23:36:52 +00:00
# configure & source common build functions
LIB_RUSTC_OPTS = " ${ libRustcOpts } "
BIN_RUSTC_OPTS = " ${ binRustcOpts } "
2024-06-20 14:57:18 +00:00
LIB_EXT = " ${ stdenv . hostPlatform . extensions . library } "
2020-04-24 23:36:52 +00:00
LIB_PATH = " ${ libPath } "
LIB_NAME = " ${ libName } "
CRATE_NAME = ' $ { lib . replaceStrings [ " - " ] [ " _ " ] libName } '
setup_link_paths
if [ [ - e " $ L I B _ P A T H " ] ] ; then
build_lib " $ L I B _ P A T H "
$ { lib . optionalString buildTests '' b u i l d _ l i b _ t e s t " $L I B _ P A T H " '' }
elif [ [ - e src/lib.rs ] ] ; then
build_lib src/lib.rs
$ { lib . optionalString buildTests " b u i l d _ l i b _ t e s t s r c / l i b . r s " }
fi
2022-09-09 14:08:57 +00:00
$ { lib . optionalString ( lib . length crateBin > 0 ) ( lib . concatMapStringsSep " \n " ( bin :
let
haveRequiredFeature = if bin ? requiredFeatures then
# Check that all element in requiredFeatures are also present in crateFeatures
lib . intersectLists bin . requiredFeatures crateFeatures == bin . requiredFeatures
else
true ;
in
if haveRequiredFeature then ''
2020-04-24 23:36:52 +00:00
mkdir - p target/bin
BIN_NAME = ' $ { bin . name or crateName } '
$ { if ! bin ? path then ''
BIN_PATH = " "
search_for_bin_path " $ B I N _ N A M E "
'' e l s e ''
BIN_PATH = ' $ { bin . path } '
'' }
$ { build_bin } " $ B I N _ N A M E " " $ B I N _ P A T H "
2022-09-09 14:08:57 +00:00
'' e l s e ''
echo Binary $ { bin . name or crateName } not compiled due to not having all of the required features - - $ { lib . escapeShellArg ( builtins . toJSON bin . requiredFeatures ) } - - enabled .
2020-04-24 23:36:52 +00:00
'' ) c r a t e B i n ) }
$ { lib . optionalString buildTests ''
# When tests are enabled build all the files in the `tests` directory as
# test binaries.
if [ - d tests ] ; then
# find all the .rs files (or symlinks to those) in the tests directory, no subdirectories
find tests - maxdepth 1 \ ( - type f - o - type l \ ) - a - name ' * . rs' - print0 | while IFS = read - r - d '' ' f i l e ; d o
mkdir - p target/bin
build_bin_test_file " $ f i l e "
done
# find all the subdirectories of tests/ that contain a main.rs file as
# that is also a test according to cargo
find tests / - mindepth 1 - maxdepth 2 \ ( - type f - o - type l \ ) - a - name ' main . rs' - print0 | while IFS = read - r - d '' ' f i l e ; d o
mkdir - p target/bin
build_bin_test_file " $ f i l e "
done
fi
'' }
# If crateBin is empty and hasCrateBin is not set then we must try to
# detect some kind of bin target based on some files that might exist.
$ { lib . optionalString ( lib . length crateBin == 0 && ! hasCrateBin ) ''
if [ [ - e src/main.rs ] ] ; then
mkdir - p target/bin
$ { build_bin } $ { crateName } src/main.rs
fi
for i in src/bin /* . r s ; d o # */
mkdir - p target/bin
$ { build_bin } " $ ( b a s e n a m e $ i . r s ) " " $ i "
done
'' }
# Remove object files to avoid "wrong ELF type"
find target - type f - name " * . o " - print0 | xargs -0 rm - f
runHook postBuild
''