Enable cross-compilation to Darwin/Mac OS X

This set of changes make it possible to do a cross build targeting Mac
OS X 10.9 ("Mavericks") from a Linux host. Tools required for a build
(in addition to the standard build toolchain, obviously): otool,
install_name_tool, c4group.

Since CMake does not (yet?) support passing environment variables to
custom build commands, you should make sure to have the
INSTALL_NAME_TOOL and OTOOL variables set to reasonable values during
the entire build. Additionally, if you have not unpacked your OS X SDK
directly into the root directory (you probably shouldn't), you need to
set the SYSROOT environment variable to the root of the SDK (the
directory containing the "System" directory). Setting up a CMake
toolchain file is left as an exercise to the reader.
issue1247
Nicolas Hake 2015-01-25 01:23:20 +01:00
commit 185c82fd1c
8 changed files with 124 additions and 57 deletions

View File

@ -825,13 +825,8 @@ else()
endif()
if(NOT USE_CONSOLE)
if(APPLE)
include(LegacyFindFreetype)
include_directories(${FREETYPE_INCLUDE_DIRS})
else()
find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
endif()
find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
endif()
# FINDLIB works the same as find_library, but also marks the resulting var as
@ -1237,18 +1232,15 @@ endforeach()
############################################################################
if (APPLE)
# for good measure - seems to be part of default OSX installation
# linking with static freetype library requires it
target_link_libraries(openclonk "/usr/lib/libbz2.dylib")
find_package("BZip2" REQUIRED)
target_link_libraries(openclonk ${BZIP2_LIBRARIES})
set(HAVE_RVALUE_REF ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++0x -g -Wall -fobjc-arc")
if(CMAKE_GENERATOR STREQUAL Xcode)
add_custom_command(TARGET openclonk
POST_BUILD COMMAND "/usr/bin/ruby" "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_bundle_libs"
)
set(CMAKE_XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER YES)
set(CMAKE_XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/C4Include.h")
set_target_properties(openclonk PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER YES)
@ -1268,6 +1260,12 @@ if (APPLE)
set_target_properties(c4group PROPERTIES XCODE_ATTRIBUTE_GCC_PFE_FILE_C_DIALECTS "c++0x objective-c++0x")
set_target_properties(openclonk PROPERTIES XCODE_ATTRIBUTE_GCC_PFE_FILE_C_DIALECTS "c++0x objective-c++0x")
endif()
add_custom_command(TARGET openclonk
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_bundle_libs"
"$<TARGET_FILE:openclonk>"
)
endif()
############################################################################
@ -1353,7 +1351,7 @@ if(USE_X11)
)
endif()
if(USE_COCOA)
TARGET_LINK_LIBRARIES(openclonk "-framework Cocoa -framework AppKit -framework Quartz -framework OpenAL -framework AudioToolBox")
TARGET_LINK_LIBRARIES(openclonk "-framework Cocoa -framework AppKit -framework Quartz -framework OpenAL -framework AudioToolbox")
endif()
if (WIN32)
# CMake is too incompetent to check whether these libraries can be linked to
@ -1417,6 +1415,15 @@ if(USE_GCC_PCH)
add_precompiled_header(openclonk src/C4Include.h)
endif()
# When cross-compiling, import c4group from a native build
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_NATIVE_TOOLS "IMPORT_NATIVE_TOOLS-NOTFOUND" CACHE FILEPATH "Export file from a native build")
INCLUDE(${IMPORT_NATIVE_TOOLS})
SET(native_c4group native-c4group)
ELSE()
SET(native_c4group c4group)
ENDIF()
############################################################################
# installation
############################################################################
@ -1487,27 +1494,27 @@ foreach(group ${OC_C4GROUPS})
if (APPLE)
if (CMAKE_GENERATOR STREQUAL Xcode)
add_custom_command(TARGET openclonk
POST_BUILD COMMAND "/bin/sh" "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
"$<TARGET_FILE:c4group>"
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
"$<TARGET_FILE:${native_c4group}>"
"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}"
# leave out third parameter here so the script can figure out Xcode-ish paths as usual
DEPENDS c4group
DEPENDS "${native_c4group}"
)
else()
add_custom_command(TARGET openclonk
POST_BUILD COMMAND "/bin/sh" "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
"$<TARGET_FILE:c4group>"
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
"$<TARGET_FILE:${native_c4group}>"
"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}"
"${CMAKE_CURRENT_BINARY_DIR}/openclonk.app/Contents/Resources"
DEPENDS c4group
DEPENDS "${native_c4group}"
)
endif()
else()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${group}
COMMAND c4group ARGS "${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}" -t "${CMAKE_CURRENT_BINARY_DIR}/${group}"
COMMAND "${native_c4group}" ARGS "${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}" -t "${CMAKE_CURRENT_BINARY_DIR}/${group}"
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}
DEPENDS c4group
DEPENDS "${native_c4group}"
VERBATIM
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${group} DESTINATION share/games/openclonk)
@ -1535,6 +1542,11 @@ else()
)
endif()
# Export native tools for later use in cross-compile builds
IF(NOT CMAKE_CROSSCOMPILING)
EXPORT(TARGETS c4group FILE ${CMAKE_BINARY_DIR}/NativeToolsExport.cmake NAMESPACE native- )
ENDIF()
############################################################################
# setup_openclonk.exe
############################################################################

View File

@ -19,7 +19,7 @@
# Use pkg-config if possible instead of doing guesswork like the default CMake module does
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
if(PKG_CONFIG_FOUND AND NOT APPLE)
set(_ft_pkgconfig_args "")
if(FREETYPE_FIND_REQUIRED)
set(_ft_pkgconfig_args "${_ft_pkgconfig_args}REQUIRED ")

View File

@ -16,12 +16,12 @@
#include <C4Include.h>
#include <C4GraphicsSystem.h>
#include <C4MouseControl.h>
#include <C4GUI.h>
#include <C4Gui.h>
#include <C4Game.h>
#include <C4Viewport.h>
#include <C4ViewportWindow.h>
#include <C4Console.h>
#include <C4Fullscreen.h>
#include <C4FullScreen.h>
#include <C4PlayerList.h>
#include <C4Gui.h>
#include <C4Landscape.h>

View File

@ -14,7 +14,7 @@
*/
#include <C4Include.h>
#include <C4Fullscreen.h>
#include <C4FullScreen.h>
#include <C4GraphicsSystem.h>
#include <C4Viewport.h>
#include <C4Console.h>

View File

@ -14,7 +14,7 @@
*/
#include <C4Include.h>
#include <C4Fullscreen.h>
#include <C4FullScreen.h>
#include <C4GraphicsSystem.h>
#include <C4Viewport.h>
#include <C4ViewportWindow.h>

View File

@ -21,7 +21,7 @@
#include <C4Rect.h>
#include <C4FullScreen.h>
#import <Appkit/AppKit.h>
#import <AppKit/AppKit.h>
#import <C4WindowController.h>
#import <C4DrawGLMac.h>

View File

@ -1,33 +1,88 @@
#!/usr/bin/env ruby
#!/bin/bash
# Bundle all the libraries, no matter their potential existence on pristine OSX installations
$libs_to_bundle=".*?/lib(jpeg|GLEW|llvm|SDL|SDL_mixer|freetype|ogg|vorbis|vorbisfile|z\.|png[0-9]*|iconv|alut)\.[^ ]+\.dylib"
$executable_path = ENV['EXECUTABLE_PATH']
$frameworks_folder_path = ENV['FRAMEWORKS_FOLDER_PATH']
set -e
Dir.chdir ENV['TARGET_BUILD_DIR'] if ENV['TARGET_BUILD_DIR']
puts "Bundling libraries..."
# Grab information about the bundle from the environment (if XCode) or make
# assumptions about the bundle layout (everywhere else)
_executable_path="${EXECUTABLE_PATH:-$1}"
if [ -n "${WRAPPER_NAME}" ]; then
_wrapper_name="${WRAPPER_NAME}"
else
_wrapper_name="${_executable_path%.app/*}"
if [ "${_wrapper_name}" == "${_executable_path}" ]; then
echo "Unable to derive bundle location from '${_wrapper_name}'!" >&2
exit 1
fi
_wrapper_name="${_wrapper_name}.app"
fi
_contents_folder="${CONTENTS_FOLDER_PATH:-${_wrapper_name}/Contents}"
_frameworks_folder_path="${FRAMEWORKS_FOLDER_PATH:-${_contents_folder}/Frameworks}"
def bundle_dependencies(executable_path)
`otool -L #{executable_path} | grep -Eo "#{$libs_to_bundle}" | grep -v "@executable_path.*"`.each_line do |lib|
lib.strip!
break if not File.exists? lib
puts "Bundling #{lib}"
base = `basename #{lib}`.strip
bundle_path = "#{$frameworks_folder_path}/#{base}"
already_bundled = File.exists? bundle_path
id = "@executable_path/../Frameworks/#{base}"
if not already_bundled then
puts "Bundling #{base}..."
`cp #{lib} #{bundle_path}`
`chmod u+w #{bundle_path}`
end
`install_name_tool -id #{id} #{bundle_path}`
`install_name_tool -change #{lib} #{id} #{$executable_path}`
`install_name_tool -change #{lib} #{id} #{executable_path}` if $executable_path != executable_path
bundle_dependencies bundle_path if not already_bundled
end
end
# Get tool names/paths from the environment in case we're cross compiling
_otool="${OTOOL:-otool}"
_install_name_tool="${INSTALL_NAME_TOOL:-install_name_tool}"
`mkdir -p #{$frameworks_folder_path}`
bundle_dependencies $executable_path
# This regexp should match every lib we want to bundle.
_libs_to_bundle=".*?/lib(jpeg|GLEW|llvm|SDL|SDL_mixer|freetype|ogg|vorbis|vorbisfile|z\.|png[0-9]*|iconv|alut)\.[^ ]+\.dylib"
if [ -n "${TARGET_BUILD_DIR}" ]; then
cd "${TARGET_BUILD_DIR}"
fi
echo "Bundling libraries..."
bundle_dependencies() {
_object_path="$1"
"${_otool}" -L "${_object_path}" | \
grep -Eo -- "${_libs_to_bundle}" | \
grep -v '@executable_path.*' | \
while read _library_name; do
_library_path="${_library_name}"
# If the library isn't available at the stored path, it may be
# stored inside the sysroot (when cross-compiling for example)
if [ ! -e "${_library_path}" -a -n "${SYSROOT}" ]; then
_library_path="${SYSROOT}${_library_path}"
fi
# Stop bundling if a lib doesn't exist
if [ ! -e "${_library_path}" ]; then
echo "Cannot find ${_library_name}." >&2
exit 1
fi
_base="$(basename "${_library_name}")"
_bundle_path="${_frameworks_folder_path}/${_base}"
_id="@executable_path/../Frameworks/${_base}"
# Skip if it's a library stub (because we can't change the install name
# of those anyway)
if file -b "${_library_path}" | grep -q 'shared library stub'; then
continue
fi
# Change the depender reference unconditionally
"${_install_name_tool}" -change "${_library_name}" "${_id}" "${_object_path}"
# Don't fixup this lib if it is already bundled - no point in doing the
# same work multiple times
[ -e "${_bundle_path}" ] && continue
echo "Bundling '${_library_path}' as '${_base}'..."
cp "${_library_path}" "${_bundle_path}"
chmod u+w "${_bundle_path}"
# Set a new install name for this dylib
"${_install_name_tool}" -id "${_id}" "${_bundle_path}"
# Also change the reference inside the application itself
if [ "${_executable_path}" != "${_object_path}" ]; then
"${_install_name_tool}" -change "${_library_name}" "${_id}" "${_executable_path}"
fi
# And also recursively bundle the dependencies of this dependency.
bundle_dependencies "${_bundle_path}"
done
}
mkdir -p "${_frameworks_folder_path}"
bundle_dependencies "${_executable_path}"

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
C4GROUP=$1
SRC_GROUP=$2