mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-25 13:48:42 -05:00
Revert to standard CMake BundleUtilities.cmake script
Fix some installation dependency finding issues.
This commit is contained in:
parent
8065f3b889
commit
a3334295ef
@ -1,975 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# BundleUtilities
|
|
||||||
# ---------------
|
|
||||||
#
|
|
||||||
# Functions to help assemble a standalone bundle application.
|
|
||||||
#
|
|
||||||
# A collection of CMake utility functions useful for dealing with .app
|
|
||||||
# bundles on the Mac and bundle-like directories on any OS.
|
|
||||||
#
|
|
||||||
# The following functions are provided by this module:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# fixup_bundle
|
|
||||||
# copy_and_fixup_bundle
|
|
||||||
# verify_app
|
|
||||||
# get_bundle_main_executable
|
|
||||||
# get_dotapp_dir
|
|
||||||
# get_bundle_and_executable
|
|
||||||
# get_bundle_all_executables
|
|
||||||
# get_item_key
|
|
||||||
# get_item_rpaths
|
|
||||||
# clear_bundle_keys
|
|
||||||
# set_bundle_key_values
|
|
||||||
# get_bundle_keys
|
|
||||||
# copy_resolved_item_into_bundle
|
|
||||||
# copy_resolved_framework_into_bundle
|
|
||||||
# fixup_bundle_item
|
|
||||||
# verify_bundle_prerequisites
|
|
||||||
# verify_bundle_symlinks
|
|
||||||
#
|
|
||||||
# Requires CMake 2.6 or greater because it uses function, break and
|
|
||||||
# PARENT_SCOPE. Also depends on GetPrerequisites.cmake.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# FIXUP_BUNDLE(<app> <libs> <dirs>)
|
|
||||||
#
|
|
||||||
# Fix up a bundle in-place and make it standalone, such that it can be
|
|
||||||
# drag-n-drop copied to another machine and run on that machine as long
|
|
||||||
# as all of the system libraries are compatible.
|
|
||||||
#
|
|
||||||
# If you pass plugins to fixup_bundle as the libs parameter, you should
|
|
||||||
# install them or copy them into the bundle before calling fixup_bundle.
|
|
||||||
# The "libs" parameter is a list of libraries that must be fixed up, but
|
|
||||||
# that cannot be determined by otool output analysis. (i.e., plugins)
|
|
||||||
#
|
|
||||||
# Gather all the keys for all the executables and libraries in a bundle,
|
|
||||||
# and then, for each key, copy each prerequisite into the bundle. Then
|
|
||||||
# fix each one up according to its own list of prerequisites.
|
|
||||||
#
|
|
||||||
# Then clear all the keys and call verify_app on the final bundle to
|
|
||||||
# ensure that it is truly standalone.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
|
|
||||||
#
|
|
||||||
# Makes a copy of the bundle <src> at location <dst> and then fixes up
|
|
||||||
# the new copied bundle in-place at <dst>...
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# VERIFY_APP(<app>)
|
|
||||||
#
|
|
||||||
# Verifies that an application <app> appears valid based on running
|
|
||||||
# analysis tools on it. Calls "message(FATAL_ERROR" if the application
|
|
||||||
# is not verified.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
|
|
||||||
#
|
|
||||||
# The result will be the full path name of the bundle's main executable
|
|
||||||
# file or an "error:" prefixed string if it could not be determined.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
|
|
||||||
#
|
|
||||||
# Returns the nearest parent dir whose name ends with ".app" given the
|
|
||||||
# full path to an executable. If there is no such parent dir, then
|
|
||||||
# simply return the dir containing the executable.
|
|
||||||
#
|
|
||||||
# The returned directory may or may not exist.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
|
|
||||||
#
|
|
||||||
# Takes either a ".app" directory name or the name of an executable
|
|
||||||
# nested inside a ".app" directory and returns the path to the ".app"
|
|
||||||
# directory in <bundle_var> and the path to its main executable in
|
|
||||||
# <executable_var>
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
|
|
||||||
#
|
|
||||||
# Scans the given bundle recursively for all executable files and
|
|
||||||
# accumulates them into a variable.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_ITEM_KEY(<item> <key_var>)
|
|
||||||
#
|
|
||||||
# Given a file (item) name, generate a key that should be unique
|
|
||||||
# considering the set of libraries that need copying or fixing up to
|
|
||||||
# make a bundle standalone. This is essentially the file name including
|
|
||||||
# extension with "." replaced by "_"
|
|
||||||
#
|
|
||||||
# This key is used as a prefix for CMake variables so that we can
|
|
||||||
# associate a set of variables with a given item based on its key.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# CLEAR_BUNDLE_KEYS(<keys_var>)
|
|
||||||
#
|
|
||||||
# Loop over the list of keys, clearing all the variables associated with
|
|
||||||
# each key. After the loop, clear the list of keys itself.
|
|
||||||
#
|
|
||||||
# Caller of get_bundle_keys should call clear_bundle_keys when done with
|
|
||||||
# list of keys.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
|
|
||||||
# <copyflag> [<rpaths>])
|
|
||||||
#
|
|
||||||
# Add a key to the list (if necessary) for the given item. If added,
|
|
||||||
# also set all the variables associated with that key.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
|
|
||||||
#
|
|
||||||
# Loop over all the executable and library files within the bundle (and
|
|
||||||
# given as extra <libs>) and accumulate a list of keys representing
|
|
||||||
# them. Set values associated with each key such that we can loop over
|
|
||||||
# all of them and copy prerequisite libs into the bundle and then do
|
|
||||||
# appropriate install_name_tool fixups.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
|
|
||||||
#
|
|
||||||
# Copy a resolved item into the bundle if necessary. Copy is not
|
|
||||||
# necessary if the resolved_item is "the same as" the
|
|
||||||
# resolved_embedded_item.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
|
|
||||||
#
|
|
||||||
# Copy a resolved framework into the bundle if necessary. Copy is not
|
|
||||||
# necessary if the resolved_item is "the same as" the
|
|
||||||
# resolved_embedded_item.
|
|
||||||
#
|
|
||||||
# By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set. If you want
|
|
||||||
# full frameworks embedded in your bundles, set
|
|
||||||
# BU_COPY_FULL_FRAMEWORK_CONTENTS to ON before calling fixup_bundle. By
|
|
||||||
# default, COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework
|
|
||||||
# dylib itself plus the framework Resources directory.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
|
|
||||||
#
|
|
||||||
# Get the direct/non-system prerequisites of the resolved embedded item.
|
|
||||||
# For each prerequisite, change the way it is referenced to the value of
|
|
||||||
# the _EMBEDDED_ITEM keyed variable for that prerequisite. (Most likely
|
|
||||||
# changing to an "@executable_path" style reference.)
|
|
||||||
#
|
|
||||||
# This function requires that the resolved_embedded_item be "inside" the
|
|
||||||
# bundle already. In other words, if you pass plugins to fixup_bundle
|
|
||||||
# as the libs parameter, you should install them or copy them into the
|
|
||||||
# bundle before calling fixup_bundle. The "libs" parameter is a list of
|
|
||||||
# libraries that must be fixed up, but that cannot be determined by
|
|
||||||
# otool output analysis. (i.e., plugins)
|
|
||||||
#
|
|
||||||
# Also, change the id of the item being fixed up to its own
|
|
||||||
# _EMBEDDED_ITEM value.
|
|
||||||
#
|
|
||||||
# Accumulate changes in a local variable and make *one* call to
|
|
||||||
# install_name_tool at the end of the function with all the changes at
|
|
||||||
# once.
|
|
||||||
#
|
|
||||||
# If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be
|
|
||||||
# marked writable before install_name_tool tries to change them.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
|
|
||||||
#
|
|
||||||
# Verifies that the sum of all prerequisites of all files inside the
|
|
||||||
# bundle are contained within the bundle or are "system" libraries,
|
|
||||||
# presumed to exist everywhere.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
|
|
||||||
#
|
|
||||||
# Verifies that any symlinks found in the bundle point to other files
|
|
||||||
# that are already also in the bundle... Anything that points to an
|
|
||||||
# external file causes this function to fail the verification.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2008-2009 Kitware, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
# The functions defined in this file depend on the get_prerequisites function
|
|
||||||
# (and possibly others) found in:
|
|
||||||
#
|
|
||||||
get_filename_component(BundleUtilities_cmake_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
|
||||||
include("${BundleUtilities_cmake_dir}/GetPrerequisites.cmake")
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_main_executable bundle result_var)
|
|
||||||
set(result "error: '${bundle}/Contents/Info.plist' file does not exist")
|
|
||||||
|
|
||||||
if(EXISTS "${bundle}/Contents/Info.plist")
|
|
||||||
set(result "error: no CFBundleExecutable in '${bundle}/Contents/Info.plist' file")
|
|
||||||
set(line_is_main_executable 0)
|
|
||||||
set(bundle_executable "")
|
|
||||||
|
|
||||||
# Read Info.plist as a list of lines:
|
|
||||||
#
|
|
||||||
set(eol_char "E")
|
|
||||||
file(READ "${bundle}/Contents/Info.plist" info_plist)
|
|
||||||
string(REPLACE ";" "\\;" info_plist "${info_plist}")
|
|
||||||
string(REPLACE "\n" "${eol_char};" info_plist "${info_plist}")
|
|
||||||
string(REPLACE "\r" "${eol_char};" info_plist "${info_plist}")
|
|
||||||
|
|
||||||
# Scan the lines for "<key>CFBundleExecutable</key>" - the line after that
|
|
||||||
# is the name of the main executable.
|
|
||||||
#
|
|
||||||
foreach(line ${info_plist})
|
|
||||||
if(line_is_main_executable)
|
|
||||||
string(REGEX REPLACE "^.*<string>(.*)</string>.*$" "\\1" bundle_executable "${line}")
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(line MATCHES "<key>CFBundleExecutable</key>")
|
|
||||||
set(line_is_main_executable 1)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT "${bundle_executable}" STREQUAL "")
|
|
||||||
if(EXISTS "${bundle}/Contents/MacOS/${bundle_executable}")
|
|
||||||
set(result "${bundle}/Contents/MacOS/${bundle_executable}")
|
|
||||||
else()
|
|
||||||
|
|
||||||
# Ultimate goal:
|
|
||||||
# If not in "Contents/MacOS" then scan the bundle for matching files. If
|
|
||||||
# there is only one executable file that matches, then use it, otherwise
|
|
||||||
# it's an error...
|
|
||||||
#
|
|
||||||
#file(GLOB_RECURSE file_list "${bundle}/${bundle_executable}")
|
|
||||||
|
|
||||||
# But for now, pragmatically, it's an error. Expect the main executable
|
|
||||||
# for the bundle to be in Contents/MacOS, it's an error if it's not:
|
|
||||||
#
|
|
||||||
set(result "error: '${bundle}/Contents/MacOS/${bundle_executable}' does not exist")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
#
|
|
||||||
# More inclusive technique... (This one would work on Windows and Linux
|
|
||||||
# too, if a developer followed the typical Mac bundle naming convention...)
|
|
||||||
#
|
|
||||||
# If there is no Info.plist file, try to find an executable with the same
|
|
||||||
# base name as the .app directory:
|
|
||||||
#
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_dotapp_dir exe dotapp_dir_var)
|
|
||||||
set(s "${exe}")
|
|
||||||
|
|
||||||
if(s MATCHES "/.*\\.app/")
|
|
||||||
# If there is a ".app" parent directory,
|
|
||||||
# ascend until we hit it:
|
|
||||||
# (typical of a Mac bundle executable)
|
|
||||||
#
|
|
||||||
set(done 0)
|
|
||||||
while(NOT ${done})
|
|
||||||
get_filename_component(snamewe "${s}" NAME_WE)
|
|
||||||
get_filename_component(sname "${s}" NAME)
|
|
||||||
get_filename_component(sdir "${s}" PATH)
|
|
||||||
set(s "${sdir}")
|
|
||||||
if(sname MATCHES "\\.app$")
|
|
||||||
set(done 1)
|
|
||||||
set(dotapp_dir "${sdir}/${sname}")
|
|
||||||
endif()
|
|
||||||
endwhile()
|
|
||||||
else()
|
|
||||||
# Otherwise use a directory containing the exe
|
|
||||||
# (typical of a non-bundle executable on Mac, Windows or Linux)
|
|
||||||
#
|
|
||||||
is_file_executable("${s}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
get_filename_component(sdir "${s}" PATH)
|
|
||||||
set(dotapp_dir "${sdir}")
|
|
||||||
else()
|
|
||||||
set(dotapp_dir "${s}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
set(${dotapp_dir_var} "${dotapp_dir}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_and_executable app bundle_var executable_var valid_var)
|
|
||||||
set(valid 0)
|
|
||||||
|
|
||||||
if(EXISTS "${app}")
|
|
||||||
# Is it a directory ending in .app?
|
|
||||||
if(IS_DIRECTORY "${app}")
|
|
||||||
if(app MATCHES "\\.app$")
|
|
||||||
get_bundle_main_executable("${app}" executable)
|
|
||||||
if(EXISTS "${app}" AND EXISTS "${executable}")
|
|
||||||
set(${bundle_var} "${app}" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "${executable}" PARENT_SCOPE)
|
|
||||||
set(valid 1)
|
|
||||||
#message(STATUS "info: handled .app directory case...")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - .app directory case...")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - directory but not .app case...")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# Is it an executable file?
|
|
||||||
is_file_executable("${app}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
get_dotapp_dir("${app}" dotapp_dir)
|
|
||||||
if(EXISTS "${dotapp_dir}")
|
|
||||||
set(${bundle_var} "${dotapp_dir}" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "${app}" PARENT_SCOPE)
|
|
||||||
set(valid 1)
|
|
||||||
#message(STATUS "info: handled executable file in .app dir case...")
|
|
||||||
else()
|
|
||||||
get_filename_component(app_dir "${app}" PATH)
|
|
||||||
set(${bundle_var} "${app_dir}" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "${app}" PARENT_SCOPE)
|
|
||||||
set(valid 1)
|
|
||||||
#message(STATUS "info: handled executable file in any dir case...")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - not .app dir, not executable file...")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: *NOT* handled - directory/file does not exist...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT valid)
|
|
||||||
set(${bundle_var} "error: not a bundle" PARENT_SCOPE)
|
|
||||||
set(${executable_var} "error: not a bundle" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${valid_var} ${valid} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_all_executables bundle exes_var)
|
|
||||||
set(exes "")
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
find_program(find_cmd "find")
|
|
||||||
mark_as_advanced(find_cmd)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# find command is much quicker than checking every file one by one on Unix
|
|
||||||
# which can take long time for large bundles, and since anyway we expect
|
|
||||||
# executable to have execute flag set we can narrow the list much quicker.
|
|
||||||
if(find_cmd)
|
|
||||||
execute_process(COMMAND "${find_cmd}" "${bundle}"
|
|
||||||
-type f \( -perm -0100 -o -perm -0010 -o -perm -0001 \)
|
|
||||||
OUTPUT_VARIABLE file_list
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
string(REPLACE "\n" ";" file_list "${file_list}")
|
|
||||||
else()
|
|
||||||
file(GLOB_RECURSE file_list "${bundle}/*")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(f ${file_list})
|
|
||||||
is_file_executable("${f}" is_executable)
|
|
||||||
if(is_executable)
|
|
||||||
set(exes ${exes} "${f}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
set(${exes_var} "${exes}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_item_rpaths item rpaths_var)
|
|
||||||
if(APPLE)
|
|
||||||
find_program(otool_cmd "otool")
|
|
||||||
mark_as_advanced(otool_cmd)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(otool_cmd)
|
|
||||||
execute_process(
|
|
||||||
COMMAND "${otool_cmd}" -l "${item}"
|
|
||||||
OUTPUT_VARIABLE load_cmds_ov
|
|
||||||
)
|
|
||||||
string(REGEX REPLACE "[^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n" "rpath \\1\n" load_cmds_ov "${load_cmds_ov}")
|
|
||||||
string(REGEX MATCHALL "rpath [^\n]+" load_cmds_ov "${load_cmds_ov}")
|
|
||||||
string(REGEX REPLACE "rpath " "" load_cmds_ov "${load_cmds_ov}")
|
|
||||||
if(load_cmds_ov)
|
|
||||||
gp_append_unique(${rpaths_var} "${load_cmds_ov}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_item_key item key_var)
|
|
||||||
get_filename_component(item_name "${item}" NAME)
|
|
||||||
if(WIN32)
|
|
||||||
string(TOLOWER "${item_name}" item_name)
|
|
||||||
endif()
|
|
||||||
string(REPLACE "." "_" ${key_var} "${item_name}")
|
|
||||||
set(${key_var} ${${key_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(clear_bundle_keys keys_var)
|
|
||||||
foreach(key ${${keys_var}})
|
|
||||||
set(${key}_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_DEFAULT_EMBEDDED_PATH PARENT_SCOPE)
|
|
||||||
set(${key}_EMBEDDED_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_EMBEDDED_ITEM PARENT_SCOPE)
|
|
||||||
set(${key}_COPYFLAG PARENT_SCOPE)
|
|
||||||
set(${key}_RPATHS PARENT_SCOPE)
|
|
||||||
endforeach()
|
|
||||||
set(${keys_var} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(set_bundle_key_values keys_var context item exepath dirs copyflag)
|
|
||||||
if(ARGC GREATER 6)
|
|
||||||
set(rpaths "${ARGV6}")
|
|
||||||
else()
|
|
||||||
set(rpaths "")
|
|
||||||
endif()
|
|
||||||
get_filename_component(item_name "${item}" NAME)
|
|
||||||
|
|
||||||
get_item_key("${item}" key)
|
|
||||||
|
|
||||||
list(LENGTH ${keys_var} length_before)
|
|
||||||
gp_append_unique(${keys_var} "${key}")
|
|
||||||
list(LENGTH ${keys_var} length_after)
|
|
||||||
|
|
||||||
if(NOT length_before EQUAL length_after)
|
|
||||||
gp_resolve_item("${context}" "${item}" "${exepath}" "${dirs}" resolved_item "${rpaths}")
|
|
||||||
|
|
||||||
gp_item_default_embedded_path("${item}" default_embedded_path)
|
|
||||||
|
|
||||||
get_item_rpaths("${resolved_item}" item_rpaths)
|
|
||||||
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
# For frameworks, construct the name under the embedded path from the
|
|
||||||
# opening "${item_name}.framework/" to the closing "/${item_name}":
|
|
||||||
#
|
|
||||||
string(REGEX REPLACE "^.*(${item_name}.framework/.*/?${item_name}).*$" "${default_embedded_path}/\\1" embedded_item "${item}")
|
|
||||||
else()
|
|
||||||
# For other items, just use the same name as the original, but in the
|
|
||||||
# embedded path:
|
|
||||||
#
|
|
||||||
set(embedded_item "${default_embedded_path}/${item_name}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Replace @executable_path and resolve ".." references:
|
|
||||||
#
|
|
||||||
string(REPLACE "@executable_path" "${exepath}" resolved_embedded_item "${embedded_item}")
|
|
||||||
get_filename_component(resolved_embedded_item "${resolved_embedded_item}" ABSOLUTE)
|
|
||||||
|
|
||||||
# *But* -- if we are not copying, then force resolved_embedded_item to be
|
|
||||||
# the same as resolved_item. In the case of multiple executables in the
|
|
||||||
# original bundle, using the default_embedded_path results in looking for
|
|
||||||
# the resolved executable next to the main bundle executable. This is here
|
|
||||||
# so that exes in the other sibling directories (like "bin") get fixed up
|
|
||||||
# properly...
|
|
||||||
#
|
|
||||||
if(NOT copyflag)
|
|
||||||
set(resolved_embedded_item "${resolved_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${keys_var} ${${keys_var}} PARENT_SCOPE)
|
|
||||||
set(${key}_ITEM "${item}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_ITEM "${resolved_item}" PARENT_SCOPE)
|
|
||||||
set(${key}_DEFAULT_EMBEDDED_PATH "${default_embedded_path}" PARENT_SCOPE)
|
|
||||||
set(${key}_EMBEDDED_ITEM "${embedded_item}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_EMBEDDED_ITEM "${resolved_embedded_item}" PARENT_SCOPE)
|
|
||||||
set(${key}_COPYFLAG "${copyflag}" PARENT_SCOPE)
|
|
||||||
set(${key}_RPATHS "${item_rpaths}" PARENT_SCOPE)
|
|
||||||
set(${key}_RDEP_RPATHS "${rpaths}" PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
#message("warning: item key '${key}' already in the list, subsequent references assumed identical to first")
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_bundle_keys app libs dirs keys_var)
|
|
||||||
set(${keys_var} PARENT_SCOPE)
|
|
||||||
|
|
||||||
get_bundle_and_executable("${app}" bundle executable valid)
|
|
||||||
if(valid)
|
|
||||||
# Always use the exepath of the main bundle executable for @executable_path
|
|
||||||
# replacements:
|
|
||||||
#
|
|
||||||
get_filename_component(exepath "${executable}" PATH)
|
|
||||||
|
|
||||||
# But do fixups on all executables in the bundle:
|
|
||||||
#
|
|
||||||
get_bundle_all_executables("${bundle}" exes)
|
|
||||||
|
|
||||||
# Set keys for main executable first:
|
|
||||||
#
|
|
||||||
set_bundle_key_values(${keys_var} "${executable}" "${executable}" "${exepath}" "${dirs}" 0)
|
|
||||||
|
|
||||||
# Get rpaths specified by main executable:
|
|
||||||
#
|
|
||||||
get_item_key("${executable}" executable_key)
|
|
||||||
set(main_rpaths "${${executable_key}_RPATHS}")
|
|
||||||
|
|
||||||
# For each extra lib, accumulate a key as well and then also accumulate
|
|
||||||
# any of its prerequisites. (Extra libs are typically dynamically loaded
|
|
||||||
# plugins: libraries that are prerequisites for full runtime functionality
|
|
||||||
# but that do not show up in otool -L output...)
|
|
||||||
#
|
|
||||||
foreach(lib ${libs})
|
|
||||||
set_bundle_key_values(${keys_var} "${lib}" "${lib}" "${exepath}" "${dirs}" 0 "${main_rpaths}")
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${lib}" prereqs 1 1 "${exepath}" "${dirs}" "${main_rpaths}")
|
|
||||||
foreach(pr ${prereqs})
|
|
||||||
set_bundle_key_values(${keys_var} "${lib}" "${pr}" "${exepath}" "${dirs}" 1 "${main_rpaths}")
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# For each executable found in the bundle, accumulate keys as we go.
|
|
||||||
# The list of keys should be complete when all prerequisites of all
|
|
||||||
# binaries in the bundle have been analyzed.
|
|
||||||
#
|
|
||||||
foreach(exe ${exes})
|
|
||||||
# Main executable is scanned first above:
|
|
||||||
#
|
|
||||||
if(NOT "${exe}" STREQUAL "${executable}")
|
|
||||||
# Add the exe itself to the keys:
|
|
||||||
#
|
|
||||||
set_bundle_key_values(${keys_var} "${exe}" "${exe}" "${exepath}" "${dirs}" 0 "${main_rpaths}")
|
|
||||||
|
|
||||||
# Get rpaths specified by executable:
|
|
||||||
#
|
|
||||||
get_item_key("${exe}" exe_key)
|
|
||||||
set(exe_rpaths "${main_rpaths}" "${${exe_key}_RPATHS}")
|
|
||||||
else()
|
|
||||||
set(exe_rpaths "${main_rpaths}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Add each prerequisite to the keys:
|
|
||||||
#
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${exe}" prereqs 1 1 "${exepath}" "${dirs}" "${exe_rpaths}")
|
|
||||||
foreach(pr ${prereqs})
|
|
||||||
set_bundle_key_values(${keys_var} "${exe}" "${pr}" "${exepath}" "${dirs}" 1 "${exe_rpaths}")
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Propagate values to caller's scope:
|
|
||||||
#
|
|
||||||
set(${keys_var} ${${keys_var}} PARENT_SCOPE)
|
|
||||||
foreach(key ${${keys_var}})
|
|
||||||
set(${key}_ITEM "${${key}_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_ITEM "${${key}_RESOLVED_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_DEFAULT_EMBEDDED_PATH "${${key}_DEFAULT_EMBEDDED_PATH}" PARENT_SCOPE)
|
|
||||||
set(${key}_EMBEDDED_ITEM "${${key}_EMBEDDED_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_RESOLVED_EMBEDDED_ITEM "${${key}_RESOLVED_EMBEDDED_ITEM}" PARENT_SCOPE)
|
|
||||||
set(${key}_COPYFLAG "${${key}_COPYFLAG}" PARENT_SCOPE)
|
|
||||||
set(${key}_RPATHS "${${key}_RPATHS}" PARENT_SCOPE)
|
|
||||||
set(${key}_RDEP_RPATHS "${${key}_RDEP_RPATHS}" PARENT_SCOPE)
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item)
|
|
||||||
if(WIN32)
|
|
||||||
# ignore case on Windows
|
|
||||||
string(TOLOWER "${resolved_item}" resolved_item_compare)
|
|
||||||
string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
|
|
||||||
else()
|
|
||||||
set(resolved_item_compare "${resolved_item}")
|
|
||||||
set(resolved_embedded_item_compare "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
|
|
||||||
message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
|
|
||||||
else()
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
file(RPATH_REMOVE FILE "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(copy_resolved_framework_into_bundle resolved_item resolved_embedded_item)
|
|
||||||
if(WIN32)
|
|
||||||
# ignore case on Windows
|
|
||||||
string(TOLOWER "${resolved_item}" resolved_item_compare)
|
|
||||||
string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
|
|
||||||
else()
|
|
||||||
set(resolved_item_compare "${resolved_item}")
|
|
||||||
set(resolved_embedded_item_compare "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
|
|
||||||
message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...")
|
|
||||||
else()
|
|
||||||
if(BU_COPY_FULL_FRAMEWORK_CONTENTS)
|
|
||||||
# Full Framework (everything):
|
|
||||||
get_filename_component(resolved_dir "${resolved_item}" PATH)
|
|
||||||
get_filename_component(resolved_dir "${resolved_dir}/../.." ABSOLUTE)
|
|
||||||
get_filename_component(resolved_embedded_dir "${resolved_embedded_item}" PATH)
|
|
||||||
get_filename_component(resolved_embedded_dir "${resolved_embedded_dir}/../.." ABSOLUTE)
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_dir}' '${resolved_embedded_dir}'")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_dir}" "${resolved_embedded_dir}")
|
|
||||||
else()
|
|
||||||
# Framework lib itself:
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
|
|
||||||
|
|
||||||
# Plus Resources, if they exist:
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+$" "\\1/Resources" resolved_resources "${resolved_item}")
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+$" "\\1/Resources" resolved_embedded_resources "${resolved_embedded_item}")
|
|
||||||
if(EXISTS "${resolved_resources}")
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_resources}' '${resolved_embedded_resources}'")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_resources}" "${resolved_embedded_resources}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Some frameworks e.g. Qt put Info.plist in wrong place, so when it is
|
|
||||||
# missing in resources, copy it from other well known incorrect locations:
|
|
||||||
if(NOT EXISTS "${resolved_resources}/Info.plist")
|
|
||||||
# Check for Contents/Info.plist in framework root (older Qt SDK):
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+/[^/]+/[^/]+$" "\\1/Contents/Info.plist" resolved_info_plist "${resolved_item}")
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+$" "\\1/Resources/Info.plist" resolved_embedded_info_plist "${resolved_embedded_item}")
|
|
||||||
if(EXISTS "${resolved_info_plist}")
|
|
||||||
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy_directory '${resolved_info_plist}' '${resolved_embedded_info_plist}'")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_info_plist}" "${resolved_embedded_info_plist}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check if framework is versioned and fix it layout
|
|
||||||
string(REGEX REPLACE "^.*/([^/]+)/[^/]+$" "\\1" resolved_embedded_version "${resolved_embedded_item}")
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+/[^/]+$" "\\1" resolved_embedded_versions "${resolved_embedded_item}")
|
|
||||||
string(REGEX REPLACE "^.*/([^/]+)/[^/]+/[^/]+$" "\\1" resolved_embedded_versions_basename "${resolved_embedded_item}")
|
|
||||||
if(resolved_embedded_versions_basename STREQUAL "Versions")
|
|
||||||
# Ensure Current symlink points to the framework version
|
|
||||||
if(NOT EXISTS "${resolved_embedded_versions}/Current")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${resolved_embedded_version}" "${resolved_embedded_versions}/Current")
|
|
||||||
endif()
|
|
||||||
# Restore symlinks in framework root pointing to current framework
|
|
||||||
# binary and resources:
|
|
||||||
string(REGEX REPLACE "^(.*)/[^/]+/[^/]+/[^/]+$" "\\1" resolved_embedded_root "${resolved_embedded_item}")
|
|
||||||
string(REGEX REPLACE "^.*/([^/]+)$" "\\1" resolved_embedded_item_basename "${resolved_embedded_item}")
|
|
||||||
if(NOT EXISTS "${resolved_embedded_root}/${resolved_embedded_item_basename}")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "Versions/Current/${resolved_embedded_item_basename}" "${resolved_embedded_root}/${resolved_embedded_item_basename}")
|
|
||||||
endif()
|
|
||||||
if(NOT EXISTS "${resolved_embedded_root}/Resources")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "Versions/Current/Resources" "${resolved_embedded_root}/Resources")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
file(RPATH_REMOVE FILE "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(fixup_bundle_item resolved_embedded_item exepath dirs)
|
|
||||||
# This item's key is "ikey":
|
|
||||||
#
|
|
||||||
get_item_key("${resolved_embedded_item}" ikey)
|
|
||||||
|
|
||||||
# Ensure the item is "inside the .app bundle" -- it should not be fixed up if
|
|
||||||
# it is not in the .app bundle... Otherwise, we'll modify files in the build
|
|
||||||
# tree, or in other varied locations around the file system, with our call to
|
|
||||||
# install_name_tool. Make sure that doesn't happen here:
|
|
||||||
#
|
|
||||||
get_dotapp_dir("${exepath}" exe_dotapp_dir)
|
|
||||||
string(LENGTH "${exe_dotapp_dir}/" exe_dotapp_dir_length)
|
|
||||||
string(LENGTH "${resolved_embedded_item}" resolved_embedded_item_length)
|
|
||||||
set(path_too_short 0)
|
|
||||||
set(is_embedded 0)
|
|
||||||
if(${resolved_embedded_item_length} LESS ${exe_dotapp_dir_length})
|
|
||||||
set(path_too_short 1)
|
|
||||||
endif()
|
|
||||||
if(NOT path_too_short)
|
|
||||||
string(SUBSTRING "${resolved_embedded_item}" 0 ${exe_dotapp_dir_length} item_substring)
|
|
||||||
if("${exe_dotapp_dir}/" STREQUAL "${item_substring}")
|
|
||||||
set(is_embedded 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT is_embedded)
|
|
||||||
message(" exe_dotapp_dir/='${exe_dotapp_dir}/'")
|
|
||||||
message(" item_substring='${item_substring}'")
|
|
||||||
message(" resolved_embedded_item='${resolved_embedded_item}'")
|
|
||||||
message("")
|
|
||||||
message("Install or copy the item into the bundle before calling fixup_bundle.")
|
|
||||||
message("Or maybe there's a typo or incorrect path in one of the args to fixup_bundle?")
|
|
||||||
message("")
|
|
||||||
message(FATAL_ERROR "cannot fixup an item that is not in the bundle...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(rpaths "${${ikey}_RPATHS}" "${${ikey}_RDEP_RPATHS}")
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${resolved_embedded_item}" prereqs 1 0 "${exepath}" "${dirs}" "${rpaths}")
|
|
||||||
|
|
||||||
set(changes "")
|
|
||||||
|
|
||||||
foreach(pr ${prereqs})
|
|
||||||
# Each referenced item's key is "rkey" in the loop:
|
|
||||||
#
|
|
||||||
get_item_key("${pr}" rkey)
|
|
||||||
|
|
||||||
if(NOT "${${rkey}_EMBEDDED_ITEM}" STREQUAL "")
|
|
||||||
set(changes ${changes} "-change" "${pr}" "${${rkey}_EMBEDDED_ITEM}")
|
|
||||||
else()
|
|
||||||
message("warning: unexpected reference to '${pr}'")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(BU_CHMOD_BUNDLE_ITEMS)
|
|
||||||
execute_process(COMMAND chmod u+w "${resolved_embedded_item}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Only if install_name_tool supports -delete_rpath:
|
|
||||||
#
|
|
||||||
execute_process(COMMAND install_name_tool
|
|
||||||
OUTPUT_VARIABLE install_name_tool_usage
|
|
||||||
ERROR_VARIABLE install_name_tool_usage
|
|
||||||
)
|
|
||||||
if(install_name_tool_usage MATCHES ".*-delete_rpath.*")
|
|
||||||
foreach(rpath ${${ikey}_RPATHS})
|
|
||||||
set(changes ${changes} -delete_rpath "${rpath}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${ikey}_EMBEDDED_ITEM)
|
|
||||||
set(changes ${changes} -id "${${ikey}_EMBEDDED_ITEM}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Change this item's id and all of its references in one call
|
|
||||||
# to install_name_tool:
|
|
||||||
#
|
|
||||||
if(changes)
|
|
||||||
set(cmd install_name_tool ${changes} "${resolved_embedded_item}")
|
|
||||||
execute_process(COMMAND ${cmd} RESULT_VARIABLE install_name_tool_result)
|
|
||||||
if(NOT install_name_tool_result EQUAL 0)
|
|
||||||
string(REPLACE ";" "' '" msg "'${cmd}'")
|
|
||||||
message(FATAL_ERROR "Command failed:\n ${msg}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(fixup_bundle app libs dirs)
|
|
||||||
message(STATUS "fixup_bundle")
|
|
||||||
message(STATUS " app='${app}'")
|
|
||||||
message(STATUS " libs='${libs}'")
|
|
||||||
message(STATUS " dirs='${dirs}'")
|
|
||||||
|
|
||||||
get_bundle_and_executable("${app}" bundle executable valid)
|
|
||||||
if(valid)
|
|
||||||
get_filename_component(exepath "${executable}" PATH)
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: preparing...")
|
|
||||||
get_bundle_keys("${app}" "${libs}" "${dirs}" keys)
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: copying...")
|
|
||||||
list(LENGTH keys n)
|
|
||||||
math(EXPR n ${n}*2)
|
|
||||||
|
|
||||||
set(i 0)
|
|
||||||
foreach(key ${keys})
|
|
||||||
math(EXPR i ${i}+1)
|
|
||||||
if(${${key}_COPYFLAG})
|
|
||||||
message(STATUS "${i}/${n}: copying '${${key}_RESOLVED_ITEM}'")
|
|
||||||
else()
|
|
||||||
message(STATUS "${i}/${n}: *NOT* copying '${${key}_RESOLVED_ITEM}'")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(show_status 0)
|
|
||||||
if(show_status)
|
|
||||||
message(STATUS "key='${key}'")
|
|
||||||
message(STATUS "item='${${key}_ITEM}'")
|
|
||||||
message(STATUS "resolved_item='${${key}_RESOLVED_ITEM}'")
|
|
||||||
message(STATUS "default_embedded_path='${${key}_DEFAULT_EMBEDDED_PATH}'")
|
|
||||||
message(STATUS "embedded_item='${${key}_EMBEDDED_ITEM}'")
|
|
||||||
message(STATUS "resolved_embedded_item='${${key}_RESOLVED_EMBEDDED_ITEM}'")
|
|
||||||
message(STATUS "copyflag='${${key}_COPYFLAG}'")
|
|
||||||
message(STATUS "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${${key}_COPYFLAG})
|
|
||||||
set(item "${${key}_ITEM}")
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
copy_resolved_framework_into_bundle("${${key}_RESOLVED_ITEM}"
|
|
||||||
"${${key}_RESOLVED_EMBEDDED_ITEM}")
|
|
||||||
else()
|
|
||||||
copy_resolved_item_into_bundle("${${key}_RESOLVED_ITEM}"
|
|
||||||
"${${key}_RESOLVED_EMBEDDED_ITEM}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: fixing...")
|
|
||||||
foreach(key ${keys})
|
|
||||||
math(EXPR i ${i}+1)
|
|
||||||
if(APPLE)
|
|
||||||
message(STATUS "${i}/${n}: fixing up '${${key}_RESOLVED_EMBEDDED_ITEM}'")
|
|
||||||
fixup_bundle_item("${${key}_RESOLVED_EMBEDDED_ITEM}" "${exepath}" "${dirs}")
|
|
||||||
else()
|
|
||||||
message(STATUS "${i}/${n}: fix-up not required on this platform '${${key}_RESOLVED_EMBEDDED_ITEM}'")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: cleaning up...")
|
|
||||||
clear_bundle_keys(keys)
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: verifying...")
|
|
||||||
verify_app("${app}")
|
|
||||||
else()
|
|
||||||
message(SEND_ERROR "error: fixup_bundle: not a valid bundle")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "fixup_bundle: done")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(copy_and_fixup_bundle src dst libs dirs)
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${src}" "${dst}")
|
|
||||||
fixup_bundle("${dst}" "${libs}" "${dirs}")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(verify_bundle_prerequisites bundle result_var info_var)
|
|
||||||
set(result 1)
|
|
||||||
set(info "")
|
|
||||||
set(count 0)
|
|
||||||
|
|
||||||
get_bundle_main_executable("${bundle}" main_bundle_exe)
|
|
||||||
|
|
||||||
get_bundle_all_executables("${bundle}" file_list)
|
|
||||||
foreach(f ${file_list})
|
|
||||||
get_filename_component(exepath "${f}" PATH)
|
|
||||||
math(EXPR count "${count} + 1")
|
|
||||||
|
|
||||||
message(STATUS "executable file ${count}: ${f}")
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${f}" prereqs 1 1 "${exepath}" "")
|
|
||||||
|
|
||||||
# On the Mac,
|
|
||||||
# "embedded" and "system" prerequisites are fine... anything else means
|
|
||||||
# the bundle's prerequisites are not verified (i.e., the bundle is not
|
|
||||||
# really "standalone")
|
|
||||||
#
|
|
||||||
# On Windows (and others? Linux/Unix/...?)
|
|
||||||
# "local" and "system" prereqs are fine...
|
|
||||||
#
|
|
||||||
set(external_prereqs "")
|
|
||||||
|
|
||||||
foreach(p ${prereqs})
|
|
||||||
set(p_type "")
|
|
||||||
gp_file_type("${f}" "${p}" p_type)
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
if(NOT "${p_type}" STREQUAL "embedded" AND NOT "${p_type}" STREQUAL "system")
|
|
||||||
set(external_prereqs ${external_prereqs} "${p}")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if(NOT "${p_type}" STREQUAL "local" AND NOT "${p_type}" STREQUAL "system")
|
|
||||||
set(external_prereqs ${external_prereqs} "${p}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(external_prereqs)
|
|
||||||
# Found non-system/somehow-unacceptable prerequisites:
|
|
||||||
set(result 0)
|
|
||||||
set(info ${info} "external prerequisites found:\nf='${f}'\nexternal_prereqs='${external_prereqs}'\n")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(result)
|
|
||||||
set(info "Verified ${count} executable files in '${bundle}'")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
|
||||||
set(${info_var} "${info}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(verify_bundle_symlinks bundle result_var info_var)
|
|
||||||
set(result 1)
|
|
||||||
set(info "")
|
|
||||||
set(count 0)
|
|
||||||
|
|
||||||
# TODO: implement this function for real...
|
|
||||||
# Right now, it is just a stub that verifies unconditionally...
|
|
||||||
|
|
||||||
set(${result_var} "${result}" PARENT_SCOPE)
|
|
||||||
set(${info_var} "${info}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(verify_app app)
|
|
||||||
set(verified 0)
|
|
||||||
set(info "")
|
|
||||||
|
|
||||||
get_bundle_and_executable("${app}" bundle executable valid)
|
|
||||||
|
|
||||||
message(STATUS "===========================================================================")
|
|
||||||
message(STATUS "Analyzing app='${app}'")
|
|
||||||
message(STATUS "bundle='${bundle}'")
|
|
||||||
message(STATUS "executable='${executable}'")
|
|
||||||
message(STATUS "valid='${valid}'")
|
|
||||||
|
|
||||||
# Verify that the bundle does not have any "external" prerequisites:
|
|
||||||
#
|
|
||||||
verify_bundle_prerequisites("${bundle}" verified info)
|
|
||||||
message(STATUS "verified='${verified}'")
|
|
||||||
message(STATUS "info='${info}'")
|
|
||||||
message(STATUS "")
|
|
||||||
|
|
||||||
if(verified)
|
|
||||||
# Verify that the bundle does not have any symlinks to external files:
|
|
||||||
#
|
|
||||||
verify_bundle_symlinks("${bundle}" verified info)
|
|
||||||
message(STATUS "verified='${verified}'")
|
|
||||||
message(STATUS "info='${info}'")
|
|
||||||
message(STATUS "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT verified)
|
|
||||||
message(FATAL_ERROR "error: verify_app failed")
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
@ -1,998 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# GetPrerequisites
|
|
||||||
# ----------------
|
|
||||||
#
|
|
||||||
# Functions to analyze and list executable file prerequisites.
|
|
||||||
#
|
|
||||||
# This module provides functions to list the .dll, .dylib or .so files
|
|
||||||
# that an executable or shared library file depends on. (Its
|
|
||||||
# prerequisites.)
|
|
||||||
#
|
|
||||||
# It uses various tools to obtain the list of required shared library
|
|
||||||
# files:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# dumpbin (Windows)
|
|
||||||
# objdump (MinGW on Windows)
|
|
||||||
# ldd (Linux/Unix)
|
|
||||||
# otool (Mac OSX)
|
|
||||||
#
|
|
||||||
# The following functions are provided by this module:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# get_prerequisites
|
|
||||||
# list_prerequisites
|
|
||||||
# list_prerequisites_by_glob
|
|
||||||
# gp_append_unique
|
|
||||||
# is_file_executable
|
|
||||||
# gp_item_default_embedded_path
|
|
||||||
# (projects can override with gp_item_default_embedded_path_override)
|
|
||||||
# gp_resolve_item
|
|
||||||
# (projects can override with gp_resolve_item_override)
|
|
||||||
# gp_resolved_file_type
|
|
||||||
# (projects can override with gp_resolved_file_type_override)
|
|
||||||
# gp_file_type
|
|
||||||
#
|
|
||||||
# Requires CMake 2.6 or greater because it uses function, break, return
|
|
||||||
# and PARENT_SCOPE.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GET_PREREQUISITES(<target> <prerequisites_var> <exclude_system> <recurse>
|
|
||||||
# <exepath> <dirs> [<rpaths>])
|
|
||||||
#
|
|
||||||
# Get the list of shared library files required by <target>. The list
|
|
||||||
# in the variable named <prerequisites_var> should be empty on first
|
|
||||||
# entry to this function. On exit, <prerequisites_var> will contain the
|
|
||||||
# list of required shared library files.
|
|
||||||
#
|
|
||||||
# <target> is the full path to an executable file. <prerequisites_var>
|
|
||||||
# is the name of a CMake variable to contain the results.
|
|
||||||
# <exclude_system> must be 0 or 1 indicating whether to include or
|
|
||||||
# exclude "system" prerequisites. If <recurse> is set to 1 all
|
|
||||||
# prerequisites will be found recursively, if set to 0 only direct
|
|
||||||
# prerequisites are listed. <exepath> is the path to the top level
|
|
||||||
# executable used for @executable_path replacment on the Mac. <dirs> is
|
|
||||||
# a list of paths where libraries might be found: these paths are
|
|
||||||
# searched first when a target without any path info is given. Then
|
|
||||||
# standard system locations are also searched: PATH, Framework
|
|
||||||
# locations, /usr/lib...
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# LIST_PREREQUISITES(<target> [<recurse> [<exclude_system> [<verbose>]]])
|
|
||||||
#
|
|
||||||
# Print a message listing the prerequisites of <target>.
|
|
||||||
#
|
|
||||||
# <target> is the name of a shared library or executable target or the
|
|
||||||
# full path to a shared library or executable file. If <recurse> is set
|
|
||||||
# to 1 all prerequisites will be found recursively, if set to 0 only
|
|
||||||
# direct prerequisites are listed. <exclude_system> must be 0 or 1
|
|
||||||
# indicating whether to include or exclude "system" prerequisites. With
|
|
||||||
# <verbose> set to 0 only the full path names of the prerequisites are
|
|
||||||
# printed, set to 1 extra informatin will be displayed.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# LIST_PREREQUISITES_BY_GLOB(<glob_arg> <glob_exp>)
|
|
||||||
#
|
|
||||||
# Print the prerequisites of shared library and executable files
|
|
||||||
# matching a globbing pattern. <glob_arg> is GLOB or GLOB_RECURSE and
|
|
||||||
# <glob_exp> is a globbing expression used with "file(GLOB" or
|
|
||||||
# "file(GLOB_RECURSE" to retrieve a list of matching files. If a
|
|
||||||
# matching file is executable, its prerequisites are listed.
|
|
||||||
#
|
|
||||||
# Any additional (optional) arguments provided are passed along as the
|
|
||||||
# optional arguments to the list_prerequisites calls.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GP_APPEND_UNIQUE(<list_var> <value>)
|
|
||||||
#
|
|
||||||
# Append <value> to the list variable <list_var> only if the value is
|
|
||||||
# not already in the list.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# IS_FILE_EXECUTABLE(<file> <result_var>)
|
|
||||||
#
|
|
||||||
# Return 1 in <result_var> if <file> is a binary executable, 0
|
|
||||||
# otherwise.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GP_ITEM_DEFAULT_EMBEDDED_PATH(<item> <default_embedded_path_var>)
|
|
||||||
#
|
|
||||||
# Return the path that others should refer to the item by when the item
|
|
||||||
# is embedded inside a bundle.
|
|
||||||
#
|
|
||||||
# Override on a per-project basis by providing a project-specific
|
|
||||||
# gp_item_default_embedded_path_override function.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GP_RESOLVE_ITEM(<context> <item> <exepath> <dirs> <resolved_item_var>
|
|
||||||
# [<rpaths>])
|
|
||||||
#
|
|
||||||
# Resolve an item into an existing full path file.
|
|
||||||
#
|
|
||||||
# Override on a per-project basis by providing a project-specific
|
|
||||||
# gp_resolve_item_override function.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GP_RESOLVED_FILE_TYPE(<original_file> <file> <exepath> <dirs> <type_var>
|
|
||||||
# [<rpaths>])
|
|
||||||
#
|
|
||||||
# Return the type of <file> with respect to <original_file>. String
|
|
||||||
# describing type of prerequisite is returned in variable named
|
|
||||||
# <type_var>.
|
|
||||||
#
|
|
||||||
# Use <exepath> and <dirs> if necessary to resolve non-absolute <file>
|
|
||||||
# values -- but only for non-embedded items.
|
|
||||||
#
|
|
||||||
# Possible types are:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# system
|
|
||||||
# local
|
|
||||||
# embedded
|
|
||||||
# other
|
|
||||||
#
|
|
||||||
# Override on a per-project basis by providing a project-specific
|
|
||||||
# gp_resolved_file_type_override function.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# GP_FILE_TYPE(<original_file> <file> <type_var>)
|
|
||||||
#
|
|
||||||
# Return the type of <file> with respect to <original_file>. String
|
|
||||||
# describing type of prerequisite is returned in variable named
|
|
||||||
# <type_var>.
|
|
||||||
#
|
|
||||||
# Possible types are:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# system
|
|
||||||
# local
|
|
||||||
# embedded
|
|
||||||
# other
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2008-2009 Kitware, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
function(gp_append_unique list_var value)
|
|
||||||
set(contains 0)
|
|
||||||
|
|
||||||
foreach(item ${${list_var}})
|
|
||||||
if(item STREQUAL "${value}")
|
|
||||||
set(contains 1)
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT contains)
|
|
||||||
set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(is_file_executable file result_var)
|
|
||||||
#
|
|
||||||
# A file is not executable until proven otherwise:
|
|
||||||
#
|
|
||||||
set(${result_var} 0 PARENT_SCOPE)
|
|
||||||
|
|
||||||
get_filename_component(file_full "${file}" ABSOLUTE)
|
|
||||||
string(TOLOWER "${file_full}" file_full_lower)
|
|
||||||
|
|
||||||
# If file name ends in .exe on Windows, *assume* executable:
|
|
||||||
#
|
|
||||||
if(WIN32 AND NOT UNIX)
|
|
||||||
if("${file_full_lower}" MATCHES "\\.exe$")
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# A clause could be added here that uses output or return value of dumpbin
|
|
||||||
# to determine ${result_var}. In 99%+? practical cases, the exe name
|
|
||||||
# match will be sufficient...
|
|
||||||
#
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Use the information returned from the Unix shell command "file" to
|
|
||||||
# determine if ${file_full} should be considered an executable file...
|
|
||||||
#
|
|
||||||
# If the file command's output contains "executable" and does *not* contain
|
|
||||||
# "text" then it is likely an executable suitable for prerequisite analysis
|
|
||||||
# via the get_prerequisites macro.
|
|
||||||
#
|
|
||||||
if(UNIX)
|
|
||||||
if(NOT file_cmd)
|
|
||||||
find_program(file_cmd "file")
|
|
||||||
mark_as_advanced(file_cmd)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(file_cmd)
|
|
||||||
execute_process(COMMAND "${file_cmd}" "${file_full}"
|
|
||||||
RESULT_VARIABLE file_rv
|
|
||||||
OUTPUT_VARIABLE file_ov
|
|
||||||
ERROR_VARIABLE file_ev
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
if(NOT file_rv STREQUAL "0")
|
|
||||||
message(FATAL_ERROR "${file_cmd} failed: ${file_rv}\n${file_ev}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Replace the name of the file in the output with a placeholder token
|
|
||||||
# (the string " _file_full_ ") so that just in case the path name of
|
|
||||||
# the file contains the word "text" or "executable" we are not fooled
|
|
||||||
# into thinking "the wrong thing" because the file name matches the
|
|
||||||
# other 'file' command output we are looking for...
|
|
||||||
#
|
|
||||||
string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
|
|
||||||
string(TOLOWER "${file_ov}" file_ov)
|
|
||||||
|
|
||||||
#message(STATUS "file_ov='${file_ov}'")
|
|
||||||
if("${file_ov}" MATCHES "executable")
|
|
||||||
#message(STATUS "executable!")
|
|
||||||
if("${file_ov}" MATCHES "text")
|
|
||||||
#message(STATUS "but text, so *not* a binary executable!")
|
|
||||||
else()
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Also detect position independent executables on Linux,
|
|
||||||
# where "file" gives "shared object ... (uses shared libraries)"
|
|
||||||
if("${file_ov}" MATCHES "shared object.*\(uses shared libs\)")
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# "file" version 5.22 does not print "(used shared libraries)"
|
|
||||||
# but uses "interpreter"
|
|
||||||
if("${file_ov}" MATCHES "shared object.*interpreter")
|
|
||||||
set(${result_var} 1 PARENT_SCOPE)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: No 'file' command, skipping execute_process...")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_item_default_embedded_path item default_embedded_path_var)
|
|
||||||
|
|
||||||
# On Windows and Linux, "embed" prerequisites in the same directory
|
|
||||||
# as the executable by default:
|
|
||||||
#
|
|
||||||
set(path "@executable_path")
|
|
||||||
set(overridden 0)
|
|
||||||
|
|
||||||
# On the Mac, relative to the executable depending on the type
|
|
||||||
# of the thing we are embedding:
|
|
||||||
#
|
|
||||||
if(APPLE)
|
|
||||||
#
|
|
||||||
# The assumption here is that all executables in the bundle will be
|
|
||||||
# in same-level-directories inside the bundle. The parent directory
|
|
||||||
# of an executable inside the bundle should be MacOS or a sibling of
|
|
||||||
# MacOS and all embedded paths returned from here will begin with
|
|
||||||
# "@executable_path/../" and will work from all executables in all
|
|
||||||
# such same-level-directories inside the bundle.
|
|
||||||
#
|
|
||||||
|
|
||||||
# By default, embed things right next to the main bundle executable:
|
|
||||||
#
|
|
||||||
set(path "@executable_path/../../Contents/MacOS")
|
|
||||||
|
|
||||||
# Embed .dylibs right next to the main bundle executable:
|
|
||||||
#
|
|
||||||
if(item MATCHES "\\.dylib$")
|
|
||||||
set(path "@executable_path/../MacOS")
|
|
||||||
set(overridden 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
|
|
||||||
#
|
|
||||||
if(NOT overridden)
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
set(path "@executable_path/../Frameworks")
|
|
||||||
set(overridden 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Provide a hook so that projects can override the default embedded location
|
|
||||||
# of any given library by whatever logic they choose:
|
|
||||||
#
|
|
||||||
if(COMMAND gp_item_default_embedded_path_override)
|
|
||||||
gp_item_default_embedded_path_override("${item}" path)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_resolve_item context item exepath dirs resolved_item_var)
|
|
||||||
set(resolved 0)
|
|
||||||
set(resolved_item "${item}")
|
|
||||||
if(ARGC GREATER 5)
|
|
||||||
set(rpaths "${ARGV5}")
|
|
||||||
else()
|
|
||||||
set(rpaths "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Is it already resolved?
|
|
||||||
#
|
|
||||||
if(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
|
|
||||||
set(resolved 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "^@executable_path")
|
|
||||||
#
|
|
||||||
# @executable_path references are assumed relative to exepath
|
|
||||||
#
|
|
||||||
string(REPLACE "@executable_path" "${exepath}" ri "${item}")
|
|
||||||
get_filename_component(ri "${ri}" ABSOLUTE)
|
|
||||||
|
|
||||||
if(EXISTS "${ri}")
|
|
||||||
#message(STATUS "info: embedded item exists (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: embedded item does not exist '${ri}'")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "^@loader_path")
|
|
||||||
#
|
|
||||||
# @loader_path references are assumed relative to the
|
|
||||||
# PATH of the given "context" (presumably another library)
|
|
||||||
#
|
|
||||||
get_filename_component(contextpath "${context}" PATH)
|
|
||||||
string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
|
|
||||||
get_filename_component(ri "${ri}" ABSOLUTE)
|
|
||||||
|
|
||||||
if(EXISTS "${ri}")
|
|
||||||
#message(STATUS "info: embedded item exists (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: embedded item does not exist '${ri}'")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "^@rpath")
|
|
||||||
#
|
|
||||||
# @rpath references are relative to the paths built into the binaries with -rpath
|
|
||||||
# We handle this case like we do for other Unixes
|
|
||||||
#
|
|
||||||
string(REPLACE "@rpath/" "" norpath_item "${item}")
|
|
||||||
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
find_file(ri "${norpath_item}" ${exepath} ${dirs} ${rpaths} NO_DEFAULT_PATH)
|
|
||||||
if(ri)
|
|
||||||
#message(STATUS "info: 'find_file' in exepath/dirs/rpaths (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
|
|
||||||
find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
|
|
||||||
if(ri)
|
|
||||||
#message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
if(item MATCHES "[^/]+\\.framework/")
|
|
||||||
set(fw "fw-NOTFOUND")
|
|
||||||
find_file(fw "${item}"
|
|
||||||
"~/Library/Frameworks"
|
|
||||||
"/Library/Frameworks"
|
|
||||||
"/System/Library/Frameworks"
|
|
||||||
)
|
|
||||||
if(fw)
|
|
||||||
#message(STATUS "info: 'find_file' found framework (${fw})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${fw}")
|
|
||||||
set(fw "fw-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Using find_program on Windows will find dll files that are in the PATH.
|
|
||||||
# (Converting simple file names into full path names if found.)
|
|
||||||
#
|
|
||||||
if(WIN32 AND NOT UNIX)
|
|
||||||
if(NOT resolved)
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
|
|
||||||
find_program(ri "${item}" PATHS "${exepath};${dirs}")
|
|
||||||
if(ri)
|
|
||||||
#message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
|
|
||||||
set(resolved 1)
|
|
||||||
set(resolved_item "${ri}")
|
|
||||||
set(ri "ri-NOTFOUND")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Provide a hook so that projects can override item resolution
|
|
||||||
# by whatever logic they choose:
|
|
||||||
#
|
|
||||||
if(COMMAND gp_resolve_item_override)
|
|
||||||
gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT resolved)
|
|
||||||
message(STATUS "
|
|
||||||
warning: cannot resolve item '${item}'
|
|
||||||
|
|
||||||
possible problems:
|
|
||||||
need more directories?
|
|
||||||
need to use InstallRequiredSystemLibraries?
|
|
||||||
run in install tree instead of build tree?
|
|
||||||
")
|
|
||||||
# message(STATUS "
|
|
||||||
#******************************************************************************
|
|
||||||
#warning: cannot resolve item '${item}'
|
|
||||||
#
|
|
||||||
# possible problems:
|
|
||||||
# need more directories?
|
|
||||||
# need to use InstallRequiredSystemLibraries?
|
|
||||||
# run in install tree instead of build tree?
|
|
||||||
#
|
|
||||||
# context='${context}'
|
|
||||||
# item='${item}'
|
|
||||||
# exepath='${exepath}'
|
|
||||||
# dirs='${dirs}'
|
|
||||||
# resolved_item_var='${resolved_item_var}'
|
|
||||||
#******************************************************************************
|
|
||||||
#")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_resolved_file_type original_file file exepath dirs type_var)
|
|
||||||
if(ARGC GREATER 5)
|
|
||||||
set(rpaths "${ARGV5}")
|
|
||||||
else()
|
|
||||||
set(rpaths "")
|
|
||||||
endif()
|
|
||||||
#message(STATUS "**")
|
|
||||||
|
|
||||||
if(NOT IS_ABSOLUTE "${original_file}")
|
|
||||||
message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(is_embedded 0)
|
|
||||||
set(is_local 0)
|
|
||||||
set(is_system 0)
|
|
||||||
|
|
||||||
set(resolved_file "${file}")
|
|
||||||
|
|
||||||
if("${file}" MATCHES "^@(executable|loader)_path")
|
|
||||||
set(is_embedded 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT is_embedded)
|
|
||||||
if(NOT IS_ABSOLUTE "${file}")
|
|
||||||
gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file "${rpaths}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
string(TOLOWER "${original_file}" original_lower)
|
|
||||||
string(TOLOWER "${resolved_file}" lower)
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
string(TOLOWER "$ENV{SystemRoot}" sysroot)
|
|
||||||
file(TO_CMAKE_PATH "${sysroot}" sysroot)
|
|
||||||
|
|
||||||
string(TOLOWER "$ENV{windir}" windir)
|
|
||||||
file(TO_CMAKE_PATH "${windir}" windir)
|
|
||||||
|
|
||||||
if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
# if cygwin, we can get the properly formed windows paths from cygpath
|
|
||||||
find_program(CYGPATH_EXECUTABLE cygpath)
|
|
||||||
|
|
||||||
if(CYGPATH_EXECUTABLE)
|
|
||||||
execute_process(COMMAND ${CYGPATH_EXECUTABLE} -W
|
|
||||||
RESULT_VARIABLE env_rv
|
|
||||||
OUTPUT_VARIABLE env_windir
|
|
||||||
ERROR_VARIABLE env_ev
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
if(NOT env_rv STREQUAL "0")
|
|
||||||
message(FATAL_ERROR "${CYGPATH_EXECUTABLE} -W failed: ${env_rv}\n${env_ev}")
|
|
||||||
endif()
|
|
||||||
execute_process(COMMAND ${CYGPATH_EXECUTABLE} -S
|
|
||||||
RESULT_VARIABLE env_rv
|
|
||||||
OUTPUT_VARIABLE env_sysdir
|
|
||||||
ERROR_VARIABLE env_ev
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
if(NOT env_rv STREQUAL "0")
|
|
||||||
message(FATAL_ERROR "${CYGPATH_EXECUTABLE} -S failed: ${env_rv}\n${env_ev}")
|
|
||||||
endif()
|
|
||||||
string(TOLOWER "${env_windir}" windir)
|
|
||||||
string(TOLOWER "${env_sysdir}" sysroot)
|
|
||||||
|
|
||||||
if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
|
|
||||||
set(is_system 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT is_system)
|
|
||||||
get_filename_component(original_path "${original_lower}" PATH)
|
|
||||||
get_filename_component(path "${lower}" PATH)
|
|
||||||
if(original_path STREQUAL path)
|
|
||||||
set(is_local 1)
|
|
||||||
else()
|
|
||||||
string(LENGTH "${original_path}/" original_length)
|
|
||||||
string(LENGTH "${lower}" path_length)
|
|
||||||
if(${path_length} GREATER ${original_length})
|
|
||||||
string(SUBSTRING "${lower}" 0 ${original_length} path)
|
|
||||||
if("${original_path}/" STREQUAL path)
|
|
||||||
set(is_embedded 1)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Return type string based on computed booleans:
|
|
||||||
#
|
|
||||||
set(type "other")
|
|
||||||
|
|
||||||
if(is_system)
|
|
||||||
set(type "system")
|
|
||||||
elseif(is_embedded)
|
|
||||||
set(type "embedded")
|
|
||||||
elseif(is_local)
|
|
||||||
set(type "local")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
|
|
||||||
#message(STATUS " type: '${type}'")
|
|
||||||
|
|
||||||
if(NOT is_embedded)
|
|
||||||
if(NOT IS_ABSOLUTE "${resolved_file}")
|
|
||||||
if(lower MATCHES "^msvc[^/]+dll" AND is_system)
|
|
||||||
message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Provide a hook so that projects can override the decision on whether a
|
|
||||||
# library belongs to the system or not by whatever logic they choose:
|
|
||||||
#
|
|
||||||
if(COMMAND gp_resolved_file_type_override)
|
|
||||||
gp_resolved_file_type_override("${resolved_file}" type)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${type_var} "${type}" PARENT_SCOPE)
|
|
||||||
|
|
||||||
#message(STATUS "**")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(gp_file_type original_file file type_var)
|
|
||||||
if(NOT IS_ABSOLUTE "${original_file}")
|
|
||||||
message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(exepath "${original_file}" PATH)
|
|
||||||
|
|
||||||
set(type "")
|
|
||||||
gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
|
|
||||||
|
|
||||||
set(${type_var} "${type}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
|
|
||||||
set(verbose 0)
|
|
||||||
set(eol_char "E")
|
|
||||||
if(ARGC GREATER 6)
|
|
||||||
set(rpaths "${ARGV6}")
|
|
||||||
else()
|
|
||||||
set(rpaths "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT IS_ABSOLUTE "${target}")
|
|
||||||
message("warning: target '${target}' is not absolute...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT EXISTS "${target}")
|
|
||||||
message("warning: target '${target}' does not exist...")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(gp_cmd_paths ${gp_cmd_paths}
|
|
||||||
"C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
|
|
||||||
"C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
|
|
||||||
"C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
|
|
||||||
"C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
|
|
||||||
"C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
|
|
||||||
"C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
|
|
||||||
"/usr/local/bin"
|
|
||||||
"/usr/bin"
|
|
||||||
)
|
|
||||||
|
|
||||||
# <setup-gp_tool-vars>
|
|
||||||
#
|
|
||||||
# Try to choose the right tool by default. Caller can set gp_tool prior to
|
|
||||||
# calling this function to force using a different tool.
|
|
||||||
#
|
|
||||||
if(NOT gp_tool)
|
|
||||||
set(gp_tool "ldd")
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
set(gp_tool "otool")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32 AND NOT UNIX) # This is how to check for cygwin, har!
|
|
||||||
find_program(gp_dumpbin "dumpbin" PATHS ${gp_cmd_paths})
|
|
||||||
if(gp_dumpbin)
|
|
||||||
set(gp_tool "dumpbin")
|
|
||||||
else() # Try harder. Maybe we're on MinGW
|
|
||||||
set(gp_tool "objdump")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
|
|
||||||
|
|
||||||
if(NOT gp_cmd)
|
|
||||||
message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(gp_cmd_maybe_filter) # optional command to pre-filter gp_tool results
|
|
||||||
|
|
||||||
if(gp_tool STREQUAL "ldd")
|
|
||||||
set(gp_cmd_args "")
|
|
||||||
set(gp_regex "^[\t ]*[^\t ]+ => ([^\t\(]+) .*${eol_char}$")
|
|
||||||
set(gp_regex_error "not found${eol_char}$")
|
|
||||||
set(gp_regex_fallback "^[\t ]*([^\t ]+) => ([^\t ]+).*${eol_char}$")
|
|
||||||
set(gp_regex_cmp_count 1)
|
|
||||||
elseif(gp_tool STREQUAL "otool")
|
|
||||||
set(gp_cmd_args "-L")
|
|
||||||
set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
|
|
||||||
set(gp_regex_error "")
|
|
||||||
set(gp_regex_fallback "")
|
|
||||||
set(gp_regex_cmp_count 3)
|
|
||||||
elseif(gp_tool STREQUAL "dumpbin")
|
|
||||||
set(gp_cmd_args "/dependents")
|
|
||||||
set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$")
|
|
||||||
set(gp_regex_error "")
|
|
||||||
set(gp_regex_fallback "")
|
|
||||||
set(gp_regex_cmp_count 1)
|
|
||||||
elseif(gp_tool STREQUAL "objdump")
|
|
||||||
set(gp_cmd_args "-p")
|
|
||||||
set(gp_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$")
|
|
||||||
set(gp_regex_error "")
|
|
||||||
set(gp_regex_fallback "")
|
|
||||||
set(gp_regex_cmp_count 1)
|
|
||||||
# objdump generaates copious output so we create a grep filter to pre-filter results
|
|
||||||
find_program(gp_grep_cmd grep)
|
|
||||||
if(gp_grep_cmd)
|
|
||||||
set(gp_cmd_maybe_filter COMMAND ${gp_grep_cmd} "^[[:blank:]]*DLL Name: ")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
|
|
||||||
message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
|
|
||||||
message(STATUS "Valid gp_tool values are dumpbin, ldd, objdump and otool.")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if(gp_tool STREQUAL "dumpbin")
|
|
||||||
# When running dumpbin, it also needs the "Common7/IDE" directory in the
|
|
||||||
# PATH. It will already be in the PATH if being run from a Visual Studio
|
|
||||||
# command prompt. Add it to the PATH here in case we are running from a
|
|
||||||
# different command prompt.
|
|
||||||
#
|
|
||||||
get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
|
|
||||||
get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
|
|
||||||
# Use cmake paths as a user may have a PATH element ending with a backslash.
|
|
||||||
# This will escape the list delimiter and create havoc!
|
|
||||||
if(EXISTS "${gp_cmd_dlls_dir}")
|
|
||||||
# only add to the path if it is not already in the path
|
|
||||||
set(gp_found_cmd_dlls_dir 0)
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PATH}" env_path)
|
|
||||||
foreach(gp_env_path_element ${env_path})
|
|
||||||
if(gp_env_path_element STREQUAL gp_cmd_dlls_dir)
|
|
||||||
set(gp_found_cmd_dlls_dir 1)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
if(NOT gp_found_cmd_dlls_dir)
|
|
||||||
file(TO_NATIVE_PATH "${gp_cmd_dlls_dir}" gp_cmd_dlls_dir)
|
|
||||||
set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
# </setup-gp_tool-vars>
|
|
||||||
|
|
||||||
if(gp_tool STREQUAL "ldd")
|
|
||||||
set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
|
|
||||||
set(new_ld_env "${exepath}")
|
|
||||||
foreach(dir ${dirs})
|
|
||||||
set(new_ld_env "${new_ld_env}:${dir}")
|
|
||||||
endforeach()
|
|
||||||
set(ENV{LD_LIBRARY_PATH} "${new_ld_env}:$ENV{LD_LIBRARY_PATH}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
# Track new prerequisites at each new level of recursion. Start with an
|
|
||||||
# empty list at each level:
|
|
||||||
#
|
|
||||||
set(unseen_prereqs)
|
|
||||||
|
|
||||||
# Run gp_cmd on the target:
|
|
||||||
#
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
|
|
||||||
${gp_cmd_maybe_filter}
|
|
||||||
RESULT_VARIABLE gp_rv
|
|
||||||
OUTPUT_VARIABLE gp_cmd_ov
|
|
||||||
ERROR_VARIABLE gp_ev
|
|
||||||
)
|
|
||||||
if(NOT gp_rv STREQUAL "0")
|
|
||||||
if(gp_tool STREQUAL "dumpbin")
|
|
||||||
# dumpbin error messages seem to go to stdout
|
|
||||||
message(FATAL_ERROR "${gp_cmd} failed: ${gp_rv}\n${gp_ev}\n${gp_cmd_ov}")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "${gp_cmd} failed: ${gp_rv}\n${gp_ev}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(gp_tool STREQUAL "ldd")
|
|
||||||
set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(verbose)
|
|
||||||
message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
|
|
||||||
message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
|
|
||||||
message(STATUS "</RawOutput>")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(target_dir "${target}" PATH)
|
|
||||||
|
|
||||||
# Convert to a list of lines:
|
|
||||||
#
|
|
||||||
string(REPLACE ";" "\\;" candidates "${gp_cmd_ov}")
|
|
||||||
string(REPLACE "\n" "${eol_char};" candidates "${candidates}")
|
|
||||||
|
|
||||||
# check for install id and remove it from list, since otool -L can include a
|
|
||||||
# reference to itself
|
|
||||||
set(gp_install_id)
|
|
||||||
if(gp_tool STREQUAL "otool")
|
|
||||||
execute_process(
|
|
||||||
COMMAND otool -D ${target}
|
|
||||||
RESULT_VARIABLE otool_rv
|
|
||||||
OUTPUT_VARIABLE gp_install_id_ov
|
|
||||||
ERROR_VARIABLE otool_ev
|
|
||||||
)
|
|
||||||
if(NOT otool_rv STREQUAL "0")
|
|
||||||
message(FATAL_ERROR "otool -D failed: ${otool_rv}\n${otool_ev}")
|
|
||||||
endif()
|
|
||||||
# second line is install name
|
|
||||||
string(REGEX REPLACE ".*:\n" "" gp_install_id "${gp_install_id_ov}")
|
|
||||||
if(gp_install_id)
|
|
||||||
# trim
|
|
||||||
string(REGEX MATCH "[^\n ].*[^\n ]" gp_install_id "${gp_install_id}")
|
|
||||||
#message("INSTALL ID is \"${gp_install_id}\"")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Analyze each line for file names that match the regular expression:
|
|
||||||
#
|
|
||||||
foreach(candidate ${candidates})
|
|
||||||
if("${candidate}" MATCHES "${gp_regex}")
|
|
||||||
|
|
||||||
# Extract information from each candidate:
|
|
||||||
if(gp_regex_error AND "${candidate}" MATCHES "${gp_regex_error}")
|
|
||||||
string(REGEX REPLACE "${gp_regex_fallback}" "\\1" raw_item "${candidate}")
|
|
||||||
else()
|
|
||||||
string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(gp_regex_cmp_count GREATER 1)
|
|
||||||
string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(gp_regex_cmp_count GREATER 2)
|
|
||||||
string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Use the raw_item as the list entries returned by this function. Use the
|
|
||||||
# gp_resolve_item function to resolve it to an actual full path file if
|
|
||||||
# necessary.
|
|
||||||
#
|
|
||||||
set(item "${raw_item}")
|
|
||||||
|
|
||||||
# Add each item unless it is excluded:
|
|
||||||
#
|
|
||||||
set(add_item 1)
|
|
||||||
|
|
||||||
if(item STREQUAL gp_install_id)
|
|
||||||
set(add_item 0)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(add_item AND ${exclude_system})
|
|
||||||
set(type "")
|
|
||||||
gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type "${rpaths}")
|
|
||||||
|
|
||||||
if(type STREQUAL "system")
|
|
||||||
set(add_item 0)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(add_item)
|
|
||||||
list(LENGTH ${prerequisites_var} list_length_before_append)
|
|
||||||
gp_append_unique(${prerequisites_var} "${item}")
|
|
||||||
list(LENGTH ${prerequisites_var} list_length_after_append)
|
|
||||||
|
|
||||||
if(${recurse})
|
|
||||||
# If item was really added, this is the first time we have seen it.
|
|
||||||
# Add it to unseen_prereqs so that we can recursively add *its*
|
|
||||||
# prerequisites...
|
|
||||||
#
|
|
||||||
# But first: resolve its name to an absolute full path name such
|
|
||||||
# that the analysis tools can simply accept it as input.
|
|
||||||
#
|
|
||||||
if(NOT list_length_before_append EQUAL list_length_after_append)
|
|
||||||
gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item "${rpaths}")
|
|
||||||
set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if(verbose)
|
|
||||||
message(STATUS "ignoring non-matching line: '${candidate}'")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
list(LENGTH ${prerequisites_var} prerequisites_var_length)
|
|
||||||
if(prerequisites_var_length GREATER 0)
|
|
||||||
list(SORT ${prerequisites_var})
|
|
||||||
endif()
|
|
||||||
if(${recurse})
|
|
||||||
set(more_inputs ${unseen_prereqs})
|
|
||||||
foreach(input ${more_inputs})
|
|
||||||
get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}" "${rpaths}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(list_prerequisites target)
|
|
||||||
if(ARGC GREATER 1 AND NOT "${ARGV1}" STREQUAL "")
|
|
||||||
set(all "${ARGV1}")
|
|
||||||
else()
|
|
||||||
set(all 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ARGC GREATER 2 AND NOT "${ARGV2}" STREQUAL "")
|
|
||||||
set(exclude_system "${ARGV2}")
|
|
||||||
else()
|
|
||||||
set(exclude_system 0)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ARGC GREATER 3 AND NOT "${ARGV3}" STREQUAL "")
|
|
||||||
set(verbose "${ARGV3}")
|
|
||||||
else()
|
|
||||||
set(verbose 0)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(count 0)
|
|
||||||
set(count_str "")
|
|
||||||
set(print_count "${verbose}")
|
|
||||||
set(print_prerequisite_type "${verbose}")
|
|
||||||
set(print_target "${verbose}")
|
|
||||||
set(type_str "")
|
|
||||||
|
|
||||||
get_filename_component(exepath "${target}" PATH)
|
|
||||||
|
|
||||||
set(prereqs "")
|
|
||||||
get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
|
|
||||||
|
|
||||||
if(print_target)
|
|
||||||
message(STATUS "File '${target}' depends on:")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
foreach(d ${prereqs})
|
|
||||||
math(EXPR count "${count} + 1")
|
|
||||||
|
|
||||||
if(print_count)
|
|
||||||
set(count_str "${count}. ")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(print_prerequisite_type)
|
|
||||||
gp_file_type("${target}" "${d}" type)
|
|
||||||
set(type_str " (${type})")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "${count_str}${d}${type_str}")
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(list_prerequisites_by_glob glob_arg glob_exp)
|
|
||||||
message(STATUS "=============================================================================")
|
|
||||||
message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
|
|
||||||
message(STATUS "")
|
|
||||||
file(${glob_arg} file_list ${glob_exp})
|
|
||||||
foreach(f ${file_list})
|
|
||||||
is_file_executable("${f}" is_f_executable)
|
|
||||||
if(is_f_executable)
|
|
||||||
message(STATUS "=============================================================================")
|
|
||||||
list_prerequisites("${f}" ${ARGN})
|
|
||||||
message(STATUS "")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endfunction()
|
|
@ -880,6 +880,9 @@ find_program (RIGCTLCOM_EXE rigctlcom)
|
|||||||
check_type_size (CACHE_ALL HAMLIB_OLD_CACHING)
|
check_type_size (CACHE_ALL HAMLIB_OLD_CACHING)
|
||||||
check_symbol_exists (rig_set_cache_timeout_ms "hamlib/rig.h" HAVE_HAMLIB_CACHING)
|
check_symbol_exists (rig_set_cache_timeout_ms "hamlib/rig.h" HAVE_HAMLIB_CACHING)
|
||||||
|
|
||||||
|
find_package (Portaudio REQUIRED)
|
||||||
|
|
||||||
|
find_package (Usb REQUIRED)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Qt5 setup
|
# Qt5 setup
|
||||||
@ -1764,8 +1767,15 @@ if (NOT is_debug_build)
|
|||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# DLL directory
|
# DLL directories
|
||||||
#set (hamlib_lib_dir ${hamlib_lib_dir}/../bin)
|
get_filename_component (hamlib_lib_dir ${Hamlib_LIBRARY} PATH)
|
||||||
|
list (APPEND fixup_library_dirs ${hamlib_lib_dir}/../bin)
|
||||||
|
|
||||||
|
get_filename_component (usb_lib_dir ${Usb_LIBRARY} PATH)
|
||||||
|
list (APPEND fixup_library_dirs ${usb_lib_dir})
|
||||||
|
|
||||||
|
get_filename_component (portaudio_lib_dir ${Portaudio_LIBRARY} PATH)
|
||||||
|
list (APPEND fixup_library_dirs ${portaudio_lib_dir}/../bin)
|
||||||
|
|
||||||
get_filename_component (fftw_lib_dir ${FFTW3F_LIBRARY} PATH)
|
get_filename_component (fftw_lib_dir ${FFTW3F_LIBRARY} PATH)
|
||||||
list (APPEND fixup_library_dirs ${fftw_lib_dir})
|
list (APPEND fixup_library_dirs ${fftw_lib_dir})
|
||||||
@ -1822,13 +1832,9 @@ if (NOT is_debug_build)
|
|||||||
set (gp_tool "objdump") # we want MinGW tool - not MSVC (See GetPrerequisites.cmake)
|
set (gp_tool "objdump") # we want MinGW tool - not MSVC (See GetPrerequisites.cmake)
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
|
||||||
#list (APPEND fixup_library_dirs ${hamlib_lib_dir})
|
|
||||||
list (APPEND fixup_library_dirs ${Hamlib_LIBRARY_DIRS})
|
|
||||||
|
|
||||||
INSTALL (CODE "
|
INSTALL (CODE "
|
||||||
get_filename_component (the_path \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_PLUGIN_DESTINATION}\" REALPATH)
|
get_filename_component (the_path \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_PLUGIN_DESTINATION}\" REALPATH)
|
||||||
file (GLOB_RECURSE QTPLUGINS \"\${the_path}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
|
file (GLOB_RECURSE QTPLUGINS \"\${the_path}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
|
||||||
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake/Modules ${CMAKE_MODULE_PATH})
|
|
||||||
include (BundleUtilities)
|
include (BundleUtilities)
|
||||||
set (BU_CHMOD_BUNDLE_ITEMS ON)
|
set (BU_CHMOD_BUNDLE_ITEMS ON)
|
||||||
set (gp_tool ${gp_tool})
|
set (gp_tool ${gp_tool})
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
find_package (Portaudio REQUIRED)
|
|
||||||
|
|
||||||
find_package (Usb REQUIRED)
|
|
||||||
|
|
||||||
set (map65_CXXSRCS
|
set (map65_CXXSRCS
|
||||||
about.cpp
|
about.cpp
|
||||||
astro.cpp
|
astro.cpp
|
||||||
@ -56,6 +52,6 @@ target_link_libraries (map65 m65impl ${FFTW3_LIBRARIES} Qt5::Widgets Qt5::Networ
|
|||||||
|
|
||||||
install (
|
install (
|
||||||
TARGETS map65
|
TARGETS map65
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
LIBRARY DESTINATION lib
|
BUNDLE DESTINATION . COMPONENT runtime
|
||||||
)
|
)
|
||||||
|
@ -143,6 +143,6 @@ target_link_libraries (m65 m65impl ${FFTW3_LIBRARIES})
|
|||||||
|
|
||||||
install (
|
install (
|
||||||
TARGETS m65
|
TARGETS m65
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
LIBRARY DESTINATION lib
|
BUNDLE DESTINATION . COMPONENT runtime
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user