2

Our company uses CMake currently to build our executables for Windows. I'm working on making our application work on Mac. So far the application builds fine on the Mac. However, when I try to open the Executable that CMake creates for the Mac, I get the following error in a terminal window:

Last login: Tue Apr 16 14:34:58 on ttys001
Locals-MacBook-Pro:~ auser$ /Users/auser/Documents/Projects/CodeMonkey/bin/CmDeveloperKit ; exit;
dyld: Library not loaded: libAbcSupport.dylib
  Referenced from: /Users/auser/Documents/Projects/CodeMonkey/bin/CmDeveloperKit
  Reason: image not found
Trace/BPT trap: 5
logout

[Process completed]

I'm thinking that the CMakeLists.txt for the project might not be setup correctly to build the executable for the Mac. I've included it below:

# Includes the common stuff for CodeMonkey
include(CmConfig)

# Set the file description
set(CMDEVELOPERKIT_FILE_DESCRIPTION "CodeMonkey Application")

# Configures this CodeMonkey module
CmModuleConfig(CmDeveloperKit FIND CodeMonkey CodeMonkeyGui)

# Get source files for CodeMonkeyGui
set(PROJECT_SOURCES ${PROJECT_SOURCES} Main.cpp)
# Only add resource files on Windows
if(WIN32)
  # Get header files for CodeMonkeyGui
  set(PROJECT_HEADERS ${PROJECT_HEADERS} CmIcon.h)
  # Get source files for CodeMonkeyGui
  set(PROJECT_RESOURCES ${PROJECT_RESOURCES} CmIcon.rc)
endif(WIN32)

# Add additional include directories
include_directories(${CODEMONKEY_INCLUDE_DIR} ${CODEMONKEYGUI_INCLUDE_DIR} ${ABC_INCLUDE_DIR})
# Add additional link directories
link_directories("${ABC_LIBRARY_DIR}")

# Creates the executable
if(WIN32)
  add_executable(${PROJECT_NAME} WIN32 ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${PROJECT_RESOURCES})
  # Sets entry point to main
  set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/ENTRY:\"mainCRTStartup\"")
else()
  add_executable(${PROJECT_NAME} ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${PROJECT_RESOURCES})
endif(WIN32)

# Add the d in debug
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX d)

# Links to the other required libs
target_link_libraries(${PROJECT_NAME} ${CODEMONKEY_LIBRARY} ${CODEMONKEYGUI_LIBRARY} 
                      ${ABC_ARASUPPORT_LIBRARY} ${ABC_ARAGUI_LIBRARY})
# Sets the appropriate dependencies
add_dependencies(${PROJECT_NAME} ${CODEMONKEY_NAME} ${CODEMONKEYGUI_NAME})

# Configure the install procedures
CmModuleInstall()

Could someone please let me know what I'm missing or have wrong in the above file? If this file is not the issue can you point me in the right direction for a fix?

Alexander Shukaev
  • 16,674
  • 8
  • 70
  • 85
robhasacamera
  • 2,967
  • 2
  • 28
  • 41
  • Did you add a path of the directory containing `libAbcSupport.dylib` to `DYLD_LIBRARY_PATH` environment variable before trying to execute the application? – Alexander Shukaev Apr 17 '13 at 01:01
  • @Haroogan Wow, I'll have to be honest and say that I didn't think that would work at first. It seems to have fixed the issue I was having though. Can you post this as an answer and explain more thoroughly what this does? Also, is there anyway to include the `libAbcSupport.dylib` within the Mac's App so I don't need to modify the environment variables to get the App to run? (reposting comment so you'll get a notification and because I'm past the time limit for editing it) – robhasacamera Apr 17 '13 at 13:13

1 Answers1

4

You should add a path of the directory containing libAbcSupport.dylib to the DYLD_LIBRARY_PATH environment variable before starting the application.

For the reference, here is the dyld(1) man-page of OS X Manual. Extract:

DYLD_LIBRARY_PATH

This is a colon separated list of directories that contain libraries. The dynamic linker searches these directories before it searches the default locations for libraries. It allows you to test new versions of existing libraries.

For each library that a program uses, the dynamic linker looks for it in each directory in DYLD_LIBRARY_PATH in turn. If it still can't find the library, it then searches DYLD_FALLBACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH in turn.

If you want this to be out-of-the-box, i.e. without needing to set this variable manually, then, for example, you should simply add proper installation process into CMakeLists. By default, DYLD_LIBRARY_PATH probably contains some directories, the system ones, and the user ones. Simply check it by:

echo $DYLD_LIBRARY_PATH

and consult the documentation on which directory is preferable (or sort of conventional) to deploy libraries for 3rd party applications on Mac OS X. Then all you'd have to do is to program CMakeLists so that on running make install it deploys libAbcSupport.dylib into such directory.

NOTE: You don't experience this problem on Windows because while Windows searches for the PATH environment variable to find DLLs too, it also searches in the current directory of the application (which is not the case for both Mac OS X and Linux). In other words, on Windows you most likely deploy AbcSupport.dll in the same directory as your application, and therefore don't have to worry about this.

NOTE: Linux is similar to Mac OS X in this regard. So if you ever have to port your application to Linux too, don't forget that you'll need LD_LIBRARY_PATH there. Here is LD.SO(8) man-page of Linux Programmer's Manual, and a relevant extract:

The LD_LIBRARY_PATH environment variable contains a colon-separated list of directories that are searched by the dynamic linker when looking for a shared library to load.

The directories are searched in the order they are mentioned in.

If not specified, the linker uses the default, which is /lib:/usr/lib:/usr/local/lib.

Community
  • 1
  • 1
Alexander Shukaev
  • 16,674
  • 8
  • 70
  • 85
  • This process produces a Linux style application layout on a Mac and relies on the Linux practice of setting the library path before executing the binary. It is wrong for a Mac application. – Khouri Giordano Apr 12 '19 at 18:54
  • @Khouri, what are you talking about? What is a Linux style application layout? Please, be more specific. `DYLD_` environment variables are defined by Mac OS X specifications of DYLD. Since author does not have proper installation procedure defined in CMake (which would allow to avoid `DYLD_` environment variable dance), the above solution provides a possibility to run the built executable regardless. – Alexander Shukaev Apr 26 '19 at 20:42
  • I'm talking about a self-contained application bundle using @rpath to find the libraries within the bundle. Linux style means your application is actually a shell script in `/opt` that sets `LD_LIBRARY_PATH` and then executes the real binary. If you're happy with that, that's ok. The general Mac population considers it abnormal. – Khouri Giordano Apr 26 '19 at 21:08
  • I'm not happy with that and it's the first time I hear about such a crappy approach to deliver one's application, and I would definitely never recommend that. I always supply proper installation procedures to my CMake build systems, which take care of both, `rpath` modifications for binary artifacts in build tree (so that they are directly runnable) and proper deployment paths (depending on target OS) for various artifacts, e.g. `/usr/lib` for shared objects or `/usr/bin` for executables and etc. The above question does not ask about deployment and installation best practices for Mac OS X. – Alexander Shukaev Apr 26 '19 at 21:17
  • A Mac application should not pollute `/usr` but keep all of that within it's bundle. On Linux and Windows, I would similarly keep all dependent libraries within a single folder. It's a little different if you are publishing a package on Linux. CMake's answer, even for the build tree, is your `CMakeLists.txt` writes a post build CMake script that does `include(BundleUtilities)` and calls `fixup_bundle()` that will walk the libraries to find runtime dependencies and then copy them all to the executable path. This works for Linux, Mac and Windows. – Khouri Giordano Apr 26 '19 at 21:33