@@ -103,28 +103,27 @@ fn build_pc_files(
103
103
104
104
fn patch_target (
105
105
pkg : & mut Package ,
106
- libkinds : & [ & str ] ,
106
+ library_types : LibraryTypes ,
107
107
capi_config : & CApiConfig ,
108
108
) -> anyhow:: Result < ( ) > {
109
109
use cargo:: core:: compiler:: CrateType ;
110
110
111
111
let manifest = pkg. manifest_mut ( ) ;
112
112
let targets = manifest. targets_mut ( ) ;
113
113
114
- let kinds: Vec < _ > = libkinds
115
- . iter ( )
116
- . map ( |& kind| match kind {
117
- "staticlib" => CrateType :: Staticlib ,
118
- "cdylib" => CrateType :: Cdylib ,
119
- _ => unreachable ! ( ) ,
120
- } )
121
- . collect ( ) ;
114
+ let mut kinds = Vec :: with_capacity ( 2 ) ;
122
115
123
- for target in targets. iter_mut ( ) {
124
- if target. is_lib ( ) {
125
- target. set_kind ( TargetKind :: Lib ( kinds. clone ( ) ) ) ;
126
- target. set_name ( & capi_config. library . name ) ;
127
- }
116
+ if library_types. staticlib {
117
+ kinds. push ( CrateType :: Staticlib ) ;
118
+ }
119
+
120
+ if library_types. cdylib {
121
+ kinds. push ( CrateType :: Cdylib ) ;
122
+ }
123
+
124
+ for target in targets. iter_mut ( ) . filter ( |t| t. is_lib ( ) ) {
125
+ target. set_kind ( TargetKind :: Lib ( kinds. to_vec ( ) ) ) ;
126
+ target. set_name ( & capi_config. library . name ) ;
128
127
}
129
128
130
129
Ok ( ( ) )
@@ -953,7 +952,7 @@ impl CPackage {
953
952
fn from_package (
954
953
pkg : & mut Package ,
955
954
args : & ArgMatches ,
956
- libkinds : & [ & str ] ,
955
+ library_types : LibraryTypes ,
957
956
rustc_target : & target:: Target ,
958
957
root_output : & Path ,
959
958
) -> anyhow:: Result < CPackage > {
@@ -962,7 +961,7 @@ impl CPackage {
962
961
let root_path = pkg. root ( ) . to_path_buf ( ) ;
963
962
let capi_config = load_manifest_capi_config ( pkg, rustc_target) ?;
964
963
965
- patch_target ( pkg, libkinds , & capi_config) ?;
964
+ patch_target ( pkg, library_types , & capi_config) ?;
966
965
967
966
let name = & capi_config. library . name ;
968
967
@@ -971,7 +970,7 @@ impl CPackage {
971
970
name,
972
971
rustc_target,
973
972
root_output,
974
- libkinds ,
973
+ library_types ,
975
974
& capi_config,
976
975
args. get_flag ( "meson" ) ,
977
976
) ?;
@@ -999,6 +998,63 @@ fn deprecation_warnings(ws: &Workspace, args: &ArgMatches) -> anyhow::Result<()>
999
998
Ok ( ( ) )
1000
999
}
1001
1000
1001
+ /// What library types to build
1002
+ #[ derive( Debug , Clone , Copy ) ]
1003
+ pub struct LibraryTypes {
1004
+ pub staticlib : bool ,
1005
+ pub cdylib : bool ,
1006
+ }
1007
+
1008
+ impl LibraryTypes {
1009
+ fn from_target ( target : & target:: Target ) -> Self {
1010
+ // for os == "none", cdylib does not make sense. By default cdylib is also not built on
1011
+ // musl, but that can be overriden by the user. That is useful when musl is being used as
1012
+ // main libc, e.g. in Alpine, Gentoo and OpenWRT
1013
+ //
1014
+ // See also
1015
+ //
1016
+ // - https://github.com/lu-zero/cargo-c?tab=readme-ov-file#shared-libraries-are-not-built-on-musl-systems
1017
+ // - https://github.com/lu-zero/cargo-c/issues/180
1018
+ Self {
1019
+ staticlib : true ,
1020
+ cdylib : target. os != "none" && target. env != "musl" ,
1021
+ }
1022
+ }
1023
+
1024
+ fn from_args ( target : & target:: Target , args : & ArgMatches ) -> Self {
1025
+ match args. get_many :: < String > ( "library-type" ) {
1026
+ Some ( library_types) => Self :: from_library_types ( target, library_types) ,
1027
+ None => Self :: from_target ( target) ,
1028
+ }
1029
+ }
1030
+
1031
+ pub ( crate ) fn from_library_types < S : AsRef < str > > (
1032
+ target : & target:: Target ,
1033
+ library_types : impl Iterator < Item = S > ,
1034
+ ) -> Self {
1035
+ let ( mut staticlib, mut cdylib) = ( false , false ) ;
1036
+
1037
+ for library_type in library_types {
1038
+ staticlib |= library_type. as_ref ( ) == "staticlib" ;
1039
+ cdylib |= library_type. as_ref ( ) == "cdylib" ;
1040
+ }
1041
+
1042
+ // when os is none, a cdylib cannot be produced
1043
+ // forcing a cdylib for musl is allowed here (see [`LibraryTypes::from_target`])
1044
+ cdylib &= target. os != "none" ;
1045
+
1046
+ Self { staticlib, cdylib }
1047
+ }
1048
+
1049
+ const fn only_staticlib ( self ) -> bool {
1050
+ self . staticlib && !self . cdylib
1051
+ }
1052
+
1053
+ const fn only_cdylib ( self ) -> bool {
1054
+ self . cdylib && !self . staticlib
1055
+ }
1056
+ }
1057
+
1002
1058
fn static_libraries ( link_line : & str , rustc_target : & target:: Target ) -> String {
1003
1059
link_line
1004
1060
. trim ( )
@@ -1029,28 +1085,15 @@ pub fn cbuild(
1029
1085
) -> anyhow:: Result < ( Vec < CPackage > , CompileOptions ) > {
1030
1086
deprecation_warnings ( ws, args) ?;
1031
1087
1032
- let rustc = config. load_global_rustc ( Some ( ws) ) ?;
1033
- let targets = args. targets ( ) ?;
1034
- let ( target, is_target_overridden) = match targets. len ( ) {
1035
- 0 => ( rustc. host . to_string ( ) , false ) ,
1036
- 1 => ( targets[ 0 ] . to_string ( ) , true ) ,
1037
- _ => {
1038
- anyhow:: bail!( "Multiple targets not supported yet" ) ;
1039
- }
1088
+ let ( target, is_target_overridden) = match args. targets ( ) ?. as_slice ( ) {
1089
+ [ ] => ( config. load_global_rustc ( Some ( ws) ) ?. host . to_string ( ) , false ) ,
1090
+ [ target] => ( target. to_string ( ) , true ) ,
1091
+ [ ..] => anyhow:: bail!( "Multiple targets not supported yet" ) ,
1040
1092
} ;
1041
1093
1042
1094
let rustc_target = target:: Target :: new ( Some ( & target) , is_target_overridden) ?;
1043
1095
1044
- let default_kind = || match ( rustc_target. os . as_str ( ) , rustc_target. env . as_str ( ) ) {
1045
- ( "none" , _) | ( _, "musl" ) => vec ! [ "staticlib" ] ,
1046
- _ => vec ! [ "staticlib" , "cdylib" ] ,
1047
- } ;
1048
-
1049
- let libkinds = args
1050
- . get_many :: < String > ( "library-type" )
1051
- . map_or_else ( default_kind, |v| v. map ( String :: as_str) . collect :: < Vec < _ > > ( ) ) ;
1052
- let only_staticlib = !libkinds. contains ( & "cdylib" ) ;
1053
- let only_cdylib = !libkinds. contains ( & "staticlib" ) ;
1096
+ let library_types = LibraryTypes :: from_args ( & rustc_target, args) ;
1054
1097
1055
1098
let profile = args. get_profile_name ( default_profile, ProfileChecking :: Custom ) ?;
1056
1099
@@ -1066,10 +1109,7 @@ pub fn cbuild(
1066
1109
. join ( PathBuf :: from ( target) )
1067
1110
. join ( profiles. get_dir_name ( ) ) ;
1068
1111
1069
- let capi_feature = InternedString :: new ( "capi" ) ;
1070
-
1071
1112
let mut members = Vec :: new ( ) ;
1072
-
1073
1113
let mut pristine = false ;
1074
1114
1075
1115
let requested: Vec < _ > = compile_opts
@@ -1079,22 +1119,23 @@ pub fn cbuild(
1079
1119
. map ( |p| p. package_id ( ) )
1080
1120
. collect ( ) ;
1081
1121
1082
- for m in ws. members_mut ( ) . filter ( |m| {
1083
- m. library ( ) . is_some ( )
1084
- && m. summary ( ) . features ( ) . contains_key ( & capi_feature)
1085
- && requested. contains ( & m. package_id ( ) )
1086
- } ) {
1087
- let cpkg = CPackage :: from_package ( m, args, & libkinds, & rustc_target, & root_output) ?;
1122
+ let capi_feature = InternedString :: new ( "capi" ) ;
1123
+ let is_relevant_package = |package : & Package | {
1124
+ package. library ( ) . is_some ( )
1125
+ && package. summary ( ) . features ( ) . contains_key ( & capi_feature)
1126
+ && requested. contains ( & package. package_id ( ) )
1127
+ } ;
1128
+
1129
+ for m in ws. members_mut ( ) . filter ( |p| is_relevant_package ( p) ) {
1130
+ let cpkg = CPackage :: from_package ( m, args, library_types, & rustc_target, & root_output) ?;
1088
1131
1089
- pristine = pristine || cpkg. finger_print . load_previous ( ) . is_err ( ) ;
1132
+ pristine |= cpkg. finger_print . load_previous ( ) . is_err ( ) ;
1090
1133
1091
1134
members. push ( cpkg) ;
1092
1135
}
1093
1136
1094
- if pristine {
1095
- // If the cache is somehow missing force a full rebuild;
1096
- compile_opts. build_config . force_rebuild = true ;
1097
- }
1137
+ // If the cache is somehow missing force a full rebuild;
1138
+ compile_opts. build_config . force_rebuild |= pristine;
1098
1139
1099
1140
let exec = Arc :: new ( Exec :: default ( ) ) ;
1100
1141
let out_dirs = compile_with_exec (
@@ -1134,7 +1175,7 @@ pub fn cbuild(
1134
1175
// if the hash value does not match.
1135
1176
if new_build && !cpkg. finger_print . is_valid ( ) {
1136
1177
let name = & cpkg. capi_config . library . name ;
1137
- let ( pkg_config_static_libs, static_libs) = if only_cdylib {
1178
+ let ( pkg_config_static_libs, static_libs) = if library_types . only_cdylib ( ) {
1138
1179
( String :: new ( ) , String :: new ( ) )
1139
1180
} else if let Some ( libs) = exec. link_line . lock ( ) . unwrap ( ) . values ( ) . next ( ) {
1140
1181
( static_libraries ( libs, & rustc_target) , libs. to_string ( ) )
@@ -1145,14 +1186,14 @@ pub fn cbuild(
1145
1186
let build_targets = & cpkg. build_targets ;
1146
1187
1147
1188
let mut pc = PkgConfig :: from_workspace ( name, & cpkg. install_paths , args, capi_config) ;
1148
- if only_staticlib {
1189
+ if library_types . only_staticlib ( ) {
1149
1190
pc. add_lib ( & pkg_config_static_libs) ;
1150
1191
}
1151
1192
pc. add_lib_private ( & pkg_config_static_libs) ;
1152
1193
1153
1194
build_pc_files ( ws, & capi_config. pkg_config . filename , & root_output, & pc) ?;
1154
1195
1155
- if !only_staticlib && capi_config. library . import_library {
1196
+ if !library_types . only_staticlib ( ) && capi_config. library . import_library {
1156
1197
let lib_name = name;
1157
1198
build_def_file ( ws, lib_name, & rustc_target, & root_output) ?;
1158
1199
build_implib_file ( ws, lib_name, & rustc_target, & root_output) ?;
@@ -1178,7 +1219,7 @@ pub fn cbuild(
1178
1219
& name. replace ( '-' , "_" ) ,
1179
1220
& rustc_target,
1180
1221
& root_output,
1181
- & libkinds ,
1222
+ library_types ,
1182
1223
capi_config,
1183
1224
args. get_flag ( "meson" ) ,
1184
1225
) ?;
@@ -1350,17 +1391,17 @@ mod tests {
1350
1391
let target_msvc = target:: Target :: new ( Some ( "x86_64-pc-windows-msvc" ) , false ) . unwrap ( ) ;
1351
1392
let target_mingw = target:: Target :: new ( Some ( "x86_64-pc-windows-gnu" ) , false ) . unwrap ( ) ;
1352
1393
1353
- assert_eq ! ( static_libraries( & libs_osx, & target_osx) , "-lSystem -lc -lm" ) ;
1394
+ assert_eq ! ( static_libraries( libs_osx, & target_osx) , "-lSystem -lc -lm" ) ;
1354
1395
assert_eq ! (
1355
- static_libraries( & libs_linux, & target_linux) ,
1396
+ static_libraries( libs_linux, & target_linux) ,
1356
1397
"-lgcc_s -lutil -lrt -lpthread -lm -ldl -lc"
1357
1398
) ;
1358
1399
assert_eq ! (
1359
- static_libraries( & libs_msvc, & target_msvc) ,
1400
+ static_libraries( libs_msvc, & target_msvc) ,
1360
1401
"-lkernel32 -ladvapi32 -lntdll -luserenv -lws2_32 -lmsvcrt"
1361
1402
) ;
1362
1403
assert_eq ! (
1363
- static_libraries( & libs_mingw, & target_mingw) ,
1404
+ static_libraries( libs_mingw, & target_mingw) ,
1364
1405
"-lkernel32 -ladvapi32 -lntdll -luserenv -lws2_32"
1365
1406
) ;
1366
1407
}
0 commit comments