Skip to content

Commit 8ecf72f

Browse files
committed
Add preliminary support for Xcode and building universal dylib
Initial support for Apple Frameworks Move scripts into subfolder Remove set(CMAKE_MACOSX_RPATH ON) because that is already the default value. Fix framework install directory when not installing to the system.
1 parent 9c82ae5 commit 8ecf72f

File tree

10 files changed

+145
-10
lines changed

10 files changed

+145
-10
lines changed

.github/workflows/cppcmake.yml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,26 @@ jobs:
3939
- {name: "ubuntu-24.04", os: "ubuntu-24.04", cmake_extra: "-DLSL_BUNDLED_PUGIXML=OFF" }
4040
- {name: "windows-x64", os: "windows-latest", cmake_extra: "-T v142,host=x86"}
4141
- {name: "windows-32", os: "windows-latest", cmake_extra: "-T v142,host=x86 -A Win32"}
42-
- {name: "macOS-latest", os: "macOS-latest"}
42+
- {name: "macOS-latest", os: "macOS-latest", cmake_extra: "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_OSX_ARCHITECTURES=x86_64;arm64 DCMAKE_SYSTEM_NAME=Darwin -DLSL_FRAMEWORK=ON -G Xcode" }
4343

4444
# runs all steps in the container configured in config.docker or as subprocesses when empty
4545
container: ${{ matrix.config.docker }}
4646
steps:
4747
- uses: actions/checkout@v4
48+
4849
- name: set up build environment in container
50+
if: ${{ matrix.config.docker }}
4951
run: |
5052
set -x
5153
apt update
5254
apt install -y --no-install-recommends g++ git ninja-build file dpkg-dev lsb-release sudo curl cmake libpugixml-dev
53-
if: ${{ matrix.config.docker }}
55+
56+
- name: Setup Xcode
57+
if: ${{ matrix.config.name == 'macOS-latest' }}
58+
uses: maxim-lobanov/setup-xcode@v1
59+
with:
60+
xcode-version: 'latest-stable'
61+
5462
- name: Configure CMake
5563
run: |
5664
if [[ "${{ matrix.config.name }}" = ubuntu-2* ]]; then
@@ -68,8 +76,12 @@ jobs:
6876
${{ matrix.config.cmake_extra }} \
6977
${{ github.event.inputs.cmakeextra }}
7078
echo ${PWD}
79+
7180
- name: make
72-
run: cmake --build build --target install --config Release -j
81+
run: cmake --build build --config Release -j
82+
83+
- name: make install
84+
run: cmake --build build --config Release --target install
7385

7486
- name: test install using examples
7587
run: |
@@ -101,6 +113,7 @@ jobs:
101113
fi
102114
cmake -E remove_directory package/_CPack_Packages
103115
cp testing/lslcfgs/default.cfg .
116+
104117
- name: upload install dir
105118
uses: actions/upload-artifact@master
106119
with:
@@ -112,6 +125,7 @@ jobs:
112125
with:
113126
name: pkg-${{ matrix.config.name }}
114127
path: package
128+
115129
- name: print network config
116130
run: |
117131
which ifconfig && ifconfig
@@ -133,12 +147,14 @@ jobs:
133147
install/bin/lsl_test_internal --order rand --wait-for-keypress never --durations yes || test ! -z "${{ matrix.config.docker }}"
134148
install/bin/lsl_test_exported --order rand --wait-for-keypress never --durations yes
135149
timeout-minutes: 10
150+
136151
- name: upload dump
137152
if: failure()
138153
uses: actions/upload-artifact@master
139154
with:
140155
name: dumps-${{ matrix.config.name }}
141156
path: dumps
157+
142158
- name: upload to release page
143159
if: github.event_name == 'release'
144160
env:

cmake/CompilerSettings.cmake

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,4 @@ endif()
3030
# Platform-specific settings
3131
if(WIN32)
3232
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
33-
elseif(APPLE)
34-
set(CMAKE_MACOSX_RPATH ON)
3533
endif()
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# This script is executed at install time.
2+
# It was generated from CreateFrameworkSymlinks.cmake.in
3+
4+
set(FRAMEWORK_DIR "${CMAKE_INSTALL_PREFIX}/@CMAKE_INSTALL_FRAMEWORK_DIR@/lsl.framework")
5+
6+
message(STATUS "Executing configured symlink script.")
7+
message(STATUS " -- Target Directory='${FRAMEWORK_DIR}'")
8+
9+
if(NOT EXISTS "${FRAMEWORK_DIR}")
10+
message(FATAL_ERROR "Framework version directory does not exist. Cannot create symlink.")
11+
endif()
12+
13+
message(STATUS " -- Framework version directory exists. Creating symlink...")
14+
15+
execute_process(
16+
COMMAND ln -sf include Headers
17+
WORKING_DIRECTORY "${FRAMEWORK_DIR}/Versions/A"
18+
RESULT_VARIABLE result
19+
ERROR_VARIABLE error
20+
)
21+
if(NOT result EQUAL 0)
22+
message(FATAL_ERROR "Failed to create Headers->include symlink: ${error}")
23+
endif()
24+
25+
execute_process(
26+
COMMAND ln -sf Versions/Current/Headers
27+
WORKING_DIRECTORY "${FRAMEWORK_DIR}"
28+
RESULT_VARIABLE result
29+
ERROR_VARIABLE error
30+
)
31+
if(NOT result EQUAL 0)
32+
message(FATAL_ERROR "Failed to create <root>Headers->Versions/Current/Headers symlink: ${error}")
33+
endif()
34+
35+
if(NOT result EQUAL 0)
36+
message(FATAL_ERROR "Failed to create Headers symlink in framework: ${error}")
37+
endif()
38+
39+
message(STATUS " -- Framework symlink created successfully.")

cmake/Installation.cmake

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,27 @@ include(CMakePackageConfigHelpers)
44
# Paths
55
if(LSL_UNIXFOLDERS)
66
include(GNUInstallDirs)
7+
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
8+
set(FRAMEWORK_DIR_DEFAULT Library/Frameworks)
9+
else()
10+
set(FRAMEWORK_DIR_DEFAULT Frameworks)
11+
endif()
12+
set(CMAKE_INSTALL_FRAMEWORK_DIR ${FRAMEWORK_DIR_DEFAULT} CACHE PATH "Install directory for frameworks on macOS")
713
else()
814
set(CMAKE_INSTALL_BINDIR LSL)
915
set(CMAKE_INSTALL_LIBDIR LSL)
1016
set(CMAKE_INSTALL_INCLUDEDIR LSL/include)
17+
set(CMAKE_INSTALL_FRAMEWORK_DIR LSL/Frameworks CACHE PATH "Install directory for frameworks on macOS")
18+
endif()
19+
20+
# For Apple frameworks, we need to next the install directories within the framework.
21+
if(APPLE AND LSL_FRAMEWORK)
22+
# For the includes, this is insufficient. Later we will create more accessible symlinks.
23+
set(LSL_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_FRAMEWORK_DIR}/lsl.framework/Versions/A/include)
24+
set(LSL_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_FRAMEWORK_DIR}/lsl.framework/Resources/CMake)
25+
else()
26+
set(LSL_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
27+
set(LSL_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/lsl)
1128
endif()
1229

1330
# Generate a version file for the package.
@@ -27,20 +44,21 @@ install(TARGETS ${LSLTargets}
2744
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
2845
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
2946
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
30-
FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
47+
FRAMEWORK DESTINATION ${CMAKE_INSTALL_FRAMEWORK_DIR}
48+
FILE_SET HEADERS DESTINATION ${LSL_INSTALL_INCLUDEDIR}
3149
)
3250

3351
# Generate the LSLConfig.cmake file and mark it for installation
3452
install(EXPORT LSLTargets
3553
FILE LSLConfig.cmake
3654
COMPONENT liblsl
3755
NAMESPACE "LSL::"
38-
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL
56+
DESTINATION ${LSL_CONFIG_INSTALL_DIR}
3957
)
4058
# A common alternative to installing the exported package config file is to generate it from a template.
4159
#configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/lslConfig.cmake.in
4260
# ${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake
43-
# INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lsl)
61+
# INSTALL_DESTINATION ${LSL_CONFIG_INSTALL_DIR})
4462
# If we use this method, then we need a corresponding install(FILES ...) command to install the generated file.
4563

4664
# Install the version file and the helper CMake script.
@@ -49,5 +67,17 @@ install(
4967
cmake/LSLCMake.cmake
5068
${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake
5169
COMPONENT liblsl
52-
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL
70+
DESTINATION ${LSL_CONFIG_INSTALL_DIR}
5371
)
72+
73+
if(APPLE AND LSL_FRAMEWORK)
74+
# Create symlinks for the framework. The variables we want to use to identify the symlink locations
75+
# are not available at install time. Instead, we create a script during configuration time that will
76+
# be run at install time to create the symlinks.
77+
configure_file(
78+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/CreateFrameworkSymlinks.cmake.in
79+
${CMAKE_CURRENT_BINARY_DIR}/CreateFrameworkSymlinks.cmake
80+
@ONLY
81+
)
82+
install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/CreateFrameworkSymlinks.cmake COMPONENT liblsl)
83+
endif()

cmake/ProjectOptions.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
option(LSL_DEBUGLOG "Enable (lots of) additional debug messages" OFF)
33
option(LSL_UNIXFOLDERS "Use the unix folder layout for install targets" ON)
44
option(LSL_BUILD_STATIC "Build LSL as a static library." OFF)
5+
option(LSL_FRAMEWORK "Build LSL as an Apple Framework (Mac only)" ON)
56
option(LSL_LEGACY_CPP_ABI "Build legacy C++ ABI into lsl-static" OFF)
67
option(LSL_OPTIMIZATIONS "Enable some more compiler optimizations" ON)
78
option(LSL_BUNDLED_BOOST "Use the bundled Boost by default" ON)

cmake/TargetLib.cmake

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,34 @@ target_compile_definitions(lsl
4747
# don't use #pragma(lib) in MSVC builds. TODO: Maybe this can be inherited from lslobj or removed on lslobj?
4848
$<$<CXX_COMPILER_ID:MSVC>:LSLNOAUTOLINK>
4949
)
50+
51+
# Extra configuration for Apple targets -- set xcode attributes
52+
if(APPLE)
53+
set_target_properties(lsl PROPERTIES
54+
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.labstreaminglayer.liblsl"
55+
)
56+
# If environment variables are set for Apple Development Team and Code Sign Identity then add these to the target
57+
# -> if `-G Xcode` generator is used then Xcode will use these variables to sign the framework.
58+
# Note, however, that it is likely that the build products will be modified post-build, invalidating the signature,
59+
# so post-hoc signing will be required. Nevertheless, this is useful for initial signing and normal Xcode workflow.
60+
if(DEFINED ENV{APPLE_DEVELOPMENT_TEAM} AND DEFINED ENV{APPLE_CODE_SIGN_IDENTITY_APP})
61+
set_target_properties(lsl PROPERTIES
62+
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY $ENV{APPLE_CODE_SIGN_IDENTITY_APP}
63+
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM $ENV{APPLE_DEVELOPMENT_TEAM}
64+
XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Manual"
65+
XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING YES # this is needed for strip symbols
66+
XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep"
67+
)
68+
endif()
69+
# Configure Apple Framework
70+
if(LSL_FRAMEWORK)
71+
set_target_properties(lsl PROPERTIES
72+
FRAMEWORK TRUE
73+
FRAMEWORK_VERSION A
74+
MACOSX_FRAMEWORK_IDENTIFIER "org.labstreaminglayer.liblsl"
75+
MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}"
76+
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION}
77+
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/lsl.entitlements"
78+
)
79+
endif(LSL_FRAMEWORK)
80+
endif(APPLE)

examples/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function(addlslexample name extension)
4242
# However, this is not necessary for the examples, as they are not intended to be relocated.
4343
# if(APPLE)
4444
# set_target_properties(${name} PROPERTIES
45-
# INSTALL_RPATH "@loader_path;@loader_path/../lib"
45+
# INSTALL_RPATH "@loader_path;@loader_path/../lib;@loader_path/../Frameworks"
4646
# )
4747
# elseif(UNIX)
4848
# set_target_properties(${name} PROPERTIES

lsl.entitlements

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<!-- Required for allowing outgoing network connections (TCP and UDP). -->
6+
<key>com.apple.security.network.client</key>
7+
<true/>
8+
9+
<!-- Required for allowing your framework to listen for incoming connections. -->
10+
<key>com.apple.security.network.server</key>
11+
<true/>
12+
13+
<!-- Specifically required for sending and receiving UDP multicast traffic used in stream advertising. -->
14+
<key>com.apple.security.network.multicast</key>
15+
<true/>
16+
</dict>
17+
</plist>

standalone_compilation_linux.sh renamed to scripts/standalone_compilation_linux.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# (pip install cmake) or as binary download from cmake.org
77

88
set -e -x
9+
cd "$(dirname "$0")/.."
910
# Try to read LSLGITREVISION from git if the variable isn't set
1011
echo ${LSLGITREVISION:="$(git describe --tags HEAD)"}
1112
${CXX:-g++} -fPIC -fvisibility=hidden -O2 ${CFLAGS} ${CXXFLAGS} -Ilslboost \

update_lslboost.sh renamed to scripts/update_lslboost.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# the absolute path to the extracted boost source archive (https://www.boost.org/users/download/)
22
set -e
33
set -x
4+
cd "$(dirname "$0")/.."
5+
46
BOOSTPATH=/tmp/boost_1_84_0
57
TMPPATH=/tmp/lslboost
68

0 commit comments

Comments
 (0)