Is clang-fat.sh only for SDL2, or can it work for SDL2_image, _mixer, etc?

I’m trying to create a universal binary for a MacOS build, and I need my dependencies to be universal as well.

After trying to figure out how to cross-compile myself, I eventually learned that SDL2’s build-scripts directory has a clang-fat.sh file. It worked great to create an SDL2 library:

$ file mac/lib/*
mac/lib/libSDL2-2.0.0.dylib: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64Mach-O 64-bit dynamically linked shared library x86_64] [arm64]
mac/lib/libSDL2-2.0.0.dylib (for architecture x86_64):	Mach-O 64-bit dynamically linked shared library x86_64
mac/lib/libSDL2-2.0.0.dylib (for architecture arm64):	Mach-O 64-bit dynamically linked shared library arm64
...

However, a similar script does not exist in SDL2_image. If I try to use SDL2’s script to configure and build SDL2_image, I get an error:

$ ./configure CC="sh ../SDL2-2.32.8/build-scripts/clang-fat.sh" --prefix=/Users/[my_username]/Projects/Tools/CustomLibs/mac && make && make install && rm -rf arm64 x64

...
+ shift
+ test x '!=' x
+ clang -arch x86_64 -mmacosx-version-min=10.9 -DMAC_OS_X_VERSION_MIN_REQUIRED=1070 -I/usr/local/include -mmacosx-version-min=10.9 '-DPACKAGE_NAME="SDL2_image"' '-DPACKAGE_TARNAME="SDL2_image"' '-DPACKAGE_VERSION="2.8.8"' '-DPACKAGE_STRING="SDL2_image' '2.8.8"' '-DPACKAGE_BUGREPORT="https://github.com/libsdl-org/SDL_image/issues"' '-DPACKAGE_URL=""' -DHAVE_STDIO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 -DHAVE_DLFCN_H=1 '-DLT_OBJDIR=".libs/"' -DSDL_BUILD_MAJOR_VERSION=2 -DSDL_BUILD_MINOR_VERSION=8 -DSDL_BUILD_MICRO_VERSION=8 '-DPACKAGE="SDL2_image"' '-DVERSION="2.8.8"' -DUSE_STBIMAGE=1 -DLOAD_JPG=1 -DLOAD_PNG=1 -DLOAD_BMP=1 -DLOAD_GIF=1 -DLOAD_LBM=1 -DLOAD_PCX=1 -DLOAD_PNM=1 -DLOAD_SVG=1 -DLOAD_TGA=1 -DLOAD_XCF=1 -DLOAD_XPM=1 -DLOAD_XV=1 -DLOAD_QOI=1 -DSDL_IMAGE_SAVE_PNG=1 -DSDL_IMAGE_SAVE_JPG=1 -I. -I./include -g -O2 -I/Users/[my_username]/Projects/Tools/CustomLibs/mac/include/SDL2 -D_THREAD_SAFE -Wall -fvisibility=hidden -c -o examples/showimage-showimage.o examples/showimage.c
../SDL2-2.32.8/build-scripts/clang-fat.sh: line 27: test: too many arguments
clang: error: no such file or directory: '2.8.8"'
make[1]: *** [examples/showimage-showimage.o] Error 1
make: *** [all-recursive] Error 1

I’m trying to debug it, but I wonder if clang-fat.sh isn’t meant to work universally across all SDL2_* libs and so I shouldn’t be trying to make it work and instead focus my efforts elsewhere.

Does anyone know?

does your username, which you omitted (okay), contains spaces? (I don’t think this matters)

consider this is a POSIX shell script, not a Bash script. shift is a command that removes the first argument and shifts all arguments to the “left”, so the second argument becomes the first argument, and the third argument becomes the second, etc. (terrible explanation)

try to modify this script and make it print stuff.

but this “too many arguments” catches my attention.

here is the exact problem:

test command excepts three arguments. because x$1 is unquoted, it is possibly expanding your username or something else as two or more strings, instead of only one.

modify line 27 to replace x$1 to "x$1" (without the backticks used for formatting)

It does not.

This part of the output:

clang: error: no such file or directory: '2.8.8"'

The only thing I noticed is when I tried making things verbose is this:

'-DPACKAGE_STRING="SDL2_image' '2.8.8"'

And looking at config.log, I see:
PACKAGE_STRING='SDL2_image 2.8.8'

In the SDL2 library, it does not seem to specify PACKAGE_STRING. It’s an empty string. I am not sure if it matters.

great catch! the quoting there is really odd. I think it should be:

'-DPACKAGE_STRING="SDL2_image 2.8.8"'

regardless. I quickly cloned both SDL and SDL_image in SDL2 branch and greped PACKAGE_STRING, it doesn’t occur in code, so I’d say it doesn’t matter. I believe you can safely define this macro as an empty string as well

I feel like I’m yak-shaving trying to get to this point, but after figuring that out, if I try to run configure and build the project, I ultimately get:

libtool: link: sh /Users/[my_username]/Projects/wc_Proj/Proj/bin/MacLibs/SDL2-2.32.8/build-scripts/clang-fat.sh -dynamiclib  -o .libs/libSDL2_image-2.0.0.dylib  src/.libs/libSDL2_image_la-IMG.o src/.libs/libSDL2_image_la-IMG_avif.o src/.libs/libSDL2_image_la-IMG_bmp.o src/.libs/libSDL2_image_la-IMG_gif.o src/.libs/libSDL2_image_la-IMG_jpg.o src/.libs/libSDL2_image_la-IMG_jxl.o src/.libs/libSDL2_image_la-IMG_lbm.o src/.libs/libSDL2_image_la-IMG_pcx.o src/.libs/libSDL2_image_la-IMG_png.o src/.libs/libSDL2_image_la-IMG_pnm.o src/.libs/libSDL2_image_la-IMG_qoi.o src/.libs/libSDL2_image_la-IMG_svg.o src/.libs/libSDL2_image_la-IMG_stb.o src/.libs/libSDL2_image_la-IMG_tga.o src/.libs/libSDL2_image_la-IMG_tif.o src/.libs/libSDL2_image_la-IMG_xcf.o src/.libs/libSDL2_image_la-IMG_xpm.o src/.libs/libSDL2_image_la-IMG_xv.o src/.libs/libSDL2_image_la-IMG_webp.o src/.libs/libSDL2_image_la-IMG_WIC.o src/.libs/libSDL2_image_la-IMG_ImageIO.o   -L/Users/[my_username]/Projects/Tools/CustomLibs/mac/lib /Users/[my_username]/Projects/Tools/CustomLibs/mac/lib/libSDL2.dylib -lm -lobjc  -Wl,-undefined -Wl,error -Wl,-framework -Wl,ApplicationServices   -install_name  /Users/[my_username]/Projects/Tools/CustomLibs/mac/lib/libSDL2_image-2.0.0.dylib -compatibility_version 801 -current_version 801.8 -Wl,-single_module
ld: warning: object file (src/.libs/libSDL2_image_la-IMG_ImageIO.o) was built for newer macOS version (12.0) than being linked (10.9)
ld: warning: ignoring file src/.libs/libSDL2_image_la-IMG_ImageIO.o, building for macOS-arm64 but attempting to link with file built for unknown-x86_64
Undefined symbols for architecture arm64:
  "_IMG_InitTIF", referenced from:
      _IMG_Init in libSDL2_image_la-IMG.o
  "_IMG_Load", referenced from:
      _IMG_LoadTexture in libSDL2_image_la-IMG.o
     (maybe you meant: _IMG_LoadSizedSVG_RW, _IMG_LoadAnimation_RW , _IMG_LoadPNG_RW , _IMG_LoadICO_RW , _IMG_LoadJXL_RW , _IMG_LoadXPM_RW , _IMG_LoadTexture_RW , _IMG_LoadCUR_RW , _IMG_LoadTyped_RW , _IMG_LoadPNM_RW , _IMG_Load_RW , _IMG_LoadWEBPAnimation_RW , _IMG_LoadTexture , _IMG_LoadSVG_RW , _IMG_LoadBMP_RW , _IMG_LoadJPG_RW , _IMG_LoadAVIF_RW , _IMG_LoadQOI_RW , _IMG_LoadGIFAnimation_RW , _IMG_LoadAnimation , _IMG_LoadTextureTyped_RW , _IMG_LoadAnimationTyped_RW , _IMG_LoadPCX_RW , _IMG_LoadXCF_RW , _IMG_LoadSTB_RW , _IMG_LoadWEBP_RW , _IMG_LoadLBM_RW , _IMG_LoadXV_RW )
  "_IMG_LoadGIF_RW", referenced from:
      _supported in libSDL2_image_la-IMG.o
  "_IMG_LoadTGA_RW", referenced from:
      _supported in libSDL2_image_la-IMG.o
  "_IMG_LoadTIF_RW", referenced from:
      _supported in libSDL2_image_la-IMG.o
  "_IMG_QuitTIF", referenced from:
      _IMG_Quit in libSDL2_image_la-IMG.o
  "_IMG_isGIF", referenced from:
      _IMG_LoadAnimationTyped_RW in libSDL2_image_la-IMG.o
      _supported in libSDL2_image_la-IMG.o
      _supported_anims in libSDL2_image_la-IMG.o
  "_IMG_isTIF", referenced from:
      _supported in libSDL2_image_la-IMG.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[4]: *** [libSDL2_image.la] Error 1
make[3]: *** [all-recursive] Error 1
make[2]: *** [CMakeFiles/SDL2_IMAGE_SHARED_LIBRARY] Error 2
make[1]: *** [CMakeFiles/SDL2_IMAGE_SHARED_LIBRARY.dir/all] Error 2
make: *** [all] Error 2

I don’t see a similar warning about the macOS version in the main SDL2 library.

Anyway, it seems like it is trying to link to the wrong things, specifically for arm64. I see the x64/.libs directory that produced the libSDL2_image-2.0.0.dylib successfully, but the arm64/.libs did not.

There are arm64 object files in arm64/src, so it built them in the right place, but it is clearly not linking to the right files.

Actually, what might be happening is that some files are becoming universal binaries, and others aren’t.

When I look at src/.libs, I see some .o files, and some are universal, and some are only x86_64.

Specifically, I can see why this error makes sense now:

$ file bin/MacLibs/SDL2_image-2.8.8/src/.libs/libSDL2_image_la-IMG_ImageIO.o 
bin/MacLibs/SDL2_image-2.8.8/src/.libs/libSDL2_image_la-IMG_ImageIO.o: Mach-O 64-bit object x86_64

It looks like this libSDL2_image_la-IMG_ImageIO.o isn’t built for arm64, so of course it can’t link.

Looking at the logs, I noticed that by and large it uses the clang-fat.sh to compile, but once in awhile, it uses gcc:

libtool: compile:  sh /Users/[my_username]/Projects/wc_Proj/Proj/bin/MacLibs/SDL2-2.32.8/build-scripts/clang-fat.sh -DPACKAGE_NAME=\"SDL2_image\" -DPACKAGE_TARNAME=\"SDL2_image\" -DPACKAGE_VERSION=\"2.8.8\" -DPACKAGE_STRING=\"SDL2_image_2.8.8\" -DPACKAGE_BUGREPORT=\"https://github.com/libsdl-org/SDL_image/issues\" -DPACKAGE_URL=\"\" -DHAVE_STDIO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DSDL_BUILD_MAJOR_VERSION=2 -DSDL_BUILD_MINOR_VERSION=8 -DSDL_BUILD_MICRO_VERSION=8 -DPACKAGE=\"SDL2_image\" -DVERSION=\"2.8.8\" -DUSE_STBIMAGE=1 -DLOAD_PNG=1 -DLOAD_SVG=1 -DLOAD_QOI=1 -DSDL_IMAGE_SAVE_PNG=1 -DSDL_IMAGE_SAVE_JPG=1 -I. -I./include -g -O2 -I/Users/[my_username]/Projects/Tools/CustomLibs/mac/include/SDL2 -D_THREAD_SAFE -Wall -fvisibility=hidden -MT src/libSDL2_image_la-IMG_WIC.lo -MD -MP -MF src/.deps/libSDL2_image_la-IMG_WIC.Tpo -c src/IMG_WIC.c  -fno-common -DPIC -o src/.libs/libSDL2_image_la-IMG_WIC.o

libtool: compile:  gcc -DPACKAGE_NAME=\"SDL2_image\" -DPACKAGE_TARNAME=\"SDL2_image\" -DPACKAGE_VERSION=\"2.8.8\" -DPACKAGE_STRING=\"SDL2_image_2.8.8\" -DPACKAGE_BUGREPORT=\"https://github.com/libsdl-org/SDL_image/issues\" -DPACKAGE_URL=\"\" -DHAVE_STDIO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_UNISTD_H=1 -DSTDC_HEADERS=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DSDL_BUILD_MAJOR_VERSION=2 -DSDL_BUILD_MINOR_VERSION=8 -DSDL_BUILD_MICRO_VERSION=8 -DPACKAGE=\"SDL2_image\" -DVERSION=\"2.8.8\" -DUSE_STBIMAGE=1 -DLOAD_PNG=1 -DLOAD_SVG=1 -DLOAD_QOI=1 -DSDL_IMAGE_SAVE_PNG=1 -DSDL_IMAGE_SAVE_JPG=1 -I. -I./include -g -O2 -I/Users/[my_username]/Projects/Tools/CustomLibs/mac/include/SDL2 -D_THREAD_SAFE -Wall -fvisibility=hidden -MT src/libSDL2_image_la-IMG_ImageIO.lo -MD -MP -MF src/.deps/libSDL2_image_la-IMG_ImageIO.Tpo -c src/IMG_ImageIO.m  -fno-common -DPIC -o src/.libs/libSDL2_image_la-IMG_ImageIO.o

So it looks like when it compiles a .c file, it uses the clang-fat.sh script, but when it compiles the .m file, it uses gcc, which means it doesn’t get the benefit of making a universal .o.

I’ll have to try it when I get time, but it looks like I’ll need to set not only CC but also OBJC to that clang-fat.sh.