Skip to content
Snippets Groups Projects
Commit 15d37713 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

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.
parent c0f709b6
Branches
No related tags found
2 merge requests!3Update to main branch,!2Rebase onto current main branch
...@@ -151,6 +151,11 @@ elseif(DARWIN) ...@@ -151,6 +151,11 @@ elseif(DARWIN)
set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug/Resources") 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_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Resources")
set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release/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(vivox_lib_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(slvoice_files SLVoice) set(slvoice_files SLVoice)
......
...@@ -5,8 +5,8 @@ set(PYTHONINTERP_FOUND) ...@@ -5,8 +5,8 @@ set(PYTHONINTERP_FOUND)
if (WINDOWS) if (WINDOWS)
# On Windows, explicitly avoid Cygwin Python. # On Windows, explicitly avoid Cygwin Python.
find_program(PYTHON_EXECUTABLE find_program(python
NAMES python.exe NAMES python3.exe python.exe
NO_DEFAULT_PATH # added so that cmake does not find cygwin python NO_DEFAULT_PATH # added so that cmake does not find cygwin python
PATHS PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\3.7\\InstallPath]
...@@ -18,19 +18,20 @@ if (WINDOWS) ...@@ -18,19 +18,20 @@ if (WINDOWS)
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.8\\InstallPath] [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.9\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\3.10\\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) include(FindPythonInterp)
else() else()
find_program(PYTHON_EXECUTABLE python3) find_program(python python3)
if (PYTHON_EXECUTABLE) if (python)
set(PYTHONINTERP_FOUND ON) set(PYTHONINTERP_FOUND ON)
endif (PYTHON_EXECUTABLE) endif (python)
endif (WINDOWS) endif (WINDOWS)
if (NOT PYTHON_EXECUTABLE) if (NOT python)
message(FATAL_ERROR "No Python interpreter found") 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) mark_as_advanced(PYTHON_EXECUTABLE)
...@@ -73,7 +73,7 @@ def main(command, arguments=[], libpath=[], vars={}): ...@@ -73,7 +73,7 @@ def main(command, arguments=[], libpath=[], vars={}):
if sys.platform == "win32": if sys.platform == "win32":
lpvars = ["PATH"] lpvars = ["PATH"]
elif sys.platform == "darwin": elif sys.platform == "darwin":
lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"] lpvars = ["LD_LIBRARY_PATH"] # , "DYLD_LIBRARY_PATH"]
elif sys.platform.startswith("linux"): elif sys.platform.startswith("linux"):
lpvars = ["LD_LIBRARY_PATH"] lpvars = ["LD_LIBRARY_PATH"]
else: else:
......
...@@ -12,11 +12,48 @@ ...@@ -12,11 +12,48 @@
#if ! defined(LL_APPLY_H) #if ! defined(LL_APPLY_H)
#define LL_APPLY_H #define LL_APPLY_H
#include <boost/type_traits/function_traits.hpp>
#include <tuple> #include <tuple>
namespace LL 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 #if __cplusplus >= 201703L
// C++17 implementation // C++17 implementation
...@@ -34,16 +71,43 @@ auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>) ...@@ -34,16 +71,43 @@ auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>)
} }
template <typename CALLABLE, typename... ARGS> 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 // 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 // pack of indexes for each entry in args. apply_impl() can then pass
// those to std::get() to unpack args into individual arguments. // those to std::get() to unpack args into individual arguments.
return apply_impl(std::forward<CALLABLE>(func), return apply_impl(std::forward<CALLABLE>(func),
std::forward<std::tuple<ARGS...>>(args), args,
std::index_sequence_for<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 #endif // C++14
} // namespace LL } // namespace LL
......
...@@ -15,10 +15,11 @@ ...@@ -15,10 +15,11 @@
#include "llleap.h" #include "llleap.h"
// STL headers // STL headers
// std headers // std headers
#include <functional>
// external library headers // external library headers
//#include <boost/algorithm/string/join.hpp>
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp>
#include <boost/phoenix/core/argument.hpp> #include <boost/phoenix/core/argument.hpp>
#include <boost/foreach.hpp>
// other Linden headers // other Linden headers
#include "../test/lltut.h" #include "../test/lltut.h"
#include "../test/namedtempfile.h" #include "../test/namedtempfile.h"
...@@ -29,7 +30,6 @@ ...@@ -29,7 +30,6 @@
#include "llstring.h" #include "llstring.h"
#include "stringize.h" #include "stringize.h"
#include "StringVec.h" #include "StringVec.h"
#include <functional>
using boost::assign::list_of; using boost::assign::list_of;
...@@ -110,11 +110,6 @@ namespace tut ...@@ -110,11 +110,6 @@ namespace tut
"import os\n" "import os\n"
"import sys\n" "import sys\n"
"\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" "from llbase import llsd\n"
"\n" "\n"
"class ProtocolError(Exception):\n" "class ProtocolError(Exception):\n"
...@@ -241,9 +236,10 @@ namespace tut ...@@ -241,9 +236,10 @@ namespace tut
"import sys\n" "import sys\n"
"sys.stderr.write('''Hello from Python!\n" "sys.stderr.write('''Hello from Python!\n"
"note partial line''')\n"); "note partial line''')\n");
StringVec vcommand{ PYTHON, script.getName() };
// std::string command{ boost::algorithm::join(vcommand, " ") };
CaptureLog log(LLError::LEVEL_INFO); CaptureLog log(LLError::LEVEL_INFO);
waitfor(LLLeap::create(get_test_name(), waitfor(LLLeap::create(get_test_name(), vcommand));
sv(list_of(PYTHON)(script.getName()))));
log.messageWith("Hello from Python!"); log.messageWith("Hello from Python!");
log.messageWith("note partial line"); log.messageWith("note partial line");
} }
......
...@@ -116,14 +116,21 @@ if (WINDOWS) ...@@ -116,14 +116,21 @@ if (WINDOWS)
LINK_FLAGS "/NODEFAULTLIB:LIBCMT" LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" 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) endif (WINDOWS)
set(TEST_EXE $<TARGET_FILE:lltest>) set(TEST_EXE $<TARGET_FILE:lltest>)
SET_TEST_PATH(DYLD_LIBRARY_PATH) SET_TEST_PATH(LD_LIBRARY_PATH)
LL_TEST_COMMAND(command LL_TEST_COMMAND(command
"${DYLD_LIBRARY_PATH}" "${LD_LIBRARY_PATH}"
"${TEST_EXE}" "${TEST_EXE}"
"--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt" "--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt"
"--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt") "--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment