diff --git a/mk/config.mk.in b/mk/config.mk.in
index 40e5e91e92dfec18ec35dc97f470ae17f06623e8..4fac28185469768aee8bc6939fc827e878ff3c01 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -777,6 +777,16 @@ LD_X			= @LdXFlag@
 # overflowing command-line length limits.
 LdIsGNULd		= @LdIsGNULd@
 
+# On MSYS, building with SplitObjs=YES fails with 
+#   ar: Bad file number
+# see #3201.  We need to specify a smaller max command-line size
+# to work around it.  32767 doesn't work; 30000 does.
+ifeq "$(Windows)" "YES"
+XARGS = xargs -s 30000
+else
+XARGS = xargs
+endif
+
 #
 # In emergency situations, REAL_SHELL is used to perform shell commands
 # from within the ghc driver script, by scribbling the command line to
diff --git a/rts/ghc.mk b/rts/ghc.mk
index fba236b88b41c1a039541694cf2d4c6a47fe3c92..a88ea931fe3c1fd12898b37a19f0916345324920 100644
--- a/rts/ghc.mk
+++ b/rts/ghc.mk
@@ -160,7 +160,7 @@ $$(rts_$1_LIB) : $$(rts_$1_OBJS) rts/libs.depend
 else
 $$(rts_$1_LIB) : $$(rts_$1_OBJS)
 	$$(RM) $$@
-	echo $$(rts_$1_OBJS) | xargs $$(AR) $$(EXTRA_AR_ARGS) $$@
+	echo $$(rts_$1_OBJS) | $$(XARGS) $$(AR) $$(EXTRA_AR_ARGS) $$@
 endif
 
 endef
diff --git a/rules/build-package-way.mk b/rules/build-package-way.mk
index 0485a203ccc9627c8cdcb2aa476c69fffdeb896d..b8df37dd052c2919dd9aaf12be0d8c18e86cc7bb 100644
--- a/rules/build-package-way.mk
+++ b/rules/build-package-way.mk
@@ -52,11 +52,11 @@ else
 ifeq "$$($1_$2_SplitObjs)" "YES"
 $$($1_$2_$3_LIB) : $$($1_$2_$3_HS_OBJS) $$($1_$2_v_C_OBJS) $$($1_$2_v_S_OBJS)
 	$$(RM) $$@
-	(echo $$($1_$2_v_C_OBJS) $$($1_$2_v_S_OBJS) `$$($1_$2_$3_MKSTUBOBJS)`; find $$(patsubst %.$$($3_osuf),%_split,$$($1_$2_$3_HS_OBJS)) -name '*.$$($3_osuf)' -print) | xargs $$(AR) $$(EXTRA_AR_ARGS) $$@
+	(echo $$($1_$2_v_C_OBJS) $$($1_$2_v_S_OBJS) `$$($1_$2_$3_MKSTUBOBJS)`; find $$(patsubst %.$$($3_osuf),%_split,$$($1_$2_$3_HS_OBJS)) -name '*.$$($3_osuf)' -print) | $$(XARGS) $$(AR) $$(EXTRA_AR_ARGS) $$@ || $(RM) $$@
 else
 $$($1_$2_$3_LIB) : $$($1_$2_$3_HS_OBJS) $$($1_$2_v_C_OBJS) $$($1_$2_v_S_OBJS)
 	$$(RM) $$@
-	echo $$($1_$2_v_C_OBJS) $$($1_$2_v_S_OBJS) $$($1_$2_$3_HS_OBJS) `$$($1_$2_$3_MKSTUBOBJS)` | xargs $$(AR) $$(EXTRA_AR_ARGS) $$@
+	echo $$($1_$2_v_C_OBJS) $$($1_$2_v_S_OBJS) $$($1_$2_$3_HS_OBJS) `$$($1_$2_$3_MKSTUBOBJS)` | $$(XARGS) $$(AR) $$(EXTRA_AR_ARGS) $$@ || $(RM) $$@
 endif
 endif