Skip to content

Commit

Permalink
Implement multiarch support in catkin
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit 0f2d1c7
Author: Jose Luis Rivero <jrivero@osrfoundation.org>
Date:   Wed Apr 30 02:36:11 2014 +0200

    Improve the method of detecting multiarch

    Run a two step approach using gcc -print-multiarch and, if failed,
    fallback to use dpkg-architecture.

commit 6039d93
Author: Jose Luis Rivero <jrivero@osrfoundation.org>
Date:   Tue Apr 29 19:21:44 2014 +0200

    Fix call to get_multiarch by removing the parameter

commit dcbc8f3
Author: Jose Luis Rivero <jrivero@osrfoundation.org>
Date:   Tue Apr 29 19:08:27 2014 +0200

    Replace dpkg-architecture by gcc -print-multiarch.

    Silent the error on cmake if the flag is not present. Checking the
    content of the OUTPUT_VARIABLE for empty should be enough to detect
    errors on multiarch detection.

commit c1c02af
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 17:07:42 2014 -0700

    Fix test by escaping single quotes

commit ae19d1b
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 16:20:22 2014 -0700

    Starting to fix broken test

commit 232d56b
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 15:55:27 2014 -0700

    Use temporary path variable in loop per @dirk-thomas 's suggestion

commit 324ac93
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 15:46:22 2014 -0700

    Remove trailing whitespace from dpkg-architecture call

commit 90f56a4
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 15:41:22 2014 -0700

    Use string with spaces for subprocess command

commit 948eb7d
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 15:32:02 2014 -0700

    Fix subprocess invocation per suggestion from @wjwwood

commit e114c9d
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 15:24:38 2014 -0700

    Use CATKIN_GLOBAL_LIB_DESTINATION and os.path.join

commit 6f89efe
Author: Steven Peters <scpeters@osrfoundation.org>
Date:   Mon Apr 28 15:01:52 2014 -0700

    Attempt at multiarch support (ros#545)

    This is an attempt at multiarch support (ros#545), supercedes
    (ros#604). The dpkg-architecture command is used to identify
    an appropriate lib folder suffix to use for LD_LIBRARY_PATH
    and PKG_CONFIG_PATH. builder.py and
    catkin_generate_environment.cmake are modified
    accordingly, though there's still a problem with isolated
    devel spaces.
  • Loading branch information
scpeters committed Apr 30, 2014
1 parent dfde4aa commit 35d9827
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 16 deletions.
24 changes: 24 additions & 0 deletions cmake/catkin_generate_environment.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@ function(catkin_generate_environment)
file(WRITE "${CMAKE_BINARY_DIR}/CATKIN_IGNORE" "")
endif()

# get multiarch name
set(CATKIN_MULTIARCH_LIB_DESTINATION "'${CATKIN_GLOBAL_LIB_DESTINATION}'")
set(CATKIN_MULTIARCH_PKGCONFIG_DESTINATION "os.path.join('${CATKIN_GLOBAL_LIB_DESTINATION}', 'pkgconfig')")
if (UNIX AND NOT APPLE)
# Two step looking for multiarch support: check for gcc -print-multiarch
# and, if failed, try to run dpkg-architecture
execute_process(COMMAND gcc -print-multiarch
OUTPUT_VARIABLE CATKIN_MULTIARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if (NOT "${CATKIN_MULTIARCH}" STREQUAL "")
execute_process(COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
OUTPUT_VARIABLE CATKIN_MULTIARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if (NOT "${CATKIN_MULTIARCH}" STREQUAL "")
set(CATKIN_MULTIARCH_LIB_DESTINATION "['${CATKIN_GLOBAL_LIB_DESTINATION}', os.path.join('${CATKIN_GLOBAL_LIB_DESTINATION}', '${CATKIN_MULTIARCH}')]")
set(CATKIN_MULTIARCH_PKGCONFIG_DESTINATION "[os.path.join('${CATKIN_GLOBAL_LIB_DESTINATION}', 'pkgconfig'), os.path.join('${CATKIN_GLOBAL_LIB_DESTINATION}', '${CATKIN_MULTIARCH}', 'pkgconfig')]")
endif()
endif()

# generate Python setup util
atomic_configure_file(${catkin_EXTRAS_DIR}/templates/_setup_util.py.in
${CATKIN_DEVEL_PREFIX}/_setup_util.py
Expand Down
33 changes: 20 additions & 13 deletions cmake/templates/_setup_util.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ IS_WINDOWS = (system == 'Windows')
ENV_VAR_SUBFOLDERS = {
'CMAKE_PREFIX_PATH': '',
'CPATH': 'include',
'LD_LIBRARY_PATH' if not IS_DARWIN else 'DYLD_LIBRARY_PATH': '@CATKIN_GLOBAL_LIB_DESTINATION@',
'LD_LIBRARY_PATH' if not IS_DARWIN else 'DYLD_LIBRARY_PATH': @CATKIN_MULTIARCH_LIB_DESTINATION@,
'PATH': '@CATKIN_GLOBAL_BIN_DESTINATION@',
'PKG_CONFIG_PATH': 'lib/pkgconfig',
'PKG_CONFIG_PATH': @CATKIN_MULTIARCH_PKGCONFIG_DESTINATION@,
'PYTHONPATH': '@PYTHON_INSTALL_DIR@',
}

Expand All @@ -68,11 +68,14 @@ def rollback_env_variables(environ, env_var_subfolders):
lines = []
unmodified_environ = copy.copy(environ)
for key in sorted(env_var_subfolders.keys()):
subfolder = env_var_subfolders[key]
value = _rollback_env_variable(unmodified_environ, key, subfolder)
if value is not None:
environ[key] = value
lines.append(assignment(key, value))
subfolders = env_var_subfolders[key]
if type(subfolders) != type([]):
subfolders = [subfolders]
for subfolder in subfolders:
value = _rollback_env_variable(unmodified_environ, key, subfolder)
if value is not None:
environ[key] = value
lines.append(assignment(key, value))
if lines:
lines.insert(0, comment('reset environment variables by unrolling modifications based on all workspaces in CMAKE_PREFIX_PATH'))
return lines
Expand Down Expand Up @@ -143,19 +146,23 @@ def prepend_env_variables(environ, env_var_subfolders, workspaces):
return lines


def _prefix_env_variable(environ, name, paths, subfolder):
def _prefix_env_variable(environ, name, paths, subfolders):
'''
Return the prefix to prepend to the environment variable NAME, adding any path in NEW_PATHS_STR without creating duplicate or empty items.
'''
value = environ[name] if name in environ else ''
environ_paths = [path for path in value.split(os.pathsep) if path]
checked_paths = []
for path in paths:
if subfolder:
path = os.path.join(path, subfolder)
# exclude any path already in env and any path we already added
if path not in environ_paths and path not in checked_paths:
checked_paths.append(path)
if type(subfolders) != type([]):
subfolders = [subfolders]
for subfolder in subfolders:
path_tmp = path
if subfolder:
path_tmp = os.path.join(path_tmp, subfolder)
# exclude any path already in env and any path we already added
if path_tmp not in environ_paths and path_tmp not in checked_paths:
checked_paths.append(path_tmp)
prefix_str = os.pathsep.join(checked_paths)
if prefix_str != '' and environ_paths:
prefix_str += os.pathsep
Expand Down
23 changes: 21 additions & 2 deletions python/catkin/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,22 @@ def isolation_print_command(cmd, path=None, add_env=None):
)


def get_multiarch():
# this function returns the suffix for lib directories on supported systems or an empty string
# it uses two step approach to look for multiarch: first run gcc -print-multiarch and if
# failed try to run dpkg-architecture
out, err = subprocess.Popen(
['gcc -print-multiarch'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
if err:
out, err = subprocess.Popen(
['dpkg-architecture -qDEB_HOST_MULTIARCH'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()

# be sure of returning empty string or a valid multiarch tuple format
assert(not out.strip() or out.strip().count('-') == 2);
return out.strip()

def get_python_install_dir():
# this function returns the same value as the CMake variable PYTHON_INSTALL_DIR from catkin/cmake/python.cmake
python_install_dir = 'lib'
Expand Down Expand Up @@ -518,9 +534,12 @@ def build_cmake_package(
subs['ld_path'] = os.path.join(install_target, 'lib') + ":"
pythonpath = os.path.join(install_target, get_python_install_dir())
subs['pythonpath'] = pythonpath + ':'
subs['pkgcfg_path'] = os.path.join(install_target, 'lib', 'pkgconfig')
subs['pkgcfg_path'] += ":"
subs['pkgcfg_path'] = os.path.join(install_target, 'lib', 'pkgconfig') + ":"
subs['path'] = os.path.join(install_target, 'bin') + ":"
arch = get_multiarch()
if arch:
subs['ld_path'] += ":" + os.path.join(install_target, 'lib', arch) + ":"
subs['pkgcfg_path'] += ":" + os.path.join(install_target, 'lib', arch, 'pkgconfig') + ":"
if not os.path.exists(os.path.dirname(new_setup_path)):
os.mkdir(os.path.dirname(new_setup_path))
with open(new_setup_path, 'w') as file_handle:
Expand Down
3 changes: 2 additions & 1 deletion test/unit_tests/test_setup_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

data = configure_file(os.path.join(os.path.dirname(__file__), '..', '..', 'cmake', 'templates', '_setup_util.py.in'),
{
'CATKIN_GLOBAL_LIB_DESTINATION': 'lib',
'CATKIN_MULTIARCH_LIB_DESTINATION': '\'lib\'',
'CATKIN_MULTIARCH_PKGCONFIG_DESTINATION': 'os.path.join(\'lib\', \'pkgconfig\')',
'CATKIN_GLOBAL_BIN_DESTINATION': 'bin',
'PYTHON_INSTALL_DIR': 'pythonX.Y/packages',
'CMAKE_PREFIX_PATH_AS_IS': '',
Expand Down

0 comments on commit 35d9827

Please sign in to comment.