Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macos] SDL 2.24.2 - SDL.h #includes <SDL2/(various)> but there is no SDL2 subdirectory #6513

Closed
nbriggs opened this issue Nov 13, 2022 · 18 comments

Comments

@nbriggs
Copy link

nbriggs commented Nov 13, 2022

For example:

In file included from ../src/sdl.c:1:
/Library/Frameworks/SDL2.framework/Headers/SDL.h:32:10: fatal error: 'SDL2/SDL_main.h' file not found
#include <SDL2/SDL_main.h>
         ^~~~~~~~~~~~~~~~~
1 error generated.

but, all the include files are at the same level in Headers/

% ls /Library/Frameworks/SDL2.framework/Versions/A/Headers/
SDL.h				SDL_keyboard.h			SDL_power.h
SDL_assert.h			SDL_keycode.h			SDL_quit.h
SDL_atomic.h			SDL_loadso.h			SDL_rect.h
SDL_audio.h			SDL_locale.h			SDL_render.h
SDL_bits.h			SDL_log.h			SDL_revision.h
SDL_blendmode.h			SDL_main.h			SDL_rwops.h
SDL_clipboard.h			SDL_messagebox.h		SDL_scancode.h
SDL_config.h			SDL_metal.h			SDL_sensor.h
SDL_config_macosx.h		SDL_misc.h			SDL_shape.h
SDL_copying.h			SDL_mouse.h			SDL_stdinc.h
SDL_cpuinfo.h			SDL_mutex.h			SDL_surface.h
SDL_endian.h			SDL_name.h			SDL_system.h
SDL_error.h			SDL_opengl.h			SDL_syswm.h
SDL_events.h			SDL_opengl_glext.h		SDL_thread.h
SDL_filesystem.h		SDL_opengles.h			SDL_timer.h
SDL_gamecontroller.h		SDL_opengles2.h			SDL_touch.h
SDL_gesture.h			SDL_opengles2_gl2.h		SDL_types.h
SDL_guid.h			SDL_opengles2_gl2ext.h		SDL_version.h
SDL_haptic.h			SDL_opengles2_gl2platform.h	SDL_video.h
SDL_hidapi.h			SDL_opengles2_khrplatform.h	SDL_vulkan.h
SDL_hints.h			SDL_pixels.h			begin_code.h
SDL_joystick.h			SDL_platform.h			close_code.h

One fix to enable compilation is to symlink SDL2 -> .

@FtZPetruska
Copy link
Contributor

I have seen a similar issue that boiled down to incorrect CMake configuration.

When using SDL2 as a framework, clang needs to be passed the -framework SDL2 option to properly set include path (prefix all the files in Headers with the name of the framework). As such your CMake target needs to link with SDL2::SDL2 even if it only needs the headers. Setting the target include directories alone will not work.

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

You should be able to only add the headers by doing:

target_include_directories(your_game PRIVATE $<TARGET_PROPERTY:SDL2::SDL2,INCLUDE_DIRECTORIES>)

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

Would making available a SDL2::Headers target be useful?

@nbriggs
Copy link
Author

nbriggs commented Nov 15, 2022

The CMakeLists.txt that I've inherited, in its SDL2 related pieces, does:

  FIND_PACKAGE(SDL2 REQUIRED)
...
  TARGET_INCLUDE_DIRECTORIES(xxx PRIVATE ${SDL2_INCLUDE_DIRS})
  TARGET_LINK_LIBRARIES(xxx ${SDL2_LIBRARIES})

where the SDL2_... appear to be provided by the SDL2 package. So that's probably just wrong for the macOS framework case. What's the right way to configure it to cope with both a typical Linux installation of SDL2 and the macOS framework case?

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

I was taught the only guaranteed working way to include the SDL headers is by doing the following, without a SDL2/ prefix.

#include "SDL.h"

This is also in line with sdl2-config.
Running sdl2-config --cflags on my system returns: -I/usr/include/SDL2 -D_REENTRANT.
The addition of the includedir to sdl2.pc was done only recently.

@nbriggs
Copy link
Author

nbriggs commented Nov 15, 2022

The above CMakeLists.txt fragments result in CMake compiling with:

[...]/usr/bin/cc -DRELEASE=351 -DSDL  -isystem /Library/Frameworks/SDL2.framework/Headers -O3 -DNDEBUG -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -mmacosx-version-min=11.7 -F /Library/Frameworks/ -std=gnu99 -MD -MT CMakeFiles/ldesdl.dir/src/sdl.c.o -MF CMakeFiles/ldesdl.dir/src/sdl.c.o.d -o CMakeFiles/ldesdl.dir/src/sdl.c.o -c /Users/briggs/Projects/maiko/src/sdl.c

and linking with:

[...]/usr/bin/cc -O3 -DNDEBUG -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk -mmacosx-version-min=11.7 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -F /Library/Frameworks/ -framework SDL2 [all the object files] -o ldesdl  -lm 

so it's pointing at the Headers to include, and the framework to link...

@FtZPetruska
Copy link
Contributor

FtZPetruska commented Nov 15, 2022

I was taught the only guaranteed working way to include the SDL headers is by doing the following, without a SDL2/ prefix.

#include "SDL.h"

This is also in line with sdl2-config. Running sdl2-config --cflags on my system returns: -I/usr/include/SDL2 -D_REENTRANT. The addition of the includedir to sdl2.pc was done only recently.

Apple's frameworks are a special case where you need to prefix the includes with SDL2/ despite not being actually being layed out this way.

If you look at the framework's SDL.h, it includes other headers this way:

#include <SDL2/SDL_main.h>
#include <SDL2/SDL_stdinc.h>
....

Whereas on a more typical release, SDL.h includes the headers as expected:

#include "SDL_main.h"
#include "SDL_stdinc.h"
...

Would making available a SDL2::Headers target be useful?

Not necessarily, for clang to properly include a framework (even to just get correct includes) it needs to be passed a -framework SDL2, if INTERFACE_INCLUDE_DIRECTORIES behaves the same as INTERFACE_LINK_OPTIONS what could be put is:

set_target_properties(SDL2::SDL2
        PROPERTIES
            INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\""
            INTERFACE_INCLUDE_DIRECTORIES "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\";SHELL:-framework SDL2"
            INTERFACE_LINK_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\";SHELL:-framework SDL2"
            COMPATIBLE_INTERFACE_BOOL "SDL2_SHARED"
            INTERFACE_SDL2_SHARED "ON"
    )

And then set SDL2_INCLUDE_DIR to SDL2::SDL2 similar to how SDL2_LIBRARIES just contains SDL2::SDL2.

EDIT: Nevermind, that does not work.

@FtZPetruska
Copy link
Contributor

After further investigating, here are the findings:

  • It is the -F /Path/To/Frameworks/ option that add the proper include for frameworks.
  • Setting INTERFACE_INCLUDE_DIRECTORIES to /Path/To/SDL2.framework/Headers allows for the end-user to just #include "SDL.h", then the rest of the headers will be found through the option above.

Moreover, checking the pull request @nbriggs linked above, I wasn't able to reproduce the issue, building and linking just fine with the latest Framework alone.

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

Thanks, I was just able to mount the .dmg on Linux with this fuse module.

I didn't know the framework's SDL.h was including other headers through SDL2/....
That means the framework's sdl2-config.cmake is missing an include path.

I think the following patch addresses this. Can someone check?

--- a/Xcode/SDL/pkg-support/resources/CMake/sdl2-config.cmake
+++ b/Xcode/SDL/pkg-support/resources/CMake/sdl2-config.cmake
@@ -39,7 +39,7 @@ string(REGEX REPLACE "SDL2\\.framework.*" "" SDL2_FRAMEWORK_PARENT_PATH "${CMAKE
 set_and_check(SDL2_PREFIX       "${SDL2_FRAMEWORK_PATH}")
 set_and_check(SDL2_EXEC_PREFIX  "${SDL2_FRAMEWORK_PATH}")
 set_and_check(SDL2_INCLUDE_DIR  "${SDL2_FRAMEWORK_PATH}/Headers")
-set(SDL2_INCLUDE_DIRS           "${SDL2_INCLUDE_DIR}")
+set(SDL2_INCLUDE_DIRS           "${SDL2_INCLUDE_DIR};${SDL2_FRAMEWORK_PATH}")
 set_and_check(SDL2_BINDIR       "${SDL2_FRAMEWORK_PATH}")
 set_and_check(SDL2_LIBDIR       "${SDL2_FRAMEWORK_PATH}")
 
@@ -53,7 +53,7 @@ if(NOT TARGET SDL2::SDL2)
     set_target_properties(SDL2::SDL2
         PROPERTIES
             INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\""
-            INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}"
+            INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
             INTERFACE_LINK_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\";SHELL:-framework SDL2"
             COMPATIBLE_INTERFACE_BOOL "SDL2_SHARED"
             INTERFACE_SDL2_SHARED "ON"

@nbriggs
Copy link
Author

nbriggs commented Nov 15, 2022

That seems to do it -- I applied that patch, removed my symlink SDL2 => . from the Headers, reconfigured, and recompiled. Typical compile step now looks like:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
 -DRELEASE=351 \
 -DSDL \
 -I/Users/briggs/Projects/maiko/inc \
 -isystem /Library/Frameworks/SDL2.framework/Headers \
 -iframework /Library/Frameworks \
 -fno-strict-aliasing  \
 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk \
 -mmacosx-version-min=11.7 \
 -F /Library/Frameworks/ \
 -std=gnu99 \
 -MD \
 -MT CMakeFiles/ldesdl.dir/src/sdl.c.o \
 -MF CMakeFiles/ldesdl.dir/src/sdl.c.o.d \
 -o CMakeFiles/ldesdl.dir/src/sdl.c.o \
 -c /Users/briggs/Projects/maiko/src/sdl.c

So, +1 for that. Thanks!

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

Applied in e6c4db8

Can this issue be considered fixed?

@nbriggs
Copy link
Author

nbriggs commented Nov 15, 2022

I'm good with that, perhaps @FtZPetruska will also have an opinion.

@FtZPetruska
Copy link
Contributor

Tried the framework with the patch, it compiles my projects with no issues. So I'm good with it too!

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

Good to hear!

Strange to see the compile command in #6513 (comment) not containing

-I/Library/Frameworks/SDL2.framework

@nbriggs
Copy link
Author

nbriggs commented Nov 15, 2022

@madebr not so strange, I think -- it has -isystem /Library/Frameworks/SDL2.framework/Headers to add that directory to the system include search path.

@madebr
Copy link
Contributor

madebr commented Nov 15, 2022

But my patch was adding the framework root folder, e.g. /Library/Frameworks/SDL2.framework.

@nbriggs
Copy link
Author

nbriggs commented Nov 16, 2022

Without the patch it does:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc \
 -DRELEASE=351 \
 -DSDL \
 -I/Users/briggs/Projects/maiko/inc \
 -isystem /Library/Frameworks/SDL2.framework/Headers \
 -fno-strict-aliasing  \
 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk \
 -mmacosx-version-min=11.7 \
 -F /Library/Frameworks/ \
 -std=gnu99 \
 -MD \
 -MT CMakeFiles/ldesdl.dir/src/sdl.c.o \
 -MF CMakeFiles/ldesdl.dir/src/sdl.c.o.d \
 -o CMakeFiles/ldesdl.dir/src/sdl.c.o \
 -c /Users/briggs/Projects/maiko/src/sdl.c

and what's missing here is the -iframework /Library/Frameworks

BUT... I'm really confused - I put the sdl2-config.cmake back to the way it was, cleared everything redid the "cmake ..", and I can't reproduce the original problem!

@madebr
Copy link
Contributor

madebr commented Jan 15, 2023

Closing this issue as the original issue has been resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants