@@ -102,28 +102,27 @@ fn build_pc_files(
102
102
103
103
fn patch_target (
104
104
pkg : & mut Package ,
105
- libkinds : & [ & str ] ,
105
+ library_types : LibraryTypes ,
106
106
capi_config : & CApiConfig ,
107
107
) -> anyhow:: Result < ( ) > {
108
108
use cargo:: core:: compiler:: CrateType ;
109
109
110
110
let manifest = pkg. manifest_mut ( ) ;
111
111
let targets = manifest. targets_mut ( ) ;
112
112
113
- let kinds: Vec < _ > = libkinds
114
- . iter ( )
115
- . map ( |& kind| match kind {
116
- "staticlib" => CrateType :: Staticlib ,
117
- "cdylib" => CrateType :: Cdylib ,
118
- _ => unreachable ! ( ) ,
119
- } )
120
- . collect ( ) ;
113
+ let mut kinds = Vec :: with_capacity ( 2 ) ;
121
114
122
- for target in targets. iter_mut ( ) {
123
- if target. is_lib ( ) {
124
- target. set_kind ( TargetKind :: Lib ( kinds. clone ( ) ) ) ;
125
- target. set_name ( & capi_config. library . name ) ;
126
- }
115
+ if library_types. staticlib {
116
+ kinds. push ( CrateType :: Staticlib ) ;
117
+ }
118
+
119
+ if library_types. cdylib {
120
+ kinds. push ( CrateType :: Cdylib ) ;
121
+ }
122
+
123
+ for target in targets. iter_mut ( ) . filter ( |t| t. is_lib ( ) ) {
124
+ target. set_kind ( TargetKind :: Lib ( kinds. to_vec ( ) ) ) ;
125
+ target. set_name ( & capi_config. library . name ) ;
127
126
}
128
127
129
128
Ok ( ( ) )
@@ -952,7 +951,7 @@ impl CPackage {
952
951
fn from_package (
953
952
pkg : & mut Package ,
954
953
args : & ArgMatches ,
955
- libkinds : & [ & str ] ,
954
+ library_types : LibraryTypes ,
956
955
rustc_target : & target:: Target ,
957
956
root_output : & Path ,
958
957
) -> anyhow:: Result < CPackage > {
@@ -961,7 +960,7 @@ impl CPackage {
961
960
let root_path = pkg. root ( ) . to_path_buf ( ) ;
962
961
let capi_config = load_manifest_capi_config ( pkg, rustc_target) ?;
963
962
964
- patch_target ( pkg, libkinds , & capi_config) ?;
963
+ patch_target ( pkg, library_types , & capi_config) ?;
965
964
966
965
let name = & capi_config. library . name ;
967
966
@@ -970,7 +969,7 @@ impl CPackage {
970
969
name,
971
970
rustc_target,
972
971
root_output,
973
- libkinds ,
972
+ library_types ,
974
973
& capi_config,
975
974
args. get_flag ( "meson" ) ,
976
975
) ?;
@@ -998,6 +997,58 @@ fn deprecation_warnings(ws: &Workspace, args: &ArgMatches) -> anyhow::Result<()>
998
997
Ok ( ( ) )
999
998
}
1000
999
1000
+ /// What library types to build
1001
+ #[ derive( Debug , Clone , Copy ) ]
1002
+ pub struct LibraryTypes {
1003
+ pub staticlib : bool ,
1004
+ pub cdylib : bool ,
1005
+ }
1006
+
1007
+ impl LibraryTypes {
1008
+ fn from_target ( target : & target:: Target ) -> Self {
1009
+ // for os == "none", cdylib does not make sense. By default cdylib is also not built on
1010
+ // musl, but that can be overriden by the user. That is useful when musl is being used as
1011
+ // main libc, e.g. in Alpine, Gentoo and OpenWRT
1012
+ Self {
1013
+ staticlib : true ,
1014
+ cdylib : target. os != "none" && target. env != "musl" ,
1015
+ }
1016
+ }
1017
+
1018
+ fn from_args ( target : & target:: Target , args : & ArgMatches ) -> Self {
1019
+ match args. get_many :: < String > ( "library-type" ) {
1020
+ Some ( library_types) => Self :: from_library_types ( target, library_types) ,
1021
+ None => Self :: from_target ( target) ,
1022
+ }
1023
+ }
1024
+
1025
+ pub ( crate ) fn from_library_types < S : AsRef < str > > (
1026
+ target : & target:: Target ,
1027
+ library_types : impl Iterator < Item = S > ,
1028
+ ) -> Self {
1029
+ let ( mut staticlib, mut cdylib) = ( false , false ) ;
1030
+
1031
+ for library_type in library_types {
1032
+ staticlib |= library_type. as_ref ( ) == "staticlib" ;
1033
+ cdylib |= library_type. as_ref ( ) == "cdylib" ;
1034
+ }
1035
+
1036
+ // when os is none, a cdylib cannot be produced
1037
+ // forcing a cdylib for musl is allowed here (see [`LibraryTypes::from_target`])
1038
+ cdylib &= target. os != "none" ;
1039
+
1040
+ Self { staticlib, cdylib }
1041
+ }
1042
+
1043
+ const fn only_staticlib ( self ) -> bool {
1044
+ self . staticlib && !self . cdylib
1045
+ }
1046
+
1047
+ const fn only_cdylib ( self ) -> bool {
1048
+ self . cdylib && !self . staticlib
1049
+ }
1050
+ }
1051
+
1001
1052
pub fn cbuild (
1002
1053
ws : & mut Workspace ,
1003
1054
config : & GlobalContext ,
@@ -1006,28 +1057,15 @@ pub fn cbuild(
1006
1057
) -> anyhow:: Result < ( Vec < CPackage > , CompileOptions ) > {
1007
1058
deprecation_warnings ( ws, args) ?;
1008
1059
1009
- let rustc = config. load_global_rustc ( Some ( ws) ) ?;
1010
- let targets = args. targets ( ) ?;
1011
- let ( target, is_target_overridden) = match targets. len ( ) {
1012
- 0 => ( rustc. host . to_string ( ) , false ) ,
1013
- 1 => ( targets[ 0 ] . to_string ( ) , true ) ,
1014
- _ => {
1015
- anyhow:: bail!( "Multiple targets not supported yet" ) ;
1016
- }
1060
+ let ( target, is_target_overridden) = match args. targets ( ) ?. as_slice ( ) {
1061
+ [ ] => ( config. load_global_rustc ( Some ( ws) ) ?. host . to_string ( ) , false ) ,
1062
+ [ target] => ( target. to_string ( ) , true ) ,
1063
+ [ ..] => anyhow:: bail!( "Multiple targets not supported yet" ) ,
1017
1064
} ;
1018
1065
1019
1066
let rustc_target = target:: Target :: new ( Some ( & target) , is_target_overridden) ?;
1020
1067
1021
- let default_kind = || match ( rustc_target. os . as_str ( ) , rustc_target. env . as_str ( ) ) {
1022
- ( "none" , _) | ( _, "musl" ) => vec ! [ "staticlib" ] ,
1023
- _ => vec ! [ "staticlib" , "cdylib" ] ,
1024
- } ;
1025
-
1026
- let libkinds = args
1027
- . get_many :: < String > ( "library-type" )
1028
- . map_or_else ( default_kind, |v| v. map ( String :: as_str) . collect :: < Vec < _ > > ( ) ) ;
1029
- let only_staticlib = !libkinds. contains ( & "cdylib" ) ;
1030
- let only_cdylib = !libkinds. contains ( & "staticlib" ) ;
1068
+ let library_types = LibraryTypes :: from_args ( & rustc_target, args) ;
1031
1069
1032
1070
let profile = args. get_profile_name ( default_profile, ProfileChecking :: Custom ) ?;
1033
1071
@@ -1043,10 +1081,7 @@ pub fn cbuild(
1043
1081
. join ( PathBuf :: from ( target) )
1044
1082
. join ( profiles. get_dir_name ( ) ) ;
1045
1083
1046
- let capi_feature = InternedString :: new ( "capi" ) ;
1047
-
1048
1084
let mut members = Vec :: new ( ) ;
1049
-
1050
1085
let mut pristine = false ;
1051
1086
1052
1087
let requested: Vec < _ > = compile_opts
@@ -1056,22 +1091,23 @@ pub fn cbuild(
1056
1091
. map ( |p| p. package_id ( ) )
1057
1092
. collect ( ) ;
1058
1093
1059
- for m in ws. members_mut ( ) . filter ( |m| {
1060
- m. library ( ) . is_some ( )
1061
- && m. summary ( ) . features ( ) . contains_key ( & capi_feature)
1062
- && requested. contains ( & m. package_id ( ) )
1063
- } ) {
1064
- let cpkg = CPackage :: from_package ( m, args, & libkinds, & rustc_target, & root_output) ?;
1094
+ let capi_feature = InternedString :: new ( "capi" ) ;
1095
+ let is_relevant_package = |package : & Package | {
1096
+ package. library ( ) . is_some ( )
1097
+ && package. summary ( ) . features ( ) . contains_key ( & capi_feature)
1098
+ && requested. contains ( & package. package_id ( ) )
1099
+ } ;
1100
+
1101
+ for m in ws. members_mut ( ) . filter ( |p| is_relevant_package ( p) ) {
1102
+ let cpkg = CPackage :: from_package ( m, args, library_types, & rustc_target, & root_output) ?;
1065
1103
1066
- pristine = pristine || cpkg. finger_print . load_previous ( ) . is_err ( ) ;
1104
+ pristine |= cpkg. finger_print . load_previous ( ) . is_err ( ) ;
1067
1105
1068
1106
members. push ( cpkg) ;
1069
1107
}
1070
1108
1071
- if pristine {
1072
- // If the cache is somehow missing force a full rebuild;
1073
- compile_opts. build_config . force_rebuild = true ;
1074
- }
1109
+ // If the cache is somehow missing force a full rebuild;
1110
+ compile_opts. build_config . force_rebuild |= pristine;
1075
1111
1076
1112
let exec = Arc :: new ( Exec :: default ( ) ) ;
1077
1113
let out_dirs = compile_with_exec (
@@ -1111,7 +1147,7 @@ pub fn cbuild(
1111
1147
// if the hash value does not match.
1112
1148
if new_build && !cpkg. finger_print . is_valid ( ) {
1113
1149
let name = & cpkg. capi_config . library . name ;
1114
- let static_libs = if only_cdylib {
1150
+ let static_libs = if library_types . only_cdylib ( ) {
1115
1151
"" . to_string ( )
1116
1152
} else {
1117
1153
exec. link_line
@@ -1126,14 +1162,14 @@ pub fn cbuild(
1126
1162
let build_targets = & cpkg. build_targets ;
1127
1163
1128
1164
let mut pc = PkgConfig :: from_workspace ( name, & cpkg. install_paths , args, capi_config) ;
1129
- if only_staticlib {
1165
+ if library_types . only_staticlib ( ) {
1130
1166
pc. add_lib ( & static_libs) ;
1131
1167
}
1132
1168
pc. add_lib_private ( & static_libs) ;
1133
1169
1134
1170
build_pc_files ( ws, & capi_config. pkg_config . filename , & root_output, & pc) ?;
1135
1171
1136
- if !only_staticlib && capi_config. library . import_library {
1172
+ if !library_types . only_staticlib ( ) && capi_config. library . import_library {
1137
1173
let lib_name = name;
1138
1174
build_def_file ( ws, lib_name, & rustc_target, & root_output) ?;
1139
1175
build_implib_file ( ws, lib_name, & rustc_target, & root_output) ?;
@@ -1159,7 +1195,7 @@ pub fn cbuild(
1159
1195
& name. replace ( '-' , "_" ) ,
1160
1196
& rustc_target,
1161
1197
& root_output,
1162
- & libkinds ,
1198
+ library_types ,
1163
1199
capi_config,
1164
1200
args. get_flag ( "meson" ) ,
1165
1201
) ?;
0 commit comments