Merge topic 'fix-12034-fixup-bundle-with-non-dotapp-exe'

51e16c0 BundleUtilities: Avoid test on Watcom dashboards (#12034)
41f962a Revert "BundleUtilities: Run test on Windows if either MSVC or dumpbin was found."
e17135e BundleUtilities: Add rpath to loadable modules in test.
8064044 BundleUtilities: Print reason for not loading module.so
f3de459 BundleUtilities: Run test on Windows if either MSVC or dumpbin was found.
900bf98 BundleUtilities: Disable running test on Windows unless using MSVC.
fa4dc08 BundleUtilities: Fix issues with custom target DEPENDS in test (#12034)
e40b79e BundleUtilities: Fix test when using xcode (#12034)
b68d3dc BundleUtilities: Fix regex to extract dependents from ldd (#12034)
7ac7b43 BundleUtilities: Work w/ non .app exes on Mac (#12034)
This commit is contained in:
Brad King 2011-06-07 14:06:09 -04:00 committed by CMake Topic Stage
commit 40792a1a15
15 changed files with 333 additions and 29 deletions

View File

@ -53,9 +53,8 @@
#
# 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 return a dir at
# the same level as the executable, named with the executable's base name and
# ending with ".app"
# 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.
#
@ -227,35 +226,35 @@ endfunction(get_bundle_main_executable)
function(get_dotapp_dir exe dotapp_dir_var)
set(s "${exe}")
set(has_dotapp_parent 0)
if(s MATCHES "^.*/.*\\.app/.*$")
set(has_dotapp_parent 1)
endif(s MATCHES "^.*/.*\\.app/.*$")
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)
if(has_dotapp_parent)
# If there is a ".app" parent directory,
# ascend until we hit it:
# (typical of a Mac bundle executable)
#
# 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(sname MATCHES "\\.app$")
else(has_dotapp_parent)
# Otherwise use a directory named the same
# as the exe, but with a ".app" extension:
# (typical of a non-bundle executable on Mac, Windows or Linux)
#
set(done 1)
set(dotapp_dir "${sdir}/${snamewe}.app")
endif(has_dotapp_parent)
endwhile(NOT ${done})
endwhile(NOT ${done})
else(s MATCHES "^.*/.*\\.app/.*$")
# 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(is_executable)
set(dotapp_dir "${s}")
endif(is_executable)
endif(s MATCHES "^.*/.*\\.app/.*$")
set(${dotapp_dir_var} "${dotapp_dir}" PARENT_SCOPE)
endfunction(get_dotapp_dir)

View File

@ -261,9 +261,9 @@ function(gp_resolve_item context item exepath dirs resolved_item_var)
# Is it already resolved?
#
if(EXISTS "${resolved_item}")
if(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
set(resolved 1)
endif(EXISTS "${resolved_item}")
endif(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
if(NOT resolved)
if(item MATCHES "@executable_path")
@ -548,7 +548,7 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
if("${gp_tool}" STREQUAL "ldd")
set(gp_cmd_args "")
set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$")
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)

View File

@ -0,0 +1,84 @@
cmake_minimum_required(VERSION 2.8)
project(BundleUtilities)
###### the various types of dependencies we can have
# a shared library
add_library(shared SHARED shared.cpp shared.h)
# another shared library
add_library(shared2 SHARED shared2.cpp shared2.h)
# a framework library
add_library(framework SHARED framework.cpp framework.h)
# TODO: fix problems with local frameworks without rpaths
#set_target_properties(framework PROPERTIES FRAMEWORK 1)
# make sure rpaths are not helping BundleUtilities or the executables
set_target_properties(shared shared2 framework PROPERTIES
SKIP_BUILD_RPATH 1)
###### test a Bundle application using dependencies
# a loadable module (depends on shared2)
# testbundleutils1 will load this at runtime
add_library(module1 MODULE module.cpp module.h)
set_target_properties(module1 PROPERTIES PREFIX "")
get_target_property(module_loc module1 LOCATION)
target_link_libraries(module1 shared2)
# a bundle application
add_executable(testbundleutils1 MACOSX_BUNDLE testbundleutils1.cpp)
target_link_libraries(testbundleutils1 shared framework ${CMAKE_DL_LIBS})
get_target_property(loc testbundleutils1 LOCATION)
set_target_properties(testbundleutils1 module1 PROPERTIES
INSTALL_RPATH "${CMAKE_CURRENT_BINARY_DIR}/testdir1"
BUILD_WITH_INSTALL_RPATH 1)
# add custom target to install and test the app
add_custom_target(testbundleutils1_test ALL
COMMAND ${CMAKE_COMMAND}
"-DINPUT=${loc}"
"-DMODULE=${module_loc}"
"-DINPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
"-DOUTPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/testdir1"
-P "${CMAKE_CURRENT_SOURCE_DIR}/bundleutils.cmake"
DEPENDS testbundleutils1 module1
)
add_dependencies(testbundleutils1_test testbundleutils1)
###### test a non-Bundle application using dependencies
# a loadable module (depends on shared2)
# testbundleutils2 will load this at runtime
add_library(module2 MODULE module.cpp module.h)
set_target_properties(module2 PROPERTIES PREFIX "")
get_target_property(module_loc module2 LOCATION)
target_link_libraries(module2 shared2)
# a non-bundle application
add_executable(testbundleutils2 testbundleutils2.cpp)
target_link_libraries(testbundleutils2 shared framework ${CMAKE_DL_LIBS})
get_target_property(loc testbundleutils2 LOCATION)
set_target_properties(testbundleutils2 module2 PROPERTIES
INSTALL_RPATH "${CMAKE_CURRENT_BINARY_DIR}/testdir2"
BUILD_WITH_INSTALL_RPATH 1)
# add custom target to install and test the app
add_custom_target(testbundleutils2_test ALL
COMMAND ${CMAKE_COMMAND}
"-DINPUT=${loc}"
"-DMODULE=${module_loc}"
"-DINPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
"-DOUTPUTDIR=${CMAKE_CURRENT_BINARY_DIR}/testdir2"
-P "${CMAKE_CURRENT_SOURCE_DIR}/bundleutils.cmake"
DEPENDS testbundleutils1 module2
)
add_dependencies(testbundleutils2_test testbundleutils2)

View File

@ -0,0 +1,45 @@
# clean passed in arguments
get_filename_component(INPUT ${INPUT} ABSOLUTE)
get_filename_component(INPUTDIR ${INPUTDIR} ABSOLUTE)
message("INPUT = ${INPUT}")
message("MODULE = ${MODULE}")
message("INPUTDIR = ${INPUTDIR}")
message("OUTPUTDIR = ${OUTPUTDIR}")
# compute location to install/test things
file(RELATIVE_PATH relative_exe "${INPUTDIR}" "${INPUT}")
set(OUTPUT "${OUTPUTDIR}/${relative_exe}")
message("OUTPUT = ${OUTPUT}")
get_filename_component(EXE_DIR "${OUTPUT}" PATH)
get_filename_component(MODULE_NAME "${MODULE}" NAME)
set(OUTPUT_MODULE "${EXE_DIR}/${MODULE_NAME}")
message("OUTPUTMODULE = ${OUTPUT_MODULE}")
# clean output dir
file(REMOVE_RECURSE "${OUTPUTDIR}")
# copy the app and plugin to installation/testing directory
configure_file("${INPUT}" "${OUTPUT}" COPYONLY)
configure_file("${MODULE}" "${OUTPUT_MODULE}" COPYONLY)
# have BundleUtilities grab all dependencies and
# check that the app runs
# for this test we'll override location to put all dependencies
# (in the same dir as the app)
# this shouldn't be necessary except for the non-bundle case on Mac
function(gp_item_default_embedded_path_override item path)
set(path "@executable_path" PARENT_SCOPE)
endfunction(gp_item_default_embedded_path_override)
include(BundleUtilities)
fixup_bundle("${OUTPUT}" "${OUTPUT_MODULE}" "${INPUTDIR}")
# make sure we can run the app
message("Executing ${OUTPUT} in ${EXE_DIR}")
execute_process(COMMAND "${OUTPUT}" RESULT_VARIABLE result OUTPUT_VARIABLE out ERROR_VARIABLE out WORKING_DIRECTORY "${EXE_DIR}")
if(NOT result STREQUAL "0")
message(FATAL_ERROR " failed to execute test program\n${out}")
endif(NOT result STREQUAL "0")

View File

@ -0,0 +1,8 @@
#include "framework.h"
#include "stdio.h"
void framework()
{
printf("framework\n");
}

View File

@ -0,0 +1,17 @@
#ifndef framework_h
#define framework_h
#ifdef WIN32
# ifdef framework_EXPORTS
# define FRAMEWORK_EXPORT __declspec(dllexport)
# else
# define FRAMEWORK_EXPORT __declspec(dllimport)
# endif
#else
# define FRAMEWORK_EXPORT
#endif
void FRAMEWORK_EXPORT framework();
#endif

View File

@ -0,0 +1,10 @@
#include "module.h"
#include "stdio.h"
#include "shared2.h"
void module()
{
printf("module\n");
shared2();
}

View File

@ -0,0 +1,7 @@
#ifndef module_h
#define module_h
void module();
#endif

View File

@ -0,0 +1,8 @@
#include "shared.h"
#include "stdio.h"
void shared()
{
printf("shared\n");
}

View File

@ -0,0 +1,17 @@
#ifndef shared_h
#define shared_h
#ifdef WIN32
# ifdef shared_EXPORTS
# define SHARED_EXPORT __declspec(dllexport)
# else
# define SHARED_EXPORT __declspec(dllimport)
# endif
#else
# define SHARED_EXPORT
#endif
void SHARED_EXPORT shared();
#endif

View File

@ -0,0 +1,8 @@
#include "shared2.h"
#include "stdio.h"
void shared2()
{
printf("shared2\n");
}

View File

@ -0,0 +1,17 @@
#ifndef shared2_h
#define shared2_h
#ifdef WIN32
# ifdef shared2_EXPORTS
# define SHARED2_EXPORT __declspec(dllexport)
# else
# define SHARED2_EXPORT __declspec(dllimport)
# endif
#else
# define SHARED2_EXPORT
#endif
void SHARED2_EXPORT shared2();
#endif

View File

@ -0,0 +1,33 @@
#include "framework.h"
#include "shared.h"
#include "stdio.h"
#if defined(WIN32)
#include <windows.h>
#else
#include "dlfcn.h"
#endif
int main(int, char**)
{
framework();
shared();
#if defined(WIN32)
HANDLE lib = LoadLibraryA("module1.dll");
if(!lib)
{
printf("Failed to open module1\n");
}
#else
void* lib = dlopen("module1.so", RTLD_LAZY);
if(!lib)
{
printf("Failed to open module1\n%s\n", dlerror());
}
#endif
return lib == 0 ? 1 : 0;
}

View File

@ -0,0 +1,33 @@
#include "framework.h"
#include "shared.h"
#include "stdio.h"
#if defined(WIN32)
#include <windows.h>
#else
#include "dlfcn.h"
#endif
int main(int, char**)
{
framework();
shared();
#if defined(WIN32)
HANDLE lib = LoadLibraryA("module2.dll");
if(!lib)
{
printf("Failed to open module2\n");
}
#else
void* lib = dlopen("module2.so", RTLD_LAZY);
if(!lib)
{
printf("Failed to open module2\n%s\n", dlerror());
}
#endif
return lib == 0 ? 1 : 0;
}

View File

@ -193,6 +193,24 @@ IF(BUILD_TESTING)
LIST(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
# run test for BundleUtilities on supported platforms/compilers
if(MSVC OR
CMAKE_SYSTEM_NAME MATCHES "Linux" OR
CMAKE_SYSTEM_NAME MATCHES "Darwin")
if(NOT "${CMAKE_TEST_GENERATOR}" STREQUAL "Watcom WMake")
ADD_TEST(BundleUtilities ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/BundleUtilities"
"${CMake_BINARY_DIR}/Tests/BundleUtilities"
--build-generator ${CMAKE_TEST_GENERATOR}
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
--build-project BundleUtilities
)
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleUtilities")
endif()
endif()
SET(CMAKE_BUILD_TEST_SOURCE_DIR "${CMake_SOURCE_DIR}/Tests/COnly")
SET(CMAKE_BUILD_TEST_BINARY_DIR "${CMake_BINARY_DIR}/Tests/CMakeBuildCOnly")
CONFIGURE_FILE("${CMake_SOURCE_DIR}/Tests/CMakeBuildTest.cmake.in"