From 16425b4c321180cd0e1b927ff7034d853db783e7 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Sun, 23 Aug 2020 11:35:02 +0200 Subject: [PATCH] (macOS) Updates to CMake scripts and corresponding documentation. --- CMakeLists.txt | 18 ++- CONTRIBUTING.md | 16 ++- INSTALL.md | 132 +++++++++++++++++++-- es-app/CMakeLists.txt | 55 ++++++--- es-app/assets/EmulationStation-DE_DS_Store | Bin 6148 -> 6148 bytes 5 files changed, 184 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9d9c71f8..c07145015 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ option(GLES "Set to ON if targeting Embedded OpenGL" ${GLES}) option(GL "Set to ON if targeting Desktop OpenGL" ${GL}) option(RPI "Set to ON to enable the Raspberry PI video player (omxplayer)" ${RPI}) option(CEC "Set to ON to enable CEC" ${CEC}) +option(APPLE_SKIP_INSTALL_LIBS "Set to ON to skip installation of shared libraries (macOS only)." + ${APPLE_SKIP_INSTALL_LIBS}) #--------------------------------------------------------------------------------------------------- # Set up OpenGL system variable. @@ -224,7 +226,7 @@ elseif(DEFINED VERO4K) link_directories("${CMAKE_FIND_ROOT_PATH}/opt/vero3/lib") endif() -if (NOT WIN32) +if(NOT WIN32) set(COMMON_LIBRARIES ${CURL_LIBRARIES} ${FreeImage_LIBRARIES} @@ -247,16 +249,22 @@ elseif(WIN32) "nanosvg") endif() -if (APPLE) +if(APPLE) # See es-app/CMakeLists.txt for an explation for why an extra 'Resources' directory # has been added to the install prefix. - set(CMAKE_INSTALL_PREFIX "/Applications/EmulationStation-DE.app/Contents/Resources") + set(CMAKE_INSTALL_PREFIX + "/Applications/EmulationStation Desktop Edition.app/Contents/Resources") # Temporary solution until the VLC find module has been updated to work properly on macOS. set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "/Applications/VLC.app/Contents/MacOS/lib/libvlc.dylib") - set(CMAKE_INSTALL_RPATH @executable_path) -# set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + + # Set the same rpath links for the install executable as for the build executable. + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + + if(NOT APPLE_SKIP_INSTALL_LIBS) + set(CMAKE_INSTALL_RPATH @executable_path) + endif() endif() # Add libCEC libraries. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d9de4ea82..46cf61da6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,18 +6,21 @@ Contributing to EmulationStation Desktop Edition There are many cards in the Kanban backlog that would be nice to implement. And for this, code contributions are very welcome. There may be a bug or two as well that needs fixing ;) +And to put it mildly, I'm confused regarding CMake, so help is needed in this area. Although the building and package generation works more or less correctly, there are some hacks and similar in the CMakeLists.txt files that need improving by someone who really knows how this software package works. + Apart from code commits, help is especially needed for thorough testing of the software and for working on the rbsimple-DE theme. It's impossible for me to test every game system (rbsimple-DE has support for more than a 100 different systems!) so it would be especially useful to hear about any issues with starting games using the default es_systems.cfg configuration file and also if there are any problems with scraping for certain systems. -In general, a review of the [es_systems.cfg_unix](resources/templates/es_systems.cfg_unix), [es_systems.cfg_macos](resources/templates/es_systems.cfg_macos) and [es_systems.cfg_windows](resources/templates/es_systems.cfg_windows) files including the supported file extensions would be great! +And it's a fact that some configuration is simply missing in these files for some systems, so that would need to be added as well. -As for rbsimple-DE there are quite some missing graphic files and other customizations for a number of game systems. \ -Check out [MISSING.md](themes/rbsimple-DE/MISSING.md) for more details of what needs to be added or updated. +In general, a review of the [es_systems.cfg_unix](resources/templates/es_systems.cfg_unix), [es_systems.cfg_macos](resources/templates/es_systems.cfg_macos) and [es_systems.cfg_windows](resources/templates/es_systems.cfg_windows) files including the supported file extensions would be great. + +As for rbsimple-DE there are quite some missing graphic files and other customizations for a number of game systems. Check out [MISSING.md](themes/rbsimple-DE/MISSING.md) for more details of what needs to be added or updated. ### Coding style: -The coding style for EmulationStation-DE is mostly a combination of the Linux Kernel style (although that's C it's close enough to C++ as far as I'm concerned) and Google's C++ guidelines. Google is not a very nice company, but they write nice code. +The coding style for EmulationStation-DE is mostly a combination of the Linux Kernel style (although that's C it's close enough to C++ as far as I'm concerned) and Google's C++ guidelines. Please refer to these documents here: @@ -27,7 +30,7 @@ https://google.github.io/styleguide/cppguide.html **Some key points:** * Column width (line length) is 100 characters -* Indentation is 4 spaces, don't use tabs as they can be interpreted differently! +* Indentation is 4 spaces, don't use tabs as they can be interpreted differently * Line break is Unix-style (line feed only, no carriage return) * Do not leave trailing whitespaces at the end of the lines (a good source code editor should have a setting to automatically trim these for you) * When breaking up long lines into multiple lines, consider what could be useful data to grep for so you don't break in the middle of such a string @@ -37,6 +40,7 @@ https://google.github.io/styleguide/cppguide.html * Always use spaces between keywords and opening brackets, i.e. `if ()`, `for ()`, `while ()` etc. * Indentation of switch/case statements is optional, but it's usually easier to read the code with indentations in place * Use `std::string` instead of `char *` or `char []` unless there is a specific reason requiring the latter +* Actually, try to use C++ syntax in general instead of C syntax, another example would be `static_cast(someFloatVariable)` instead of `(int)someFloatVariable` * If the arguments (and initializer list) for a function or class exceeds 4 items, arrange them vertically to make the code easier to read * Always declare one variable per line, never combine multiple declarations of the same type * Name local variables with the first word in small letters and the proceeding words starting with capital letters, e.g. myExampleVariable @@ -49,4 +53,4 @@ https://google.github.io/styleguide/cppguide.html ### Building and configuring: -Please refer to the [INSTALL.md](INSTALL.md) file for details on everything related to building and configuring EmulationStation Desktop Edition. +Please refer to the [INSTALL.md](INSTALL.md) file for details on everything related to building EmulationStation Desktop Edition. diff --git a/INSTALL.md b/INSTALL.md index 16a4bb502..19bb8fc0d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -136,7 +136,7 @@ Assuming the default installation prefix `/usr/local` has been used, this is the /usr/local/man/man6/emulationstation.6.gz /usr/local/share/applications/emulationstation.desktop /usr/local/share/emulationstation/LICENSE -/usr/local/share/emulationstation/LICENSES/* +/usr/local/share/emulationstation/licenses/* /usr/local/share/emulationstation/resources/* /usr/local/share/emulationstation/themes/* /usr/local/share/pixmaps/emulationstation.svg @@ -156,9 +156,9 @@ And it will look in the following locations for the themes, also in the listed o * `[INSTALL PREFIX]/share/emulationstation/themes/` * `[ES EXECUTABLE DIRECTORY]/themes/` -The theme is not mandatory to start the application, but ES will be basically useless without it. +A theme is not mandatory to start the application, but ES will be basically useless without it. -So the home directory will always take precedence, and any resources or themes located there will override the ones in the installation path or the path of the ES executable. +The home directory will always take precedence, and any resources or themes located there will override the ones in the installation path or in the path of the ES executable. **Creating .deb and .rpm packages:** @@ -198,7 +198,7 @@ sudo apt-get install rpm ## Building on macOS -EmulationStation for macOS is built using Clang/LLVM which is the default compiler for this operating system. It's pretty straightforward to build software on this OS. Although it's a bizarre Unix variant, it is still a proper system with good tools. The main deficiency (apart from a quite strange user interface) is that there is no package manager and you need to register an account to install software from the App Store. There are several third party package managers though, and the use of one of them, _Homebrew_, is detailed below. +EmulationStation for macOS is built using Clang/LLVM which is the default compiler for this operating system. It's pretty straightforward to build software on this OS. Although it's a bizarre Unix variant, it is still a proper system with good tools. The main deficiency (apart from a very strange window manager) is that there is no package manager and you need to register an account to install software from the App Store. There are several third party package managers though, and the use of one of them, `Homebrew`, is detailed below. **Setting up the build tools:** @@ -269,13 +269,95 @@ Keep in mind though that a debug version will be much slower due to all compiler Running `make -j6` (or whatever number of parallel jobs you prefer) speeds up the compilation time if you have cores to spare. -**Creating .dmg DragNDrop installer:** +**Installing:** -Simply run `cpack` to build the .dmg installer: +As macOS does not have any package manager which would have handled the library dependencies, we need to bundle the required shared libraries with the application. Copy the following .dylib files from their respective installation directories to the emulationstation-de build directory: + +``` +libSDL2-2.0.0.dylib +libcurl.4.dylib +libfreeimage.dylib +libfreetype.6.dylib +libvlc.dylib +libvlccore.dylib +``` + +Note that the filenames could be slightly different depending on what versions you have installed on your system. + +In addition to these, you need to create a `plugins` directory and copy over the following VLC libraries, which are normally located in `/Applications/VLC.app/Contents/MacOS/plugins/`: + +``` +libaudio_format_plugin.dylib +libavcodec_plugin.dylib +libconsole_logger_plugin.dylib +libfilesystem_plugin.dylib +libfreetype_plugin.dylib +libswscale_plugin.dylib +libtrivial_channel_mixer_plugin.dylib +libvmem_plugin.dylib +libwave_plugin.dylib +libx264_plugin.dylib +libx265_plugin.dylib +``` + +If you only want to build EmulationStation to be used on your own computer, there's the option to skip the entire bundling of the libraries and use the ones already installed using Homebrew, meaning you can skip the previous .dylib copying. To do so, run CMake with the following option: + +``` +cmake -DAPPLE_SKIP_INSTALL_LIBS=ON . +``` + +**Note:** This also affects the .dmg package generation using cpack, so if this options is enabled, the package will be unusable for everyone but yourself as the required libraries will not be bundled with the application. + +On macOS you can then install the application as a normal user, i.e. no root privileges are required. Simply run the following to install the application to `/Applications/EmulationStation Desktop Edition.app`: + +``` +make install +``` + +This will be the directory structure for the installation: + +``` +/Applications/EmulationStation Desktop Edition.app/Contents/Info.plist +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/EmulationStation +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/libSDL2-2.0.0.dylib +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/libcurl.4.dylib +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/libfreeimage.dylib +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/libfreetype.6.dylib +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/libvlc.dylib +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/libvlccore.dylib +/Applications/EmulationStation Desktop Edition.app/Contents/MacOS/plugins/* +/Applications/EmulationStation Desktop Edition.app/Contents/Resources/EmulationStation-DE.icns +/Applications/EmulationStation Desktop Edition.app/Contents/Resources/LICENSE +/Applications/EmulationStation Desktop Edition.app/Contents/Resources/licenses/* +/Applications/EmulationStation Desktop Edition.app/Contents/Resources/resources/* +/Applications/EmulationStation Desktop Edition.app/Contents/Resources/themes/* +``` + +ES will look in the following locations for the resources, in the listed order: + +* `[HOME]/.emulationstation/resources/` +* `[ES EXECUTABLE DIRECTORY]/../Resources/resources/` +* `[ES EXECUTABLE DIRECTORY]/resources/` + +**Note:** The resources directory is critical, without it the application won't start. + +And it will look in the following locations for the themes, also in the listed order: + +* `[HOME]/.emulationstation/themes/` +* `[ES EXECUTABLE DIRECTORY]/../Resources/themes/` +* `[ES EXECUTABLE DIRECTORY]/themes/` + +A theme is not mandatory to start the application, but ES will be basically useless without it. + +The home directory will always take precedence, and any resources or themes located there will override the ones in the installation path or in the path of the ES executable. + +**Creating a .dmg installer:** + +Simply run `cpack` to build a .dmg disk image/installer: ``` myusername@computer:~/emulationstation-de$ cpack -CPack: Create package using DragNDrop +CPack: Create package using Bundle CPack: Install projects CPack: - Run preinstall target for: emulationstation-de CPack: - Install project: emulationstation-de [] @@ -283,6 +365,42 @@ CPack: Create package CPack: - package: /Users/myusername/emulationstation-de/EmulationStation-DE-1.0.0.dmg generated. ``` +**Special considerations regarding run-paths:** + +Even after considerable effort I've been unable to make CMake natively set correct rpaths for the EmulationStation binary on macOS. Therefore a hack/workaround is in place that uses install_name_tool to change absolute paths to rpaths for most of the bundled libraries. + +This is certainly not perfect as the versions of the libraries are hardcoded inside es-app/CMakeLists.txt. Therefore always check that all the rpaths are set correctly if you intend to create a .dmg image that will be used on other computers than your own. + +Simply run `otool -L EmulationStation` and verify that the result looks something like this: + +``` +EmulationStation: + @rpath/libcurl.4.dylib (compatibility version 7.0.0, current version 8.0.0) + @rpath/libfreeimage.dylib (compatibility version 3.0.0, current version 3.18.0) + @rpath/libfreetype.6.dylib (compatibility version 24.0.0, current version 24.2.0) + @rpath/libSDL2-2.0.0.dylib (compatibility version 13.0.0, current version 13.0.0) + /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 22.0.0) + @rpath/libvlc.dylib (compatibility version 12.0.0, current version 12.0.0) + /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0) + /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0) + /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1) +``` + +If any of the lines that should start with @rpath instead has an absolute path, then you have a problem and need to modify the install_name_tools parameters in es-app/CMakeLists.txt, for example: + +`/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib (compatibility version 13.0.0, current version 13.0.0)` + +This is the section that would need to be modified: + +``` +add_custom_command(TARGET EmulationStation POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} + -change /usr/lib/libcurl.4.dylib @rpath/libcurl.4.dylib + -change /usr/local/opt/freeimage/lib/libfreeimage.dylib @rpath/libfreeimage.dylib + -change /usr/local/opt/freetype/lib/libfreetype.6.dylib @rpath/libfreetype.6.dylib + -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib @rpath/libSDL2-2.0.0.dylib + $) +``` + ## Building on Windows diff --git a/es-app/CMakeLists.txt b/es-app/CMakeLists.txt index 3ab2dcea1..2f5d25348 100644 --- a/es-app/CMakeLists.txt +++ b/es-app/CMakeLists.txt @@ -141,26 +141,43 @@ elseif(APPLE) DESTINATION ../Resources) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_Info.plist DESTINATION .. RENAME Info.plist) - install(FILES ${CMAKE_SOURCE_DIR}/libcurl.4.dylib - DESTINATION ../MacOS) - install(FILES ${CMAKE_SOURCE_DIR}/libfreeimage.dylib - DESTINATION ../MacOS) - install(FILES ${CMAKE_SOURCE_DIR}/libfreetype.6.dylib - DESTINATION ../MacOS) - install(FILES ${CMAKE_SOURCE_DIR}/libSDL2-2.0.0.dylib - DESTINATION ../MacOS) - install(FILES ${CMAKE_SOURCE_DIR}/libvlc.dylib - DESTINATION ../MacOS) - install(FILES ${CMAKE_SOURCE_DIR}/libvlccore.dylib - DESTINATION ../MacOS) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins - DESTINATION ../MacOS) + + # Another hack/workaround. I have not been able to find any way whatsover to force the + # linker to use rpaths for all shared libraries instead of absolute paths. So instead + # we're running install_name_tool as a post-build command to manually change the absolute + # paths to the rpaths for these libraries. The worst thing about this approach is that + # the library version needs to be manually changed here depending on what's installed + # on your system (e.g. if using libSDL2-2.1.0.dylib instead of libSDL2-2.0.0.dylib). + # This problem definitely needs to be resolved properly at a later date. + add_custom_command(TARGET EmulationStation POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} + -change /usr/lib/libcurl.4.dylib @rpath/libcurl.4.dylib + -change /usr/local/opt/freeimage/lib/libfreeimage.dylib @rpath/libfreeimage.dylib + -change /usr/local/opt/freetype/lib/libfreetype.6.dylib @rpath/libfreetype.6.dylib + -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib @rpath/libSDL2-2.0.0.dylib + $) + + if(NOT APPLE_SKIP_INSTALL_LIBS) + install(FILES ${CMAKE_SOURCE_DIR}/libcurl.4.dylib + DESTINATION ../MacOS) + install(FILES ${CMAKE_SOURCE_DIR}/libfreeimage.dylib + DESTINATION ../MacOS) + install(FILES ${CMAKE_SOURCE_DIR}/libfreetype.6.dylib + DESTINATION ../MacOS) + install(FILES ${CMAKE_SOURCE_DIR}/libSDL2-2.0.0.dylib + DESTINATION ../MacOS) + install(FILES ${CMAKE_SOURCE_DIR}/libvlc.dylib + DESTINATION ../MacOS) + install(FILES ${CMAKE_SOURCE_DIR}/libvlccore.dylib + DESTINATION ../MacOS) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins + DESTINATION ../MacOS) + endif() install(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ../Resources) -# install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources -# DESTINATION ../Resources) -# install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes -# DESTINATION ../Resources) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources + DESTINATION ../Resources) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes + DESTINATION ../Resources) install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses DESTINATION ../Resources) else() @@ -202,7 +219,7 @@ if(APPLE) set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE.icns") set(CPACK_DMG_VOLUME_NAME "EmulationStation Desktop Edition ${CPACK_PACKAGE_VERSION}") set(CPACK_DMG_DS_STORE "${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_DS_Store") - set(CPACK_BUNDLE_NAME "EmulationStation-DE") + set(CPACK_BUNDLE_NAME "EmulationStation Desktop Edition") set(CPACK_BUNDLE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE.icns") set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_Info.plist") elseif(WIN32) diff --git a/es-app/assets/EmulationStation-DE_DS_Store b/es-app/assets/EmulationStation-DE_DS_Store index 3a109eec2076bfa8bdd526ff03ca6a77ea3842dc..c7dd91e90270cb49bcbce019e8ebd80764ae46c5 100644 GIT binary patch delta 140 zcmZoMXfc=|#>B`mu~2NHo+2aD#DLwC4MbQb^D}7(W->4^T&XBOaO?knAd7)PWpWI& zqPzlw3qvYHF+(;(2}3?Z0fPdAD?R3j hXWY!r!OsD-3n=oPc{0Cg1?m;qsFB@zGt delta 281 zcmZoMXfc=|#>B)qu~2NHo+2aL#DLw44=^$^vQ6e;)E2a3U|`spndx=*|9>EhfkAw- z2cx2{E`tk$D}x?GB0~W~foD#Ba#Buy5>QqEh`#|bNXI#39f~MAa?%Zhlk;;6fGQc7 ze(4+rQebmYRpsWpxTKVpBr`DFP6?F(sl~1;1*<9<6dMaN5H>PvUD&*lF^^?4I|n}p b(BnYPcjn3bB9