Commit 635598be authored by Utkarsh Ayachit's avatar Utkarsh Ayachit
Browse files

add launcher project

Adding a new project that simply builds the ParaView launchers.
Currently, we're only doing these on linux.
parent 3c79daff
......@@ -117,6 +117,7 @@ function (superbuild_find_projects var)
fontconfig
glproto
gperf
launchers
libfabric
llvm
mesa
......@@ -201,6 +202,14 @@ function (superbuild_sanity_check)
message(SEND_ERROR "Cannot enable OSMesa and Mesa at the same time.")
endif ()
# Sanity check: report cases where it doesn't make any sense to enable launchers.
if (launchers_enabled AND NOT (mesa_enabled OR mpi_enabled))
message(SEND_ERROR "Launchers cannot be enabled since neither MPI or MESA is enabled.")
endif ()
if (launchers_enabled AND mpi_enabled AND USE_SYSTEM_mpi AND NOT mesa_enabled)
message(SEND_ERROR "Launchers cannot be enabled since MESA is not enabled and USE_SYSTEM_mpi is ON.")
endif ()
endfunction ()
function (superbuild_add_packaging)
......
cmake_minimum_required(VERSION 3.12)
project(launchers)
find_package(ParaView REQUIRED)
option(LAUNCHER_ENABLE_MESA "Enable Mesa launch option" OFF)
option(LAUNCHER_ENABLE_MPI "Enable MPI launch option" OFF)
set(LAUNCHER_MESA_LIBDIR "<LIBDIR>/mesa"
CACHE STRING "The directory containing the Mesa libraries (<LIBDIR> is replaced with the runtime library install location)")
set(LAUNCHER_MPI_LIBDIR "<LIBDIR>/mpi"
CACHE STRING "The directory containing the MPI libraries (<LIBDIR> is replaced with the runtime library install location)")
include(GNUInstallDirs)
if (WIN32)
set(_launcher_replacement "${CMAKE_INSTALL_BINDIR}")
else ()
set(_launcher_replacement "${CMAKE_INSTALL_LIBDIR}")
endif ()
string(REPLACE "<LIBDIR>" "${_launcher_replacement}" _launcher_mesa_libdir "${LAUNCHER_MESA_LIBDIR}")
file(RELATIVE_PATH _launcher_mesa_relpath
"/prefix/${CMAKE_INSTALL_BINDIR}"
"/prefix/${_launcher_mesa_libdir}")
string(REPLACE "<LIBDIR>" "${_launcher_replacement}" _launcher_mpi_libdir "${LAUNCHER_MPI_LIBDIR}")
file(RELATIVE_PATH _launcher_mpi_relpath
"/prefix/${CMAKE_INSTALL_BINDIR}"
"/prefix/${_launcher_mpi_libdir}")
# Set up rpaths
set(CMAKE_BUILD_RPATH_USE_ORIGIN 1)
if (UNIX AND NOT APPLE)
file(RELATIVE_PATH _launcher_client_relpath
"/prefix/${CMAKE_INSTALL_BINDIR}"
"/prefix/${CMAKE_INSTALL_LIBDIR}")
set(_launcher_client_origin_rpath
"$ORIGIN/${_launcher_client_relpath}")
list(APPEND CMAKE_INSTALL_RPATH
"${_launcher_client_origin_rpath}")
endif()
set(tools
paraview
pvbatch
pvdataserver
pvpython
pvrenderserver
pvserver)
foreach(tool IN LISTS tools)
if (NOT TARGET ParaView::${tool})
continue()
endif()
set(name "${tool}-launcher")
add_executable(${name}
launcher.cxx)
add_executable(Launcher::${tool} ALIAS ${name})
target_link_libraries(${name}
PRIVATE
VTK::vtksys)
target_compile_definitions(${name}
PRIVATE
"MESA_RELATIVE_LIBDIR=\"${_launcher_mesa_relpath}\""
"MPI_RELATIVE_LIBDIR=\"${_launcher_mpi_relpath}\""
"TOOL=\"${tool}\""
"TOOL_SUFFIX=\"-real\"")
if (LAUNCHER_ENABLE_MPI)
target_compile_definitions(${name}
PRIVATE
"ENABLE_MPI")
endif()
if (LAUNCHER_ENABLE_MESA)
target_compile_definitions(${name}
PRIVATE
"ENABLE_MESA")
endif()
install(
TARGETS "${name}"
DESTINATION "${CMAKE_INSTALL_BINDIR}"
COMPONENT runtime)
endforeach()
/*=========================================================================
Program: ParaView
Module: launcher.cxx
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <vtksys/Process.h>
#include <vtksys/SystemTools.hxx>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
static char const* const mesa_relative_libdir = MESA_RELATIVE_LIBDIR;
static char const* const mpi_relative_libdir = MPI_RELATIVE_LIBDIR;
static char const* const tool = TOOL;
static char const* const tool_suffix = TOOL_SUFFIX;
#if defined(_WIN32)
static char const* const library_env = "PATH";
#elif defined(__APPLE__)
static char const* const library_env = "DYLD_LIBRARY_PATH";
#else
static char const* const library_env = "LD_LIBRARY_PATH";
#endif
#if defined(_WIN32)
static char const path_separator = ';';
#else
static char const path_separator = ':';
#endif
static char const* const backends[] = { "llvmpipe", "swr", nullptr };
void available(char const* name, char const* const* arr)
{
std::cerr << "Available " << name << ":" << std::endl;
char const* const* current = arr;
while (*current)
{
std::cerr << " " << *current << std::endl;
++current;
}
}
void usage(char const* prog)
{
std::cerr << "Launcher options:"
<< std::endl
<< " --print Print modified environment." << std::endl;
#if ENABLE_MPI
std::cerr << " --system-mpi Use MPI implementation available on the system." << std::endl;
#endif
#if ENABLE_MESA
std::cerr << " --mesa Use Mesa GL for rendering." << std::endl
<< " --backend <backend> Specify mesa backend." << std::endl << std::endl;
available("backends", backends);
#endif
}
void error(char const* msg, char const* arg)
{
if (arg)
{
std::cerr << "error: " << msg << arg << std::endl;
}
else
{
std::cerr << "error: " << msg << std::endl;
}
}
void set_launcher_env(bool print, char const* var, const char* value)
{
std::string const setting = std::string(var) + "=" + value;
vtksys::SystemTools::PutEnv(setting);
if (print)
{
std::cerr << setting << std::endl;
}
}
std::string current_exe_dir(char const* prog)
{
std::string exe_dir;
#if defined(_WIN32) && !defined(__CYGWIN__)
(void)prog; // ignore this on windows
wchar_t modulepath[_MAX_PATH];
::GetModuleFileNameW(NULL, modulepath, sizeof(modulepath));
std::string path = vtksys::Encoding::ToNarrow(modulepath);
std::string realPath = vtksys::SystemTools::GetRealPathResolvingWindowsSubst(path, NULL);
if (realPath.empty())
{
realPath = path;
}
exe_dir = vtksys::SystemTools::GetFilenamePath(realPath);
#elif defined(__APPLE__)
(void)prog; // ignore this on OS X
#define CM_EXE_PATH_LOCAL_SIZE 16384
char exe_path_local[CM_EXE_PATH_LOCAL_SIZE];
#if defined(MAC_OS_X_VERSION_10_3) && !defined(MAC_OS_X_VERSION_10_4)
unsigned long exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
#else
uint32_t exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
#endif
#undef CM_EXE_PATH_LOCAL_SIZE
char* exe_path = exe_path_local;
if (_NSGetExecutablePath(exe_path, &exe_path_size) < 0)
{
exe_path = static_cast<char*>(malloc(exe_path_size));
_NSGetExecutablePath(exe_path, &exe_path_size);
}
exe_dir = vtksys::SystemTools::GetFilenamePath(vtksys::SystemTools::GetRealPath(exe_path));
if (exe_path != exe_path_local)
{
free(exe_path);
}
#else
std::string errorMsg;
std::string exe;
if (vtksys::SystemTools::FindProgramPath(prog, exe, errorMsg))
{
// remove symlinks
exe = vtksys::SystemTools::GetRealPath(exe);
exe_dir = vtksys::SystemTools::GetFilenamePath(exe);
}
else
{
// ???
}
#endif
return exe_dir;
}
int main(int argc, char* argv[])
{
char const* backend = nullptr;
bool print = false;
bool help = false;
bool forward_mpi = true;
bool forward_mesa = false;
std::vector<char const*> args;
for (int i = 1; i < argc; ++i)
{
char const* arg = argv[i];
if (!strcmp(arg, "--help") || !strcmp(arg, "/?"))
{
help = true;
args.push_back(arg);
}
else if (!strcmp(arg, "--print") && !print)
{
print = true;
}
else if (!strcmp(arg, "--system-mpi") && forward_mpi)
{
forward_mpi = false;
}
else if (!strcmp(arg, "--mesa") && !forward_mesa)
{
forward_mesa = true;
}
else if (!strcmp(arg, "--backend") && backend == nullptr)
{
++i;
if (argc <= i)
{
error("--backend requires an argument", nullptr);
return EXIT_FAILURE;
}
backend = argv[i];
// Check that the backend argument is valid.
bool have_backend = false;
char const* const* current_backend = backends;
while (*current_backend)
{
if (!strcmp(*current_backend, backend))
{
have_backend = true;
break;
}
++current_backend;
}
if (!have_backend)
{
error("unknown backend: ", backend);
available("backends", backends);
return EXIT_FAILURE;
}
}
else
{
args.push_back(arg);
}
}
args.push_back(nullptr);
std::string const exe_dir = current_exe_dir(argv[0]);
std::string prefix_paths;
if (forward_mesa)
{
prefix_paths += exe_dir + "/" + mesa_relative_libdir;
}
if (forward_mpi)
{
if (prefix_paths.size() > 0)
{
prefix_paths += path_separator;
}
prefix_paths += exe_dir + "/" + mpi_relative_libdir;
}
// Set up the environment
if (prefix_paths.size() > 0)
{
char const* cur_value = vtksys::SystemTools::GetEnv(library_env);
std::string new_library_env;
// Unset -> use just the new path.
if (!cur_value)
{
new_library_env = prefix_paths;
}
// Empty -> use just the new path.
else if (!*cur_value)
{
new_library_env = prefix_paths;
}
// Prepend it with the separator.
else
{
new_library_env = prefix_paths + path_separator + cur_value;
}
set_launcher_env(print, library_env, new_library_env.c_str());
}
if (backend)
{
set_launcher_env(print, "GALLIUM_DRIVER", backend);
}
if (help)
{
usage(tool);
std::cerr << std::endl << tool << " options:" << std::endl;
}
// Build the command line for the tool.
std::string const tool_path = exe_dir + "/" + tool + tool_suffix;
// Insert the program to run as argv[0].
args.insert(args.begin(), tool_path.c_str());
// Append a NULL at the end of the array.
args.push_back(nullptr);
// Run the tool with the arguments given.
auto proc = vtksysProcess_New();
vtksysProcess_SetCommand(proc, args.data());
vtksysProcess_SetPipeShared(proc, vtksysProcess_Pipe_STDOUT, 1);
vtksysProcess_SetPipeShared(proc, vtksysProcess_Pipe_STDERR, 1);
vtksysProcess_Execute(proc);
vtksysProcess_WaitForExit(proc, nullptr);
// Extract the result of the command.
int const state = vtksysProcess_GetState(proc);
int ret = EXIT_FAILURE;
if (state == vtksysProcess_State_Exited)
{
ret = vtksysProcess_GetExitValue(proc);
}
else if (state == vtksysProcess_State_Exception)
{
const char* exception_str = vtksysProcess_GetExceptionString(proc);
error("exception occurred: ", exception_str);
}
else if (state == vtksysProcess_State_Error)
{
const char* error_str = vtksysProcess_GetErrorString(proc);
error("process error: ", error_str);
}
else if (state == vtksysProcess_State_Expired)
{
error("timeout error", nullptr);
}
// Cleanup.
vtksysProcess_Delete(proc);
return ret;
}
superbuild_add_project(launchers
DEPENDS paraview
DEPENDS_OPTIONAL mesa mpi qt5
CMAKE_ARGS
-DCMAKE_INSTALL_BINDIR:PATH=bin
-DCMAKE_INSTALL_LIBDIR:PATH=lib
-DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib
-DLAUNCHER_ENABLE_MESA:BOOL=${mesa_enabled}
-DLAUNCHER_MESA_LIBDIR:STRING=<LIBDIR>/mesa
-DLAUNCHER_ENABLE_MPI:BOOL=${mpi_enabled}
-DLAUNCHER_MPI_LIBDIR:STRING=<LIBDIR>/mpi
)
......@@ -214,3 +214,6 @@ superbuild_set_revision(gdal
# https://github.com/judajake/gdal-svn.git
URL "https://www.paraview.org/files/dependencies/gdal-98353693d6f1d607954220b2f8b040375e3d1744.tar.bz2"
URL_MD5 5aa285dcc856f98ce44020ae1ae192cb)
superbuild_set_revision(launchers
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/launchers")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment