Skip to content

Commit ad0efb2

Browse files
committed
CMake: rework install path / Qt installation handling
1 parent 32d4c6c commit ad0efb2

File tree

2 files changed

+108
-138
lines changed

2 files changed

+108
-138
lines changed

CMakeLists.txt

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,35 +217,42 @@ if(NOT LSL_NO_FANCY_LIBNAME)
217217
)
218218
endif()
219219

220-
if(NOT LSL_UNIXFOLDERS)
221-
set(LSLPREFIX "LSL/")
220+
if(LSL_UNIXFOLDERS)
221+
include(GNUInstallDirs)
222+
else()
223+
set(CMAKE_INSTALL_BINDIR LSL)
224+
set(CMAKE_INSTALL_LIBDIR LSL)
225+
set(CMAKE_INSTALL_INCLUDEDIR LSL/include)
226+
set(CMAKE_INSTALL_DATAROOTDIR LSL/share)
222227
endif()
223228

224229
add_executable(lslver testing/lslver.c)
225230
target_link_libraries(lslver PRIVATE lsl)
226231

227232
install(TARGETS ${LSL_EXPORT_TARGETS}
233+
EXPORT LSLConfig
228234
COMPONENT liblsl
229-
EXPORT LSLConfig #"${PROJECT_NAME}Config"
230-
RUNTIME DESTINATION ${LSLPREFIX}bin
231-
LIBRARY DESTINATION ${LSLPREFIX}lib
232-
ARCHIVE DESTINATION ${LSLPREFIX}lib
235+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
236+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
237+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
233238
)
234239

235240
install(EXPORT LSLConfig #"${PROJECT_NAME}Config"
236241
COMPONENT liblsl
237242
NAMESPACE "LSL::"
238-
DESTINATION "${LSLPREFIX}share/LSL")
243+
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/LSL
244+
)
239245

240246
# install headers
241-
install(DIRECTORY include
242-
DESTINATION "./${LSLPREFIX}"
247+
install(DIRECTORY include/
248+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
243249
COMPONENT liblsl
244250
)
245251

246252
install(FILES LSLCMake.cmake
247253
COMPONENT liblsl
248-
DESTINATION "${LSLPREFIX}share/LSL")
254+
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/LSL
255+
)
249256

250257
include(LSLCMake.cmake)
251258

LSLCMake.cmake

Lines changed: 91 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Common functions and settings for LSL
22

33
message(STATUS "Included LSL CMake helpers, rev. 11")
4+
option(LSL_DEPLOYAPPLIBS "Copy library dependencies (at the moment Qt + liblsl) to the installation dir" ON)
45

56
# set build type and default install dir if not done already
67
if(NOT CMAKE_BUILD_TYPE)
@@ -71,13 +72,8 @@ function(installLSLAuxFiles target)
7172
endif()
7273
endfunction()
7374

74-
# installLSLApp: adds the specified target to the install list
75-
#
76-
# there are two install types for different use cases
77-
# Windows users mostly want a folder per app that contains
78-
# everything needed to run the app, whereas on Linux,
79-
# OS X (homebrew) and Conda the libraries are installed
80-
# separately to save space, ease upgrading and distribution
75+
# installLSLApp: adds the specified target to the install list and
76+
# add some quality-of-life improvements for Qt executables
8177
function(installLSLApp target)
8278
get_target_property(TARGET_LIBRARIES ${target} LINK_LIBRARIES)
8379
string(REGEX MATCH ";Qt5::" qtapp ";${TARGET_LIBRARIES}")
@@ -89,145 +85,114 @@ function(installLSLApp target)
8985
AUTORCC ON
9086
)
9187
endif()
88+
# add start menu shortcut if supported by installer
89+
set_property(INSTALL "${PROJECT_NAME}/$<TARGET_FILE_NAME:${target}>" PROPERTY
90+
CPACK_START_MENU_SHORTCUTS "${target}")
91+
9292
if(LSL_UNIXFOLDERS)
93-
install(TARGETS ${target}
94-
COMPONENT "${PROJECT_NAME}"
95-
RUNTIME DESTINATION bin
96-
BUNDLE DESTINATION bin
97-
LIBRARY DESTINATION lib
98-
)
93+
include(GNUInstallDirs)
94+
set(lsldir "\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
9995
else()
100-
installLSLAppSingleFolder(${target} "${qtapp}")
96+
set(CMAKE_INSTALL_BINDIR ${PROJECT_NAME})
97+
set(CMAKE_INSTALL_LIBDIR ${PROJECT_NAME})
98+
set(lsldir "\${CMAKE_INSTALL_PREFIX}/LSL")
10199
endif()
102100
set_property(GLOBAL APPEND PROPERTY
103101
"LSLDEPENDS_${PROJECT_NAME}" liblsl)
104-
endfunction()
105-
106-
function(findQtInstallationTool qtdeploytoolname)
107-
if(QT_DEPLOYQT_EXECUTABLE)
102+
install(TARGETS ${target} COMPONENT ${PROJECT_NAME}
103+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
104+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
105+
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
106+
# skip copying libraries if disabled or on Linux
107+
if(NOT LSL_DEPLOYAPPLIBS OR UNIX AND NOT APPLE)
108108
return()
109109
endif()
110-
get_target_property(QT_QMAKE_EXE Qt5::qmake IMPORTED_LOCATION)
111-
get_filename_component(QT_BIN_DIR "${QT_QMAKE_EXE}" DIRECTORY)
112-
find_program (QT_DEPLOYQT_EXECUTABLE ${qtdeploytoolname} HINTS "${QT_BIN_DIR}")
113-
if (QT_DEPLOYQT_EXECUTABLE)
114-
message(STATUS "Qt deploy tool found at ${QT_DEPLOYQT_EXECUTABLE}")
115-
else()
116-
message(WARNING "Windeployqt wasn't found, installing ${PROJECT_NAME} will fail!")
110+
111+
# skip exe deployment for libraries
112+
get_target_property(target_type ${target} TYPE)
113+
if(NOT target_type STREQUAL "EXECUTABLE")
117114
return()
118115
endif()
119-
endfunction()
120-
121-
# installLSLAppSingleFolder: installs the app its folder and copies needed libraries
122-
#
123-
# when calling make install / ninja install the executable is installed to
124-
# CMAKE_INSTALL_PREFIX/PROJECT_NAME/TARGET_NAME
125-
# e.g. C:/LSL/BrainAmpSeries/BrainAmpSeries.exe
126-
function(installLSLAppSingleFolder target deployqt)
127-
install(TARGETS ${target}
128-
COMPONENT "${PROJECT_NAME}"
129-
BUNDLE DESTINATION ${PROJECT_NAME}
130-
RUNTIME DESTINATION ${PROJECT_NAME}
131-
LIBRARY DESTINATION ${PROJECT_NAME}/lib
132-
)
133-
set(appbin "${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/${target}${CMAKE_EXECUTABLE_SUFFIX}")
134116

135117
# Copy lsl library for WIN32 or MacOS.
136118
# On Mac, dylib is only needed for macdeployqt and for non bundles when not using system liblsl.
137119
# Copy anyway, and fixup_bundle can deal with the dylib already being present.
138-
if(WIN32 OR APPLE)
139-
installLSLAuxFiles(${target} $<TARGET_FILE:LSL::lsl>)
140-
set_property(INSTALL "${PROJECT_NAME}/$<TARGET_FILE_NAME:${target}>" PROPERTY
141-
CPACK_START_MENU_SHORTCUTS "${target}")
142-
endif()
143-
144-
# do we need to install with Qt5?
145-
if(deployqt)
146-
if(WIN32)
147-
findQtInstallationTool("windeployqt")
148-
if (QT_DEPLOYQT_EXECUTABLE)
149-
file (TO_NATIVE_PATH "${QT_BIN_DIR}" QT_BIN_DIR_NATIVE)
150-
# It's safer to use `\` separators in the Path, but we need to escape them
151-
string (REPLACE "\\" "\\\\" QT_BIN_DIR_NATIVE "${QT_BIN_DIR_NATIVE}")
152-
set(QT_DEPLOYQT_FLAGS --no-translations --no-system-d3d-compiler --no-opengl-sw --no-compiler-runtime)
153-
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${target}_$<CONFIG>_path"
154-
CONTENT "$<TARGET_FILE:${target}>" # Full path to .exe file
155-
)
156-
get_filename_component(appdir ${appbin} DIRECTORY CACHE)
157-
install (CODE "
158-
file(READ \"${CMAKE_CURRENT_BINARY_DIR}/${target}_${CMAKE_BUILD_TYPE}_path\" _file)
159-
message (STATUS \"Running Qt Deploy Tool for \${_file}\")
160-
if (CMAKE_INSTALL_CONFIG_NAME STREQUAL \"Debug\")
161-
set(QT_DEPLOYQT_FLAGS \"\${QT_DEPLOYQT_FLAGS} --debug\")
162-
else ()
163-
set(QT_DEPLOYQT_FLAGS \"\${QT_DEPLOYQT_FLAGS} --release\")
164-
endif ()
165-
execute_process(COMMAND
166-
\"${CMAKE_COMMAND}\" -E env
167-
\"Path=${QT_BIN_DIR_NATIVE};\$ENV{SystemRoot}\\\\System32;\$ENV{SystemRoot}\"
168-
\"${QT_DEPLOYQT_EXECUTABLE}\"
169-
${QT_DEPLOYQT_FLAGS} --dry-run --list mapping
170-
\"${appbin}\"
171-
OUTPUT_VARIABLE output
172-
OUTPUT_STRIP_TRAILING_WHITESPACE
173-
)
174-
string(REPLACE \"\\\\\" \"/\" _output \${output})
175-
separate_arguments(_files WINDOWS_COMMAND \${_output})
176-
while(_files)
177-
list(GET _files 0 _src)
178-
list(GET _files 1 _dest)
179-
execute_process(
180-
COMMAND \"${CMAKE_COMMAND}\" -E
181-
copy_if_different \${_src} \"\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/$\{_dest}\"
182-
)
183-
list(REMOVE_AT _files 0 1)
184-
endwhile()
185-
" COMPONENT ${target})
186-
#add_custom_command(TARGET ${target} POST_BUILD
187-
# COMMAND "${CMAKE_COMMAND}" -E env PATH="${QT_BIN_DIR}" "${QT_DEPLOYQT_EXECUTABLE}"
188-
# ${QT_DEPLOYQT_FLAGS}
189-
# \"$<TARGET_FILE:${target}>\")
190-
endif()
191-
elseif(APPLE)
192-
# It should be enough to call fixup_bundle (see below),
193-
# but this fails to install qt plugins (cocoa).
194-
# Use macdeployqt instead (but this is bad at grabbing lsl dylib, so we did that above)
195-
findQtInstallationTool("macdeployqt")
196-
if(QT_DEPLOYQT_EXECUTABLE)
197-
set(QT_DEPLOYQT_FLAGS "-verbose=1") # Adding -libpath=${CMAKE_INSTALL_PREFIX}/LSL/lib seems to do nothing, maybe deprecated
198-
install(CODE "
199-
message(STATUS \"Running Qt Deploy Tool...\")
200-
#list(APPEND QT_DEPLOYQT_FLAGS -dmg)
201-
if(CMAKE_INSTALL_CONFIG_NAME STREQUAL \"Debug\")
202-
list(APPEND QT_DEPLOYQT_FLAGS -use-debug-libs)
203-
endif()
204-
execute_process(COMMAND
205-
\"${QT_DEPLOYQT_EXECUTABLE}\"
206-
\"${appbin}.app\"
207-
${QT_DEPLOYQT_FLAGS}
208-
)
209-
")
210-
endif()
211-
endif()
212-
elseif(APPLE)
120+
installLSLAuxFiles(${target} $<TARGET_FILE:LSL::lsl>)
121+
if(APPLE AND NOT qtapp)
213122
# fixup_bundle appears to be broken for Qt apps. Use only for non-Qt.
214123
get_target_property(target_is_bundle ${target} MACOSX_BUNDLE)
215124
if(target_is_bundle)
216125
install(CODE "
217126
include(BundleUtilities)
218127
set(BU_CHMOD_BUNDLE_ITEMS ON)
219-
fixup_bundle(
220-
${appbin}.app
221-
\"\"
222-
\"${CMAKE_INSTALL_PREFIX}/LSL/lib\"
223-
)
128+
fixup_bundle(\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/${target}.app \"\" \"${lsldir}\")
224129
"
225130
COMPONENT ${PROJECT_NAME}
226131
)
227132
endif()
228133
endif()
134+
135+
# skip the rest if qt doesn't need to be deployed
136+
if(NOT qtapp)
137+
return()
138+
endif()
139+
140+
cmake_minimum_required(VERSION 3.15) # generator expressions in install(CODE)
141+
if(WIN32)
142+
findQtInstallationTool("windeployqt")
143+
install(CODE "
144+
message (STATUS \"Running windeployqt on $<TARGET_FILE:${target}>\")
145+
execute_process(
146+
COMMAND ${QT_DEPLOYQT_EXECUTABLE} --no-translations
147+
--no-system-d3d-compiler --no-opengl-sw --no-virtualkeyboard
148+
--no-compiler-runtime --dry-run --list mapping
149+
$<TARGET_FILE:${target}>
150+
OUTPUT_VARIABLE output
151+
OUTPUT_STRIP_TRAILING_WHITESPACE
152+
)
153+
file(TO_CMAKE_PATH \${output} output) # convert slashes
154+
separate_arguments(_files WINDOWS_COMMAND \${output})
155+
while(_files)
156+
list(POP_FRONT _files _src)
157+
list(POP_FRONT _files _dest)
158+
get_filename_component(_dest \${_dest} DIRECTORY RELATIVE)
159+
file(COPY \${_src} DESTINATION \${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/\${_dest})
160+
endwhile()"
161+
COMPONENT ${target})
162+
elseif(APPLE)
163+
# It should be enough to call fixup_bundle (see below),
164+
# but this fails to install qt plugins (cocoa).
165+
# Use macdeployqt instead (but this is bad at grabbing lsl dylib, so we did that above)
166+
findQtInstallationTool("macdeployqt")
167+
install(CODE "
168+
if(\${CMAKE_INSTALL_CONFIG_NAME} STREQUAL Debug)
169+
set(debug 1)
170+
endif()
171+
message(STATUS \"Running Qt Deploy Tool for $<TARGET_FILE:${target}>...\")
172+
execute_process(COMMAND
173+
echo \"${QT_DEPLOYQT_EXECUTABLE}\"
174+
$<TARGET_FILE:${target}>
175+
-verbose=1
176+
$<$<BOOL:\${debug}>:--use-debug-libs>
177+
)
178+
")
179+
endif()
229180
endfunction()
230181

182+
function(findQtInstallationTool qtdeploytoolname)
183+
if(QT_DEPLOYQT_EXECUTABLE)
184+
return()
185+
endif()
186+
get_target_property(QT_QMAKE_EXE Qt5::qmake IMPORTED_LOCATION)
187+
get_filename_component(QT_BIN_DIR "${QT_QMAKE_EXE}" DIRECTORY)
188+
find_program (QT_DEPLOYQT_EXECUTABLE ${qtdeploytoolname} HINTS "${QT_BIN_DIR}")
189+
if (QT_DEPLOYQT_EXECUTABLE)
190+
message(STATUS "Qt deploy tool found at ${QT_DEPLOYQT_EXECUTABLE}")
191+
else()
192+
message(WARNING "Qt deploy tool wasn't found, installing ${PROJECT_NAME} will fail!")
193+
return()
194+
endif()
195+
endfunction()
231196

232197
# default paths, versions and magic to guess it on windows
233198
# guess default paths for Windows / VC
@@ -330,12 +295,12 @@ macro(LSLGenerateCPackConfig)
330295
set(CPACK_PACKAGE_VENDOR "Labstreaminglayer")
331296
if(APPLE)
332297
set(CPACK_GENERATOR "TBZ2")
333-
if(DEFINED ENV{OSXVER})
334-
# Configured by Travis-CI for multi-osx builds.
335-
set(LSL_OS "$ENV{OSXVER}")
336-
else()
337-
set(LSL_OS "OSX${lslplatform}")
338-
endif(DEFINED ENV{OSXVER})
298+
if(DEFINED ENV{OSXVER})
299+
# Configured by Travis-CI for multi-osx builds.
300+
set(LSL_OS "$ENV{OSXVER}")
301+
else()
302+
set(LSL_OS "OSX${lslplatform}")
303+
endif(DEFINED ENV{OSXVER})
339304
elseif(WIN32)
340305
set(CPACK_GENERATOR ZIP) # you can create NSIS packages by calling 'cpack -G NSIS'
341306
set(CPACK_NSIS_MODIFY_PATH ON)
@@ -365,9 +330,7 @@ macro(LSLGenerateCPackConfig)
365330
get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS)
366331
foreach(component ${CPACK_COMPONENTS_ALL})
367332
string(TOUPPER ${component} COMPONENT)
368-
message(STATUS "Setting packages name for ${COMPONENT}")
369333
set(LSL_CPACK_FILENAME "${component}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-${LSL_OS}")
370-
message(STATUS "File name: ${LSL_CPACK_FILENAME}")
371334
get_property(LSLDEPENDS GLOBAL PROPERTY "LSLDEPENDS_${component}")
372335
if(LSLDEPENDS)
373336
list(REMOVE_DUPLICATES LSLDEPENDS)

0 commit comments

Comments
 (0)