From a3334295efde7c7f06405d090b67d3f501f6d7d7 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 18 Apr 2021 01:06:04 +0100 Subject: [PATCH] Revert to standard CMake BundleUtilities.cmake script Fix some installation dependency finding issues. --- CMake/Modules/BundleUtilities.cmake | 975 -------------------------- CMake/Modules/GetPrerequisites.cmake | 998 --------------------------- CMakeLists.txt | 18 +- map65/CMakeLists.txt | 8 +- map65/libm65/CMakeLists.txt | 4 +- 5 files changed, 16 insertions(+), 1987 deletions(-) delete mode 100644 CMake/Modules/BundleUtilities.cmake delete mode 100644 CMake/Modules/GetPrerequisites.cmake diff --git a/CMake/Modules/BundleUtilities.cmake b/CMake/Modules/BundleUtilities.cmake deleted file mode 100644 index b7975d3ea..000000000 --- a/CMake/Modules/BundleUtilities.cmake +++ /dev/null @@ -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( ) -# -# 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( ) -# -# Makes a copy of the bundle at location and then fixes up -# the new copied bundle in-place at ... -# -# :: -# -# VERIFY_APP() -# -# Verifies that an application appears valid based on running -# analysis tools on it. Calls "message(FATAL_ERROR" if the application -# is not verified. -# -# :: -# -# GET_BUNDLE_MAIN_EXECUTABLE( ) -# -# 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( ) -# -# 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( ) -# -# 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 and the path to its main executable in -# -# -# :: -# -# GET_BUNDLE_ALL_EXECUTABLES( ) -# -# Scans the given bundle recursively for all executable files and -# accumulates them into a variable. -# -# :: -# -# GET_ITEM_KEY( ) -# -# 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() -# -# 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( -# []) -# -# 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( ) -# -# Loop over all the executable and library files within the bundle (and -# given as extra ) 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( ) -# -# 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( ) -# -# 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( ) -# -# 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( ) -# -# 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( ) -# -# 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 "CFBundleExecutable" - the line after that - # is the name of the main executable. - # - foreach(line ${info_plist}) - if(line_is_main_executable) - string(REGEX REPLACE "^.*(.*).*$" "\\1" bundle_executable "${line}") - break() - endif() - - if(line MATCHES "CFBundleExecutable") - 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() diff --git a/CMake/Modules/GetPrerequisites.cmake b/CMake/Modules/GetPrerequisites.cmake deleted file mode 100644 index e4018b670..000000000 --- a/CMake/Modules/GetPrerequisites.cmake +++ /dev/null @@ -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( -# []) -# -# Get the list of shared library files required by . The list -# in the variable named should be empty on first -# entry to this function. On exit, will contain the -# list of required shared library files. -# -# is the full path to an executable file. -# is the name of a CMake variable to contain the results. -# must be 0 or 1 indicating whether to include or -# exclude "system" prerequisites. If is set to 1 all -# prerequisites will be found recursively, if set to 0 only direct -# prerequisites are listed. is the path to the top level -# executable used for @executable_path replacment on the Mac. 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( [ [ []]]) -# -# Print a message listing the prerequisites of . -# -# is the name of a shared library or executable target or the -# full path to a shared library or executable file. If is set -# to 1 all prerequisites will be found recursively, if set to 0 only -# direct prerequisites are listed. must be 0 or 1 -# indicating whether to include or exclude "system" prerequisites. With -# 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( ) -# -# Print the prerequisites of shared library and executable files -# matching a globbing pattern. is GLOB or GLOB_RECURSE and -# 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( ) -# -# Append to the list variable only if the value is -# not already in the list. -# -# :: -# -# IS_FILE_EXECUTABLE( ) -# -# Return 1 in if is a binary executable, 0 -# otherwise. -# -# :: -# -# GP_ITEM_DEFAULT_EMBEDDED_PATH( ) -# -# 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( -# []) -# -# 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( -# []) -# -# Return the type of with respect to . String -# describing type of prerequisite is returned in variable named -# . -# -# Use and if necessary to resolve non-absolute -# 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( ) -# -# Return the type of with respect to . String -# describing type of prerequisite is returned in variable named -# . -# -# 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" - ) - - # - # - # 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() - # - # - - 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 "") - message(STATUS "gp_cmd_ov='${gp_cmd_ov}'") - message(STATUS "") - 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() diff --git a/CMakeLists.txt b/CMakeLists.txt index 18cf5a28a..790ce6b48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -880,6 +880,9 @@ find_program (RIGCTLCOM_EXE rigctlcom) check_type_size (CACHE_ALL HAMLIB_OLD_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 @@ -1764,8 +1767,15 @@ if (NOT is_debug_build) endif (APPLE) if (WIN32) - # DLL directory - #set (hamlib_lib_dir ${hamlib_lib_dir}/../bin) + # DLL directories + 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) 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) endif (WIN32) - #list (APPEND fixup_library_dirs ${hamlib_lib_dir}) - list (APPEND fixup_library_dirs ${Hamlib_LIBRARY_DIRS}) - INSTALL (CODE " get_filename_component (the_path \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${WSJT_PLUGIN_DESTINATION}\" REALPATH) file (GLOB_RECURSE QTPLUGINS \"\${the_path}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\") - set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake/Modules ${CMAKE_MODULE_PATH}) include (BundleUtilities) set (BU_CHMOD_BUNDLE_ITEMS ON) set (gp_tool ${gp_tool}) diff --git a/map65/CMakeLists.txt b/map65/CMakeLists.txt index 8114532b8..67a1831cd 100644 --- a/map65/CMakeLists.txt +++ b/map65/CMakeLists.txt @@ -1,7 +1,3 @@ -find_package (Portaudio REQUIRED) - -find_package (Usb REQUIRED) - set (map65_CXXSRCS about.cpp astro.cpp @@ -56,6 +52,6 @@ target_link_libraries (map65 m65impl ${FFTW3_LIBRARIES} Qt5::Widgets Qt5::Networ install ( TARGETS map65 - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime + BUNDLE DESTINATION . COMPONENT runtime ) diff --git a/map65/libm65/CMakeLists.txt b/map65/libm65/CMakeLists.txt index f28295f61..40519be77 100644 --- a/map65/libm65/CMakeLists.txt +++ b/map65/libm65/CMakeLists.txt @@ -143,6 +143,6 @@ target_link_libraries (m65 m65impl ${FFTW3_LIBRARIES}) install ( TARGETS m65 - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime + BUNDLE DESTINATION . COMPONENT runtime )