DRTVWR-558: Fix builds on macOS 12.5 Monterey.

Always search for python3[.exe] instead of plain 'python'. macOS Monterey no
longer bundles Python 2 at all.

Explicitly make PYTHON_EXECUTABLE a cached value so if the user edits it in
CMakeCache.txt, it won't be overwritten by indra/cmake/Python.cmake.

Do NOT set DYLD_LIBRARY_PATH for test executables! That has Bad Effects, as
discussed in https://stackoverflow.com/q/73418423/5533635. Instead, create
symlinks from build-mumble/sharedlibs/Resources -> Release/Resources and from
build-mumble/test/Resources -> ../sharedlibs/Release/Resources. For test
executables in sharedlibs/RelWithDebInfo and test/RelWithDebInfo, this
supports our dylibs' baked-in load path @executable_path/../Resources. That
load path assumes running in a standard app bundle (which the viewer in fact
does), but we've been avoiding creating an app bundle for every test program.
These symlinks allow us to continue doing that while avoiding
DYLD_LIBRARY_PATH.

Add indra/llcommon/apply.h. The LL::apply() function and its wrapper macro
VAPPLY were very useful in diagnosing the problem.

Tweak llleap_test.cpp. This source was modified extensively for diagnostic
purposes; these are the small improvements that remain.
master
Nat Goodspeed 2022-08-22 21:00:42 -04:00
parent c0f709b637
commit 15d37713b9
6 changed files with 95 additions and 22 deletions

View File

@ -151,6 +151,11 @@ elseif(DARWIN)
set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug/Resources")
set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Resources")
set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release/Resources")
# Support our "@executable_path/../Resources" load path for executables
# that end up in any of the above SHARED_LIB_STAGING_DIR_MUMBLE
# directories.
file(CREATE_LINK "Release/Resources" "${SHARED_LIB_STAGING_DIR}/Resources"
SYMBOLIC)
set(vivox_lib_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(slvoice_files SLVoice)

View File

@ -5,8 +5,8 @@ set(PYTHONINTERP_FOUND)
if (WINDOWS)
# On Windows, explicitly avoid Cygwin Python.
find_program(PYTHON_EXECUTABLE
NAMES python.exe
find_program(python
NAMES python3.exe python.exe
NO_DEFAULT_PATH # added so that cmake does not find cygwin python
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath]
@ -18,19 +18,20 @@ if (WINDOWS)
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.8\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.9\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.10\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.11\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.11\\InstallPath]
)
include(FindPythonInterp)
else()
find_program(PYTHON_EXECUTABLE python3)
find_program(python python3)
if (PYTHON_EXECUTABLE)
if (python)
set(PYTHONINTERP_FOUND ON)
endif (PYTHON_EXECUTABLE)
endif (python)
endif (WINDOWS)
if (NOT PYTHON_EXECUTABLE)
if (NOT python)
message(FATAL_ERROR "No Python interpreter found")
endif (NOT PYTHON_EXECUTABLE)
endif (NOT python)
set(PYTHON_EXECUTABLE "${python}" CACHE FILEPATH "Python interpreter for builds")
mark_as_advanced(PYTHON_EXECUTABLE)

View File

@ -73,7 +73,7 @@ def main(command, arguments=[], libpath=[], vars={}):
if sys.platform == "win32":
lpvars = ["PATH"]
elif sys.platform == "darwin":
lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"]
lpvars = ["LD_LIBRARY_PATH"] # , "DYLD_LIBRARY_PATH"]
elif sys.platform.startswith("linux"):
lpvars = ["LD_LIBRARY_PATH"]
else:

View File

@ -12,11 +12,48 @@
#if ! defined(LL_APPLY_H)
#define LL_APPLY_H
#include <boost/type_traits/function_traits.hpp>
#include <tuple>
namespace LL
{
/**
* USAGE NOTE:
* https://stackoverflow.com/a/40523474/5533635
*
* If you're trying to pass apply() a variadic function, the compiler
* complains that it can't deduce the callable type, presumably because it
* doesn't know which arity to reify to pass.
*
* But it works to wrap the variadic function in a generic lambda, e.g.:
*
* @CODE
* LL::apply(
* [](auto&&... args)
* {
* return variadic(std::forward<decltype(args)>(args)...);
* },
* args);
* @ENDCODE
*
* Presumably this is because there's only one instance of the generic lambda
* @em type, with a variadic <tt>operator()()</tt>.
*
* It's pointless to provide a wrapper @em function that implicitly supplies
* the generic lambda. You couldn't pass your variadic function to our wrapper
* function, for the same original reason!
*
* Instead we provide a wrapper @em macro. Sorry, Dr. Stroustrup.
*/
#define VAPPLY(FUNC, ARGS) \
LL::apply( \
[](auto&&... args) \
{ \
return (FUNC)(std::forward<decltype(args)>(args)...); \
}, \
(ARGS))
#if __cplusplus >= 201703L
// C++17 implementation
@ -34,16 +71,43 @@ auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>)
}
template <typename CALLABLE, typename... ARGS>
auto apply(CALLABLE&& func, std::tuple<ARGS...>&& args)
auto apply(CALLABLE&& func, const std::tuple<ARGS...>& args)
{
// std::index_sequence_for is the magic sauce here, generating an argument
// pack of indexes for each entry in args. apply_impl() can then pass
// those to std::get() to unpack args into individual arguments.
return apply_impl(std::forward<CALLABLE>(func),
std::forward<std::tuple<ARGS...>>(args),
args,
std::index_sequence_for<ARGS...>{});
}
// per https://stackoverflow.com/a/57510428/5533635
template <typename CALLABLE, typename T, size_t SIZE>
auto apply(CALLABLE&& func, const std::array<T, SIZE>& args)
{
return apply(std::forward<CALLABLE>(func), std::tuple_cat(args));
}
// per https://stackoverflow.com/a/28411055/5533635
template <typename CALLABLE, typename T, std::size_t... I>
auto apply_impl(CALLABLE&& func, const std::vector<T>& args, std::index_sequence<I...>)
{
return apply_impl(std::forward<CALLABLE>(func),
std::make_tuple(std::forward<T>(args[I])...),
I...);
}
// this goes beyond C++17 std::apply()
template <typename CALLABLE, typename T>
auto apply(CALLABLE&& func, const std::vector<T>& args)
{
constexpr auto arity = boost::function_traits<CALLABLE>::arity;
assert(args.size() == arity);
return apply_impl(std::forward<CALLABLE>(func),
args,
std::make_index_sequence<arity>());
}
#endif // C++14
} // namespace LL

View File

@ -15,10 +15,11 @@
#include "llleap.h"
// STL headers
// std headers
#include <functional>
// external library headers
//#include <boost/algorithm/string/join.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/phoenix/core/argument.hpp>
#include <boost/foreach.hpp>
// other Linden headers
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
@ -29,7 +30,6 @@
#include "llstring.h"
#include "stringize.h"
#include "StringVec.h"
#include <functional>
using boost::assign::list_of;
@ -110,11 +110,6 @@ namespace tut
"import os\n"
"import sys\n"
"\n"
// Don't forget that this Python script is written to some
// temp directory somewhere! Its __file__ is useless in
// finding indra/lib/python. Use our __FILE__, with
// raw-string syntax to deal with Windows pathnames.
"mydir = os.path.dirname(r'" << __FILE__ << "')\n"
"from llbase import llsd\n"
"\n"
"class ProtocolError(Exception):\n"
@ -241,9 +236,10 @@ namespace tut
"import sys\n"
"sys.stderr.write('''Hello from Python!\n"
"note partial line''')\n");
StringVec vcommand{ PYTHON, script.getName() };
// std::string command{ boost::algorithm::join(vcommand, " ") };
CaptureLog log(LLError::LEVEL_INFO);
waitfor(LLLeap::create(get_test_name(),
sv(list_of(PYTHON)(script.getName()))));
waitfor(LLLeap::create(get_test_name(), vcommand));
log.messageWith("Hello from Python!");
log.messageWith("note partial line");
}

View File

@ -116,14 +116,21 @@ if (WINDOWS)
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
)
elseif (DARWIN)
# Support our "@executable_path/../Resources" load path for our test
# executable. This SHOULD properly be "$<TARGET_FILE_DIR:lltest>/Resources",
# but the CMake $<TARGET_FILE_DIR> generator expression isn't evaluated by
# CREATE_LINK, so fudge it.
file(CREATE_LINK "../sharedlibs/Release/Resources" "${CMAKE_BINARY_DIR}/test/Resources"
SYMBOLIC)
endif (WINDOWS)
set(TEST_EXE $<TARGET_FILE:lltest>)
SET_TEST_PATH(DYLD_LIBRARY_PATH)
SET_TEST_PATH(LD_LIBRARY_PATH)
LL_TEST_COMMAND(command
"${DYLD_LIBRARY_PATH}"
"${LD_LIBRARY_PATH}"
"${TEST_EXE}"
"--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt"
"--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")