Embedding binaries within macOS bundle

Howdy folks, long time listener first time caller etc.

I’m looking for information on how to embed an executable binary within a macOS app bundle when using CMake with Xcode. My project is set up as follows:

Executable target Foo which is built as a “Command Line tool” in Xcode parlance.

Executable target Bar, which is an App target. Bar has a dependency on Foo.

When I build I get both my Foo binary and my Bar.app bundle in my build dir, so far all is well. However what I’d like to accomplish is to embed the Foo binary within the Contents/MacOS directory in the Bar.app bundle.

In Xcode this can easily be done “manually” by adding a Copy Files phase to the target’s “Build Phases” setting Destination to Executables and adding the Foo target to the list of files. This results in the appropriate PBXCopyFilesBuildPhase node in the project.pbxcproj file.

However I’ve been unable to figure out how to do this through CMake, I’ve managed to copy other bundle resources by setting the MACOSX_PACKAGE_LOCATION property on the files, but setting this on the Foo target has no effect. I’ve trawled the internet for solutions but haven’t been able to find anything so far, is there a “canonical” way of doing this with CMake?

Thanks!

CMake’s own packaging does something like this where these binaries live in Contents/bin. The only detail that I can think of is to install the main program first and then the helpers.

Thanks! Would you be able to point me in the general direction of where this is done in the CMake repository? I had a search for bin/ but it wasn’t that fruitful.

I’m not sure exactly. @brad.king?

They are not integrated in CMake’s build tree, but we use a symlink there to put cmake-gui next to the rest of the binaries in the bin directory.

The integration occurs during installation. CMake.app is installed by this code to the real install prefix, and then all the rest of the files go to the prefix with CMake.app/Contents appended. See this code.

The same installation process is used during packaging with CPack to produce our official binaries.

Thanks for the answers both of you, that’s very helpful.

Symlinking when building and then doing the copying during installation seems like a good approach.

Can I ask why the “native” way isn’t supported? Given that we can populate other bundle directories like Frameworks/ & Resources/ using the MACOSX_PACKAGE_LOCATION property, why not do something similar for executables? It would be really nice to be able to set a property on a bundle target where I can specify an executable and have that copied into the bundle’s MacOS/ directory.

Cheers!

That feels like it would be a property that ultimately depends on consumers. If I have a not_a_bundle executable with a property of MACOSX_PACKAGE_LOCATION, what is responsible for putting it into the bundle? Which bundle? Multiple?

That’s a good point. I’m not too familiar with CMake in this regard but I suppose the bundle concept doesn’t really make sense outside of Apple platforms, might be hard to express that an executable should contain another executable in a cross-platform way.

The benefit of doing it in XCode seems to be that the build system is a bit more intelligent in what it needs to copy and when, but symlinking is not an expensive operation so that isn’t really a big deal.

Thanks for the help!