Unable to run program in CLion macOS Big Sur

I am unable to run a simple SDL program in CLion. I have SDL2 installed accurately, according to home-brew. When the program is run in the CLion IDE, the following is produced as an error (the cmake and .cpp file are referenced below the error message):

[ 50%] Building CXX object CMakeFiles/SDLBasic.dir/main.cpp.o
[100%] Linking CXX executable SDLBasic
Undefined symbols for architecture x86_64:
  "_SDL_Init", referenced from:
      _main in main.cpp.o
  "_SDL_Quit", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [SDLBasic] Error 1
make[2]: *** [CMakeFiles/SDLBasic.dir/all] Error 2
make[1]: *** [CMakeFiles/SDLBasic.dir/rule] Error 2
make: *** [SDLBasic] Error 2

The cmake is as follows:

cmake_minimum_required(VERSION 3.20)
project(SDLBasic)

set(CMAKE_CXX_STANDARD 14)

add_executable(SDLBasic main.cpp)

include_directories("/Library/Frameworks/SDL2.framework/Versions/A/Headers")
find_library(SDL2_LIBRARY SDL2 "/Library/Frameworks/SDL2.framework/Versions/A/Headers")
find_library(SDL2_App ${SDL2_LIBRARY})
include_directories("/usr/local/Cellar/sdl2/2.0.18/lib/libSDL2.a")
include_directories("/Library/Frameworks")

The main.cpp is as follows:

#include <iostream>
#include <SDL.h>



using namespace std;

int main() {

    if(SDL_Init(SDL_INIT_VIDEO) < 0) {
        cout << "SDL init failed." << endl;
        return 1;
    }

    cout << "SDL Init succeeded." << endl;

    SDL_Quit();

    return 0;
}

The error message says it can’t find the SDL functions you’re calling because you aren’t linking against SDL.

I know very little about Cmake, but your Cmake file looks wrong. Homebrew doesn’t install SDL (or anything else) to system directories like /Library/Frameworks. In fact, it doesn’t install SDL as a framework at all, but rather just the shared and static libraries and include files (with symlinks in /usr/local). Even if it did, trying to link directly to the binary inside the framework would probably be a bad idea.

edit: Solution

When Homebrew installs SDL, it also installs a cmake package that knows what libraries to link to and what to set the include directories to in order for Cmake to know how to compile your app with SDL. Googling “sdl cmake” found this blog post. According to that post, your cmake file will have to be something like this:

cmake_minimum_required(VERSION 3.20)

project(SDLBasic)

find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})

add_executable(SDLBasic main.cpp)
target_link_libraries(SDLBasic ${SDL2_LIBRARIES})

I think you’re trying to create a Universal Binary, which is not possible using Homebrew. The reason being: Homebrew only provides artifacts of the same architecture as your machine.

Check your CLion settings for anything related to “fat binaries” or “universal binaries”. If you want to have both architectures, you may want to go on SDL’s website and grab the latest development libraries for macOS, they should be compiled in both x86_64 and arm64. Don’t forget to uninstall SDL2 from Homebrew if you go down that route.

Edit: It appears that the framework distributed on the website, while containing the two architecture does not have CMake targets. So this may not fit your needs.

To clarify, I used Homebrew to verify istallation as a part of trouble shooting. The main installation of SDL i have is located in my “/Library/Frameworks” directory. It was installed via the “Development Libraries” for Mac OS X on the SDL site. It was from there and including the SDL files in the cmake file, via a directory, that I was getting errors. I used homebrew as a trouble shooting method to see if it stated if SDL was installed and it is saying it is. I thought I’d clarify that.

I found a solution using CMake and SDL2 Development Libraries available on libsdl.org.

Assuming you’ve placed the framework in /Library/Frameworks/. Your CMakeLists should look like this:

cmake_minimum_required(VERSION 3.20)
project(SDLBasic)

set(CMAKE_CXX_STANDARD 14)

add_executable(SDLBasic main.cpp)

set(SDL2_LIB "/Library/Frameworks/SDL2.framework/SDL2")
target_include_directories(SDLBasic PRIVATE "/Library/Frameworks/SDL2.framework/Headers")

target_link_libraries(SDLBasic ${SDL2_LIB})

Since SDL2main is not needed on macOS, there is only a single dynamic library file which has no extension: SDL2.framework/SDL2. For the include directories, it is generally better practice to only set it on a per-target basis using target_include_directories, similarly you can just give the path to the Headers folder in the framework.

Hope this works out for you too!

1 Like

I have replaced my CMake with your suggestion and I am pleased to say it has worked. Thank you for the help!

1 Like

You shouldn’t need to link to specific files/paths inside the framework

I was able to get a test program built with this CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(test)

set(CMAKE_CXX_STANDARD 17)

add_executable(test main.cpp)

link_directories(./)

find_library(SDL2_LIB
		NAMES SDL2
		HINTS "./"
		REQUIRED)

target_link_libraries(test ${SDL2_LIB})

I put SDL2.framework in the same directory as the source code, if you’ve installed SDL2.framework to /Library/Frameworks then change the link_directories and find_library HINTS lines to point there instead

The advantage is that this will actually use the -framework command for the compiler, which will then link to the correct binary inside the framework and add its Headers directory to the include directories for you.