Skip to content

MacOS development setup

Javier Gonzalez edited this page Apr 30, 2026 · 1 revision

The ds repo contains files whose names differ only in case (e.g. Aca_Id_Image.cc and aca_id_image.cc in the same directory). APFS is case-insensitive by default: if you check this repo out onto a stock macOS volume, the second filename in each pair silently overwrites the first, and one file is lost. Sometimes the lost file is a stale duplicate; sometimes it is the live implementation.

This document is the breadcrumb trail for setting up a Mac so you do not lose source files when working with this repo.

Show collisions

The easiest way to see the name collisions is to rsync the DS repo into Mac OSX. A git status command will yield something like:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   arcclient/ocat/ZeroOffsetAimpoints.cc
        modified:   dslibs/aplib/Tokenizer.cc
        modified:   dslibs/comm/IPCClient.cc
        modified:   dslibs/comm/IPCServer.cc
        modified:   dslibs/gen/regtest/BTree.t1.baseline
        modified:   dslibs/gen/regtest/BTree.t1.test
        modified:   dslibs/gen/regtest/Queue.t1.baseline
        modified:   dslibs/gen/regtest/Queue.t1.test
        modified:   dslibs/gen/regtest/SArray.t1.baseline
        modified:   dslibs/gen/regtest/SArray.t1.test
        modified:   dslibs/gen/regtest/Stack.t1.baseline
        modified:   dslibs/gen/regtest/Stack.t1.test
        modified:   dstools/asp/aca_calc_photom/Aca_Calc_Photom.cc
        modified:   dstools/asp/aca_id_image/Aca_Id_Image.cc
        modified:   dstools/asp/asp_calc_boresight/Asp_Calc_Boresight.cc
        modified:   dstools/asp/asp_calc_photo/ASP_Calc_Photo.cc
        modified:   dstools/asp/asp_calc_photo/ASP_Calc_Photo.hh
        modified:   dstools/asp/asp_make_qualint/Asp_Make_Qualint.cc
        modified:   dstools/asp/asp_make_qualint/Asp_Make_Qualint.hh
        modified:   dstools/asp/asp_sgt2cent/ASP_Sgt2cent.cc
        modified:   dstools/asp/asp_sgt2cent/ASP_Sgt2cent.hh
        modified:   dstools/mta/monitor/mta_gen_fidhtml/MTA_HTML.cc
        modified:   dstools/mta/monitor/mta_gen_fidhtml/MTA_HTML.hh
        modified:   dstools/mta/monitor/mta_merge_files/MTA_Merge_Files.cc

All those "modified" files are just missing files, that the file system replaces with a similarly named file.

The fix: a case-sensitive sparse bundle

A separate APFS volume in the system disk container would be cleaner, but on Apple Silicon you typically hit Error: -69493: You can't add any more APFS Volumes to its APFS Container. A sparse bundle is the workaround — a self-contained file that behaves like a volume, grows on demand, and bypasses the container limit.

hdiutil create -size 50g -fs "Case-sensitive APFS" \
    -type SPARSEBUNDLE -volname chandra-ds-source ~/chandra-ds-source

This creates ~/chandra-ds-source.sparsebundle. Mount it manually with:

hdiutil attach ~/chandra-ds-source.sparsebundle    # mounts at /Volumes/chandra-ds-source
hdiutil detach /Volumes/chandra-ds-source          # unmount

Clone the repo into /Volumes/chandra-ds-source/ds and work there. All file operations on that volume are case-sensitive, so the upstream sources coexist correctly.

Auto-mount at login

~/Library/LaunchAgents/com.javierg.chandra-ds-source.plist runs hdiutil attach at login so the volume is always available:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.javierg.chandra-ds-source</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/hdiutil</string>
        <string>attach</string>
        <string>-nobrowse</string>
        <string>/Users/javierg/chandra-ds-source.sparsebundle</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/Users/javierg/Library/Logs/chandra-ds-source-mount.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/javierg/Library/Logs/chandra-ds-source-mount.log</string>
</dict>
</plist>

To activate without logging out:

launchctl load ~/Library/LaunchAgents/com.javierg.chandra-ds-source.plist

To remove the auto-mount:

launchctl unload ~/Library/LaunchAgents/com.javierg.chandra-ds-source.plist
rm ~/Library/LaunchAgents/com.javierg.chandra-ds-source.plist

-nobrowse keeps the volume off the Finder sidebar. Drop that argument if you want the volume visible.

Verify

mount | grep chandra-ds-source                          # should show /Volumes/chandra-ds-source
diskutil info /Volumes/chandra-ds-source | grep -i case # "Case-sensitive: Yes"
tail ~/Library/Logs/chandra-ds-source-mount.log         # check launchd output if mount failed

A quick functional check — these two paths should be distinct files on the case-sensitive volume:

cd /Volumes/chandra-ds-source/ds
ls dstools/asp/aca_id_image/Aca_Id_Image.cc dstools/asp/aca_id_image/aca_id_image.cc

Why not just rename one file?

Renaming Aca_Id_Image.ccAca_Id_Image_main.cc would break the collision but creates a permanent local fork: each renamed file forces edits to its CMakeLists.txt SRCS line and to every #include that names it, and the patch must be kept out of upstream commits forever. Survivable for a one-off audit, painful as an ongoing workspace. Use the sparse bundle.