2017-02-10 10:53:34 -05:00
# Mason CMake
2016-12-15 05:31:15 -05:00
2017-02-10 10:53:34 -05:00
include ( CMakeParseArguments )
2016-12-15 05:31:15 -05:00
2017-02-10 10:53:34 -05:00
function ( mason_detect_platform )
# Determine platform
if ( NOT MASON_PLATFORM )
# we call uname -s manually here since
# CMAKE_HOST_SYSTEM_NAME will not be defined before the project() call
execute_process (
C O M M A N D u n a m e - s
O U T P U T _ V A R I A B L E U N A M E
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E )
if ( UNAME STREQUAL "Darwin" )
set ( MASON_PLATFORM "osx" PARENT_SCOPE )
else ( )
set ( MASON_PLATFORM "linux" PARENT_SCOPE )
endif ( )
2016-12-15 05:31:15 -05:00
endif ( )
2017-02-10 10:53:34 -05:00
# Determine platform version string
if ( NOT MASON_PLATFORM_VERSION )
execute_process (
C O M M A N D u n a m e - m
O U T P U T _ V A R I A B L E M A S O N _ P L A T F O R M _ V E R S I O N
O U T P U T _ S T R I P _ T R A I L I N G _ W H I T E S P A C E )
set ( MASON_PLATFORM_VERSION "${MASON_PLATFORM_VERSION}" PARENT_SCOPE )
2016-12-15 05:31:15 -05:00
endif ( )
2017-02-10 10:53:34 -05:00
endfunction ( )
2016-12-15 05:31:15 -05:00
function ( mason_use _PACKAGE )
if ( NOT _PACKAGE )
message ( FATAL_ERROR "[Mason] No package name given" )
endif ( )
cmake_parse_arguments ( "" "HEADER_ONLY" "VERSION" "" ${ ARGN } )
if ( _UNPARSED_ARGUMENTS )
message ( FATAL_ERROR "[Mason] mason_use() called with unrecognized arguments: ${_UNPARSED_ARGUMENTS}" )
endif ( )
if ( NOT _VERSION )
message ( FATAL_ERROR "[Mason] Specifying a version is required" )
endif ( )
if ( MASON_PACKAGE_ ${ _PACKAGE } _INVOCATION STREQUAL "${MASON_INVOCATION}" )
# Check that the previous invocation of mason_use didn't select another version of this package
if ( NOT MASON_PACKAGE_ ${ _PACKAGE } _VERSION STREQUAL ${ _VERSION } )
message ( FATAL_ERROR "[Mason] Already using ${_PACKAGE} ${MASON_PACKAGE_${_PACKAGE}_VERSION}. Cannot select version ${_VERSION}." )
endif ( )
else ( )
if ( _HEADER_ONLY )
set ( _PLATFORM_ID "headers" )
else ( )
set ( _PLATFORM_ID "${MASON_PLATFORM}-${MASON_PLATFORM_VERSION}" )
endif ( )
set ( _SLUG "${_PLATFORM_ID}/${_PACKAGE}/${_VERSION}" )
set ( _INSTALL_PATH "${MASON_PACKAGE_DIR}/${_SLUG}" )
file ( RELATIVE_PATH _INSTALL_PATH_RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${_INSTALL_PATH}" )
if ( NOT EXISTS "${_INSTALL_PATH}" )
set ( _CACHE_PATH "${MASON_PACKAGE_DIR}/.binaries/${_SLUG}.tar.gz" )
if ( NOT EXISTS "${_CACHE_PATH}" )
# Download the package
set ( _URL "${MASON_REPOSITORY}/${_SLUG}.tar.gz" )
2017-02-10 10:53:34 -05:00
message ( "[Mason] Downloading package ${_URL}..." )
2016-12-15 05:31:15 -05:00
set ( _FAILED )
set ( _ERROR )
# Note: some CMake versions are compiled without SSL support
get_filename_component ( _CACHE_DIR "${_CACHE_PATH}" DIRECTORY )
file ( MAKE_DIRECTORY "${_CACHE_DIR}" )
execute_process (
C O M M A N D c u r l - - r e t r y 3 - s - f - S - L " $ { _ U R L } " - o " $ { _ C A C H E _ P A T H } . t m p "
R E S U L T _ V A R I A B L E _ F A I L E D
E R R O R _ V A R I A B L E _ E R R O R )
if ( _FAILED )
message ( FATAL_ERROR "[Mason] Failed to download ${_URL}: ${_ERROR}" )
else ( )
# We downloaded to a temporary file to prevent half-finished downloads
file ( RENAME "${_CACHE_PATH}.tmp" "${_CACHE_PATH}" )
endif ( )
endif ( )
# Unpack the package
2017-02-10 10:53:34 -05:00
message ( "[Mason] Unpacking package to ${_INSTALL_PATH_RELATIVE}..." )
2016-12-15 05:31:15 -05:00
file ( MAKE_DIRECTORY "${_INSTALL_PATH}" )
execute_process (
C O M M A N D $ { C M A K E _ C O M M A N D } - E t a r x z f " $ { _ C A C H E _ P A T H } "
W O R K I N G _ D I R E C T O R Y " $ { _ I N S T A L L _ P A T H } " )
endif ( )
2017-02-10 10:53:34 -05:00
# Error out if there is no config file.
2016-12-15 05:31:15 -05:00
if ( NOT EXISTS "${_INSTALL_PATH}/mason.ini" )
2017-02-10 10:53:34 -05:00
message ( FATAL_ERROR "[Mason] Could not find mason.ini for package ${_PACKAGE} ${_VERSION}" )
2016-12-15 05:31:15 -05:00
endif ( )
set ( MASON_PACKAGE_ ${ _PACKAGE } _PREFIX "${_INSTALL_PATH}" CACHE STRING "${_PACKAGE} ${_INSTALL_PATH}" FORCE )
mark_as_advanced ( MASON_PACKAGE_ ${ _PACKAGE } _PREFIX )
# Load the configuration from the ini file
file ( STRINGS "${_INSTALL_PATH}/mason.ini" _CONFIG_FILE )
foreach ( _LINE IN LISTS _CONFIG_FILE )
string ( REGEX MATCH "^([a-z_]+) *= *" _KEY "${_LINE}" )
if ( _KEY )
string ( LENGTH "${_KEY}" _KEY_LENGTH )
string ( SUBSTRING "${_LINE}" ${ _KEY_LENGTH } -1 _VALUE )
string ( REGEX REPLACE ";.*$" "" _VALUE "${_VALUE}" ) # Trim trailing commas
string ( REPLACE "{prefix}" "${_INSTALL_PATH}" _VALUE "${_VALUE}" )
string ( STRIP "${_VALUE}" _VALUE )
string ( REPLACE "=" "" _KEY "${_KEY}" )
string ( STRIP "${_KEY}" _KEY )
string ( TOUPPER "${_KEY}" _KEY )
if ( _KEY STREQUAL "INCLUDE_DIRS" OR _KEY STREQUAL "STATIC_LIBS" )
separate_arguments ( _VALUE )
endif ( )
set ( MASON_PACKAGE_ ${ _PACKAGE } _ ${ _KEY } "${_VALUE}" CACHE STRING "${_PACKAGE} ${_KEY}" FORCE )
mark_as_advanced ( MASON_PACKAGE_ ${ _PACKAGE } _ ${ _KEY } )
endif ( )
endforeach ( )
# Compare version in the package to catch errors early on
if ( NOT _VERSION STREQUAL MASON_PACKAGE_ ${ _PACKAGE } _VERSION )
message ( FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has version '${MASON_PACKAGE_${_PACKAGE}_VERSION}', but required '${_VERSION}'" )
endif ( )
if ( NOT _PACKAGE STREQUAL MASON_PACKAGE_ ${ _PACKAGE } _NAME )
message ( FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has name '${MASON_PACKAGE_${_PACKAGE}_NAME}', but required '${_NAME}'" )
endif ( )
if ( NOT _HEADER_ONLY )
if ( NOT MASON_PLATFORM STREQUAL MASON_PACKAGE_ ${ _PACKAGE } _PLATFORM )
message ( FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has platform '${MASON_PACKAGE_${_PACKAGE}_PLATFORM}', but required '${MASON_PLATFORM}'" )
endif ( )
if ( NOT MASON_PLATFORM_VERSION STREQUAL MASON_PACKAGE_ ${ _PACKAGE } _PLATFORM_VERSION )
message ( FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has platform version '${MASON_PACKAGE_${_PACKAGE}_PLATFORM_VERSION}', but required '${MASON_PLATFORM_VERSION}'" )
endif ( )
endif ( )
# Concatenate the static libs and libraries
set ( _LIBRARIES )
list ( APPEND _LIBRARIES ${ MASON_PACKAGE_${_PACKAGE } _STATIC_LIBS} ${ MASON_PACKAGE_${_PACKAGE } _LDFLAGS} )
set ( MASON_PACKAGE_ ${ _PACKAGE } _LIBRARIES "${_LIBRARIES}" CACHE STRING "${_PACKAGE} _LIBRARIES" FORCE )
mark_as_advanced ( MASON_PACKAGE_ ${ _PACKAGE } _LIBRARIES )
if ( NOT _HEADER_ONLY )
string ( REGEX MATCHALL "(^| +)-L *([^ ]+)" MASON_PACKAGE_ ${ _PACKAGE } _LIBRARY_DIRS "${MASON_PACKAGE_${_PACKAGE}_LDFLAGS}" )
string ( REGEX REPLACE "(^| +)-L *" "\\1" MASON_PACKAGE_ ${ _PACKAGE } _LIBRARY_DIRS "${MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS}" )
set ( MASON_PACKAGE_ ${ _PACKAGE } _LIBRARY_DIRS "${MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS}" CACHE STRING "${_PACKAGE} ${MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS}" FORCE )
mark_as_advanced ( MASON_PACKAGE_ ${ _PACKAGE } _LIBRARY_DIRS )
endif ( )
# Store invocation ID to prevent different versions of the same package in one invocation
set ( MASON_PACKAGE_ ${ _PACKAGE } _INVOCATION "${MASON_INVOCATION}" CACHE INTERNAL "${_PACKAGE} invocation ID" FORCE )
endif ( )
endfunction ( )
macro ( target_add_mason_package _TARGET _VISIBILITY _PACKAGE )
if ( NOT MASON_PACKAGE_ ${ _PACKAGE } _INVOCATION )
message ( FATAL_ERROR "[Mason] Package ${_PACKAGE} has not been initialized yet" )
endif ( )
target_include_directories ( ${ _TARGET } ${ _VISIBILITY } "${MASON_PACKAGE_${_PACKAGE}_INCLUDE_DIRS}" )
target_compile_definitions ( ${ _TARGET } ${ _VISIBILITY } "${MASON_PACKAGE_${_PACKAGE}_DEFINITIONS}" )
target_compile_options ( ${ _TARGET } ${ _VISIBILITY } "${MASON_PACKAGE_${_PACKAGE}_OPTIONS}" )
target_link_libraries ( ${ _TARGET } ${ _VISIBILITY } "${MASON_PACKAGE_${_PACKAGE}_LIBRARIES}" )
endmacro ( )
2017-02-10 10:53:34 -05:00
# Setup
string ( RANDOM LENGTH 16 MASON_INVOCATION )
# Read environment variables if CMake is run in command mode
if ( CMAKE_ARGC )
set ( MASON_PLATFORM "$ENV{MASON_PLATFORM}" )
set ( MASON_PLATFORM_VERSION "$ENV{MASON_PLATFORM_VERSION}" )
set ( MASON_PACKAGE_DIR "$ENV{MASON_PACKAGE_DIR}" )
set ( MASON_REPOSITORY "$ENV{MASON_REPOSITORY}" )
endif ( )
# Directory where Mason packages are located; typically ends with mason_packages
if ( NOT MASON_PACKAGE_DIR )
set ( MASON_PACKAGE_DIR "${CMAKE_SOURCE_DIR}/mason_packages" )
endif ( )
# URL prefix of where packages are located.
if ( NOT MASON_REPOSITORY )
set ( MASON_REPOSITORY "https://mason-binaries.s3.amazonaws.com" )
endif ( )
mason_detect_platform ( )
# Execute commands if CMake is run in command mode
if ( CMAKE_ARGC )
# Collect remaining arguments for passing to mason_use
set ( _MASON_ARGS )
if ( ${ CMAKE_ARGC } LESS 5 )
message ( FATAL_ERROR "Usage: mason.sh [install|prefix] PACKAGE VERSION" )
endif ( )
if ( ${ CMAKE_ARGV3 } STREQUAL "install" )
# Install the package
mason_use ( ${ CMAKE_ARGV4 } VERSION ${ CMAKE_ARGV5 } )
elseif ( ${ CMAKE_ARGV3 } STREQUAL "prefix" )
set ( PKG_PREFIX "${MASON_PACKAGE_DIR}/${MASON_PLATFORM}-${MASON_PLATFORM_VERSION}/${CMAKE_ARGV4}/${CMAKE_ARGV5}" )
# CMake can't write to stdout with message()
execute_process ( COMMAND ${ CMAKE_COMMAND } -E echo "${PKG_PREFIX}" )
else ( )
message ( FATAL_ERROR "Usage: mason.sh [install|prefix] PACKAGE VERSION" )
endif ( )
endif ( )