Commits (41)
#[==[.md
# `CTestCustom.cmake`
This is a trampoline CTest custom file which includes any other
`CTestCustom.cmake` files provided by a superbuild.
#]==]
# INTERNAL
# Sets up CTest's variables to ignore messages from a project.
function (_project_ignore_regexes variable project)
......@@ -21,20 +28,27 @@ function (_project_ignore_regexes variable project)
PARENT_SCOPE)
endfunction ()
# Ignore warnings from a project.
#
# Usage:
#
# ignore_project_warnings(<name>)
#[==[.md
## Ignoring project outputs
Since superbuilds build many third party projects, it can be useful to ignore
all warnings and errors coming from a project. Note that these only suppress
from appearing on CDash. To completely silence a project even when building
interactively, it is better to use `SUPPRESS_<project>_OUTPUT` variables.
Real errors will still fail the build, but output of configure-time failures
will not show up in CDash.
```
ignore_project_warnings(<project>)
ignore_project_errors(<project>)
```
#]==]
macro (ignore_project_warnings project)
_project_ignore_regexes(CTEST_CUSTOM_WARNING_EXCEPTION "${project}")
endmacro ()
# Ignore errors from a project.
#
# Usage:
#
# ignore_project_errors(<name>)
macro (ignore_project_errors project)
_project_ignore_regexes(CTEST_CUSTOM_ERROR_EXCEPTION "${project}")
endmacro ()
......
#[==[.md
# Cross compilation support
This is untested, but exists from prior support in a previous implemenation of
the superbuild. Most of them are intended to be used by the common superbuild
itself, but there are some hooks projects can set.
It seems that the module is largely ignored for now.
#]==]
#[==[.md
## Hooks
### `superbuild_cross_prepare`
If defined, this command is called in order to to do any up-front configuration
settings which may be necessary.
#]==]
# Sets up the build for a particular target platform.
#
# Currently unused.
function (superbuild_cross_determine_target)
if (NOT CMAKE_CROSSCOMPILING)
return ()
......@@ -7,8 +29,7 @@ function (superbuild_cross_determine_target)
# right environment settings.
_superbuild_cross_target_machine()
# Configure the platform dependent settings 64bit_build, static_only, mpi
# search path.
# Configure platform dependent settings 64bit_build, static_only.
_superbuild_cross_platform_settings()
if (COMMAND superbuild_cross_prepare)
......@@ -16,22 +37,21 @@ function (superbuild_cross_determine_target)
endif ()
endfunction ()
#=============================================================================
# Ask user what the target machine is, so that we can choose the right
# right build hints and patches later on.
#
# Provide a cache variable to indicate the targeted machine.
function (_superbuild_cross_target_machine)
set(cross_target "generic"
set(SUPERBUILD_CROSS_TARGET "generic"
CACHE STRING "Platform to cross compile for, either generic|bgp_xlc|bgq_xlc|bgq_gnu|xk7_gnu")
set_property(CACHE cross_target PROPERTY STRINGS
# TODO: This should be managed by the project, not hard-coded.
set_property(CACHE SUPERBUILD_CROSS_TARGET PROPERTY STRINGS
"generic" "bgp_xlc" "bgq_xlc" "bgq_gnu" "xk7_gnu")
endfunction ()
#=============================================================================
# Includes an optionally site-specific file from the cross-compiling directory.
# Includes an optional site-specific file from the cross-compiling directory.
#
# Currently unused.
function (_superbuild_cross_include_file var name)
set(site_file
"crosscompile/${cross_target}/${name}.cmake")
"crosscompile/${SUPERBUILD_CROSS_TARGET}/${name}.cmake")
include("${site_file}" OPTIONAL
RESULT_VARIABLE res)
if (NOT res)
......@@ -43,13 +63,11 @@ function (_superbuild_cross_include_file var name)
PARENT_SCOPE)
endfunction ()
#=============================================================================
# Configures the cmake files that describe how to cross compile paraview
# From the ${cross_target} directory into the build tree.
#
# Configures the cmake files that describe how to crosscompile for a given
# platform. From the ${SUPERBUILD_CROSS_TARGET} directory into the build tree.
function (_superbuild_cross_platform_settings)
set(site_toolchain
"${CMAKE_CURRENT_LIST_DIR}/crosscompile/${cross_target}/toolchain.cmake.in")
"${CMAKE_SOURCE_DIR}/crosscompile/${SUPERBUILD_CROSS_TARGET}/toolchain.cmake.in")
set(superbuild_cross_toolchain
"${CMAKE_BINARY_DIR}/crosscompile/toolchain.cmake")
......
# This file implements the logic to inject environment variables into the build
# steps of projects. It is quite messy.
#[==[.md INTERNAL
# `SuperbuildExternalProject`
This file is basically a wrapper around CMake's `ExternalProject` module with
additional support for managing environments, parallel build settings, download
management, and output suppression.
#]==]
if (CMAKE_VERSION VERSION_LESS "3.9")
# Needed for fixes.
......@@ -26,7 +31,7 @@ if (CMAKE_GENERATOR MATCHES "Makefiles")
set(superbuild_make_program "${CMAKE_MAKE_PROGRAM}")
endif ()
# Add "PROCESS_ENVIRONMENT" to the list of keywords recognized.
# Add `PROCESS_ENVIRONMENT` to the list of keywords.
string(REPLACE ")" "|PROCESS_ENVIRONMENT)"
_ep_keywords__superbuild_ExternalProject_add "${_ep_keywords_ExternalProject_Add}")
......@@ -67,6 +72,7 @@ function (_superbuild_ep_strip_extra_arguments name)
ExternalProject_add("${name}" "${arguments}")
endfunction ()
# Wraps a command in a CMake script which handles environment management.
function (_superbuild_ep_wrap_command var target command_name)
get_property(has_command TARGET "${target}"
PROPERTY "_EP_${command_name}_COMMAND" SET)
......@@ -129,6 +135,7 @@ function (_superbuild_ExternalProject_add name)
return ()
endif ()
# Wrap the three main commands which require environment manipulation.
_superbuild_ep_wrap_command(configure_command "sb-${name}" CONFIGURE)
_superbuild_ep_wrap_command(build_command "sb-${name}" BUILD)
_superbuild_ep_wrap_command(install_command "sb-${name}" INSTALL)
......@@ -145,7 +152,7 @@ function (_superbuild_ExternalProject_add name)
list(APPEND args
"${install_command}")
# Now strip PROCESS_ENVIRONMENT and commands from arguments.
# Now strip `PROCESS_ENVIRONMENT` and commands from arguments.
set(skip FALSE)
foreach (arg IN LISTS ARGN)
if (arg MATCHES "${_ep_keywords__superbuild_ExternalProject_add}")
......@@ -182,6 +189,7 @@ function (_superbuild_ExternalProject_add name)
# empty install, configure, build, etc.
ExternalProject_add("${name}" "${args}")
# Hook up the download step with the `download-all` target.
if (TARGET "${name}-download")
add_dependencies(download-all
"${name}-download")
......@@ -193,6 +201,7 @@ function (_superbuild_ExternalProject_add name)
_EP_PROCESS_ENVIRONMENT)
_ep_replace_location_tags("${name}" process_environment)
# Configure each CMake script used during the actual build.
foreach (step IN ITEMS configure build install)
if (req_${step}_command)
set(step_command "${original_${step}_command}")
......
This diff is collapsed.
This diff is collapsed.
#[==[.md
# Packaging support
One use case of the superbuild is to build packages for projects in order to
distribute for use as release binaries. The superbuild creates these packages
as tests. The reason it isn't done as a CPack step of the build is because
CPack only supports a single package per build. Multiple formats are supported,
but not distinct packages. Another reason is that CPack runs the `install` step
of a project which redoes a build of all targets. The superbuild may have "use
master" sources and when making a package, we don't want to change what is
being packaged.
The general strategy for the tests is to have a CMake project generated in the
build tree which includes the necessary `.bundle.cmake` files. These files
contain install code and can use CPack variables to change the generated
package.
#]==]
set(_superbuild_packaging_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
# Adds a test to package a "bundle" project.
#
# Usage:
#
# superbuild_add_extra_package_test(<name> <generator>
# [<property> <value>]...)
#
# This packages a bundle described by a ``${name}.bundle.cmake`` file in the
# project hierarchy. Variables may be put into the package's context by setting
# the ``superbuild_export_variables`` variable to a list of variables to put
# into the generated CMake project.
#
# Extra arguments are set as properties on the test. This should be used for
# things such as ``TIMEOUT`` and ``LABEL``.
#
# This creates a test named ``cpack-${name}-${generator}`` which generates the
# package requested. These tests are set up so that they cannot run in parallel
# with each other. This is because CPack uses the ``_CPack_Packages`` directory
# for itself in all tests.
# TODO: link to the right section in SuperbuildVariables.md
#[==[.md
## Adding a package test
The `superbuild_add_extra_package_test` function handles the logic for adding a
test which builds the package. Due to the way CPack works, only one packaging
test may be run concurrently.
```
superbuild_add_extra_package_test(<NAME> <GENERATOR>
[<PROPERTY> <VALUE>]...)
```
Adds a test with the name `cpack-NAME-GENERATOR`. The packaging rules are
handled by including a `NAME.bundle.cmake` file. The same include paths used in
the build are available in the packaging steps. By default, only the variables
in the [SuperbuildVariables][] packaging section are available. Other variables
may be passed to the packaging step by adding the variable name to the
`superbuild_export_variables` list. The value of the variable available when
adding the test is used.
All other arguments are set as properties on the tests. The only reserved
property is the `RESOURCE_LOCK` property.
[SuperbuildVariables]: SuperbuildVariables.md
#]==]
# TODO: use a PROPERTIES argument
# TODO: use a VARIABLES argument
function (superbuild_add_extra_package_test name generator)
set(superbuild_extra_variables)
foreach (variable IN LISTS superbuild_export_variables)
......@@ -27,6 +55,7 @@ function (superbuild_add_extra_package_test name generator)
endforeach ()
set(cpack_source_dir "${CMAKE_BINARY_DIR}/cpack/${name}/${generator}")
# Create a build directory so that the installation variant doesn't conflict.
set(cpack_build_dir "${cpack_source_dir}/build")
configure_file(
"${_superbuild_packaging_cmake_dir}/superbuild_package_cmakelists.cmake.in"
......@@ -57,14 +86,19 @@ function (superbuild_add_extra_package_test name generator)
${ARGN})
endfunction ()
# Add a "superbuild-install" target to install one of the packages.
#
# This function adds a target which acts like "make install" for a selected
# package.
#
# The ``default`` argument is used as the default package to build and the
# cache editors use the list of available packages as the selection choices for
# the ``SUPERBUILD_DEFAULT_INSTALL`` variable.
#[==[.md
In addition to packages, a package may be used as a template for the `install`
target of the superbuild.
```
superbuild_enable_install_target(<DEFAULT>)
```
This uses a user-selectable `.bundle.cmake` to control the `install` target of
the superbuild. The default should be in the form `<NAME>/<GENERATOR>`. An
error is produced if the test for the package does not exist.
#]==]
function (superbuild_enable_install_target default)
get_property(all_packages GLOBAL
PROPERTY _superbuild_packages)
......@@ -112,27 +146,3 @@ function (superbuild_enable_install_target default)
COMPONENT install)
endif ()
endfunction ()
# DEPRECATED
# Adds a test to package the top-level superbuild.
#
# This is deprecated because CPack will rerun the build of the top-level
# project. Since superbuilds never have a "do-nothing" build in the presense of
# Git repositories, it is not recommended to use this.
function (superbuild_add_package_test generator)
message(AUTHOR_WARNING
"superbuild_add_package_test: This function is deprecated; "
"use the newer superbuild_add_extra_package_test mechanism instead.")
add_test(
NAME "cpack-${generator}"
COMMAND "${CMAKE_CPACK_COMMAND}"
-V
-G "${generator}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
set_tests_properties("cpack-${generator}"
PROPERTIES
RESOURCE_LOCK cpack
${ARGN})
endfunction ()
#[==[.md
# Specifying revisions
When building a package, its sources must come from somewhere. In order to keep
the "what to build" (sources) separate from the "how to build" (the project
files) and separately updatable, the superbuild gathers source information
separately.
There are multiple ways to specify a revision with the functions in the
superbuild, but in general, a package will use the first-specified revision
that is encountered. This is so that a specific project can, for example, use a
different version of Boost than is provided in the common superbuild
infrastructure.
#]==]
include(CMakeParseArguments)
# Sets the arguments to ``ExternalProject_add`` to download the project.
#
# Usage:
#
# superbuild_set_revision(<name> <args>...)
#
# If this is called multiple times for a single project, only the first one
# takes effect.
#[==[.md
## Simple use case
The simplest use case is when a project just has a given location for its
sources that isn't configurable at build time by a user.
```
superbuild_set_revision(<NAME> <ARG>...)
```
The `superbuild_set_revision` function stores the given `ARG` for use when then
`NAME` project is built. See the documentation for [ExternalProject][] for the
supported download location arguments.
Note that validation of the arguments only happens when the project is being
built.
[ExternalProject]: https://cmake.org/cmake/help/v3.9/module/ExternalProject.html
#]==]
function (superbuild_set_revision name)
get_property(have_revision GLOBAL
PROPERTY
......@@ -20,26 +46,33 @@ function (superbuild_set_revision name)
endif ()
endfunction ()
# Sets arguments to ``ExternalProject_add`` to download the project, but adds
# cache variables so that they may be changed by the user.
#
# Usage:
#
# superbuild_set_customizable_revision(<name> <args>...)
#
# Adds advanced variables for the following keys:
#
# GIT_REPOSITORY, GIT_TAG, URL, URL_HASH, URL_MD5, and SOURCE_DIR
#
# they are named ``${name_UPPER}_${key}``.
function (superbuild_set_customizable_revision name)
#[==[.md INTERNAL
## Customizable revisions
```
_superbuild_set_customizable_revision(<NAME> <ARG>...)
```
This is used for `CUSTOMIZABLE` revisions in the
`superbuild_set_selectable_source` function. The following keys are turned into
cache variables. Others are ignored.
- `GIT_REPOSITORY`
- `GIT_TAG`
- `URL`
- `URL_HASH`
- `URL_MD5`
- `SOURCE_DIR`
The cache variables are named `<NAME>_<KEY>`.
#]==]
function (_superbuild_set_customizable_revision name)
set(keys
GIT_REPOSITORY GIT_TAG
URL URL_HASH URL_MD5
SOURCE_DIR)
cmake_parse_arguments(_args "" "${keys}" "" ${ARGN})
set(customized_args)
string(TOUPPER "${name}" name_UPPER)
foreach (key IN LISTS keys)
if (_args_${key})
......@@ -48,8 +81,7 @@ function (superbuild_set_customizable_revision name)
if (key STREQUAL "SOURCE_DIR")
set(cache_type PATH)
endif ()
superbuild_deprecated_setting(option_default "${option_name}" "${name_UPPER}_${key}" "${_args_${key}}")
set("${option_name}" "${option_default}"
set("${option_name}" "${_args_${key}}"
CACHE "${cache_type}" "${key} for project '${name}'")
if (NOT key STREQUAL "SOURCE_DIR")
mark_as_advanced(${option_name})
......@@ -66,93 +98,79 @@ function (superbuild_set_customizable_revision name)
${_args_UNPARSED_ARGUMENTS})
endfunction ()
# Convenient way to declare a main project's source.
#
# Usage:
#
# superbuild_set_external_source(<name>
# <git-url> <git-ref>
# <tarball-url> <tarball-md5>)
#
# Adds options to build the project from a git repository, a tarball, or a
# source tree (linked from the source tree as
# ``${CMAKE_SOURCE_DIR}/source-${name}``). Usually relevant for the "primary"
# project(s) in a single superbuild.
function (superbuild_set_external_source name git_repo git_tag tarball_url tarball_md5)
option("${name}_FROM_GIT" "If enabled, fetch sources from GIT" ON)
cmake_dependent_option("${name}_FROM_SOURCE_DIR" "Use an existing source directory" OFF
"NOT ${name}_FROM_GIT" OFF)
set(args)
if (${name}_FROM_GIT)
set(args
GIT_REPOSITORY "${git_repo}"
GIT_TAG "${git_tag}")
elseif (${name}_FROM_SOURCE_DIR)
set(args
SOURCE_DIR "${CMAKE_SOURCE_DIR}/source-${name}")
else ()
set(args
URL "${tarball_url}"
URL_MD5 "${tarball_md5}")
endif ()
superbuild_set_customizable_revision("${name}"
${args})
# Push the cmake_dependent_option to the parent scope.
set("${name}_FROM_SOURCE_DIR"
"${${name}_FROM_SOURCE_DIR}"
PARENT_SCOPE)
endfunction ()
# A way to provide selections for a project's source.
#
# Usage:
#
# superbuild_set_selectable_source(<name>
# [SELECTS_WITH <parent_name>]
# <SELECT <selection_name> [DEFAULT] [CUSTOMIZABLE] [FALLBACK]
# <args...>>...)
#
# This may be used to provide multiple ways to build a project:
#
# superbuild_set_selectable_source(myproject
# SELECT v1.0
# URL "https://hostname/path/to/myproject-1.0.tar.gz"
# URL_MD5 00000000000000000000000000000000
# SELECT v2.0 DEFAULT
# URL "https://hostname/path/to/myproject-2.0.tar.gz"
# URL_MD5 00000000000000000000000000000000
# SELECT git CUSTOMIZABLE
# GIT_REPOSITORY "https://path/to/myproject.git"
# GIT_TAG "origin/master"
# SELECT source CUSTOMIZABLE
# SOURCE_DIR "path/to/local/directory")
#
# superbuild_set_selectable_source(myprojectdocs
# SELECTS_WITH myproject
# SELECT v1.0
# URL "https://hostname/path/to/myprojectdocs-1.0.tar.gz"
# URL_MD5 00000000000000000000000000000000
# SELECT v2.0
# URL "https://hostname/path/to/myprojectdocs-2.0.tar.gz"
# URL_MD5 00000000000000000000000000000000
# SELECT git FALLBACK
# GIT_REPOSITORY "https://path/to/myprojectdocs.git"
# GIT_TAG "origin/master")
#
# Generally, the ``source`` selection should be used to set up an external
# directory as the source tree for the project.
#
# This will create a variable in the cache named ``${name}_SOURCE_SELECTION``
# which may be used to select one of the sources.
#
# If ``SELECTS_WITH`` is given, the selection of the ``<parent_name>`` will be
# used as the selection for this project as well. The ``DEFAULT`` keyword may
# not be used in projects which use ``SELECTS_WITH``. Instead, the ``FALLBACK``
# keyword may be used to indicate that that selection should be used if there
# is not a matching selection in this project.
#[==[.md
## User-selectable sources
Some projects may have different locations for sources that a user might want
to choose between. To facilitate this, a project may have a "selectable"
source. This creates a user-facing cache variable `<NAME>_SOURCE_SELECTION`
which chooses a selection that then indicates where the sources should be
retrieved. It is an error to choose a selection that does not exist.
The signature is:
```
superbuild_set_selectable_source(<NAME>
[SELECTS_WITH <PARENT>]
<SELECT <SELECTION> [DEFAULT] [CUSTOMIZABLE] [FALLBACK]
<ARG>...>...)
```
Each selection is followed by a set of arguments which is used as the source
arguments for the project if it is used. The default selection is either the
one marked by the `DEFAULT` argument or the first selection if none is
specified.
A selection may be `CUSTOMIZABLE` which means that the values to the arguments
may be edited by the user.
A project may also `SELECTS_WITH` another project. If given, the selection of
the `PARENT` project will be used as the selection for this project as well if
it exists. Rather than the `DEFAULT` keyword, a `SELECTS_WITH` project may use
`FALLBACK` which indicates the selection that should be used if the parent
project uses a selection that is not valid for the current project.
Some conventions are used for certain selections, but are not enforced.
Usually, at least the `git` and `source` selections are available for "primary"
projects within a superbuild. Both of these should be marked as `CUSTOMIZABLE`.
As an example:
```cmake
superbuild_set_selectable_source(myproject
SELECT v1.0
URL "https://hostname/path/to/myproject-1.0.tar.gz"
URL_MD5 00000000000000000000000000000000
SELECT v2.0 DEFAULT
URL "https://hostname/path/to/myproject-2.0.tar.gz"
URL_MD5 00000000000000000000000000000000
SELECT git CUSTOMIZABLE
GIT_REPOSITORY "https://path/to/myproject.git"
GIT_TAG "origin/master"
SELECT source CUSTOMIZABLE
SOURCE_DIR "path/to/local/directory")
superbuild_set_selectable_source(myprojectdocs
SELECTS_WITH myproject
SELECT v1.0
URL "https://hostname/path/to/myprojectdocs-1.0.tar.gz"
URL_MD5 00000000000000000000000000000000
SELECT v2.0
URL "https://hostname/path/to/myprojectdocs-2.0.tar.gz"
URL_MD5 00000000000000000000000000000000
SELECT git FALLBACK
GIT_REPOSITORY "https://path/to/myprojectdocs.git"
GIT_TAG "origin/master")
```
In this example, the `myproject` project defaults to the `v2.0` selection. In
addition, a `v1.0` is available and the other two are `CUSTOMIZABLE` which
allows a user to set the values with the given arguments. The `myprojectdocs`
project indicates that it `SELECTS_WITH` `myproject`. This means that if the
selection for `myproject` exists for `myprojectdocs` as well, it will be used.
However, if it does not exist, the selection marked as the `FALLBACK` will be
used instead.
#]==]
function (superbuild_set_selectable_source name)
set(selections)
set(customizable_selections)
......@@ -355,7 +373,7 @@ function (superbuild_set_selectable_source name)
superbuild_set_revision("${name}"
${selection_${selection}_args})
else ()
superbuild_set_customizable_revision("${name}"
_superbuild_set_customizable_revision("${name}"
${selection_${selection}_args})
endif ()
endfunction ()
#[==[.md
# Testing packages
The packages created by the superbuild packaging support may also be tested. In
order to do so, the created package must first be extracted.
#]==]
set(_superbuild_testing_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
# Adds a test which extracts a CPack artifact.
#[==[.md
The `superbuild_add_extract_test` extracts a package generated by a packaging
test.
```
superbuild_add_extract_test(<NAME> <PREFIX> <GENERATOR> <OUTPUT>
[<PROPERTY> <VALUE>]...)
```
The `NAME` and `GENERATOR` arguments must match the corresponding package test
that should be extracted. There is also the `PREFIX` argument which should be a
prefix long enough to make the glob for the resulting package name unique.
The `OUTPUT` is the path to the directory that the package should be extracted
into. One intermediate directory is removed from the extraction. For example, a
package containing `dirname/bin/program` and `dirname/include/header.h` will
have a `bin` and `include` directory under the given output directory.
#]==]
# TODO: use a PROPERTIES argument
function (superbuild_add_extract_test name glob_prefix generator output)
set(_ZIP_test_glob "${glob_prefix}*.zip")
set(_NSIS_test_glob "${glob_prefix}*.exe")
set(_DragNDrop_test_glob "${glob_prefix}*.dmg")
set(_TGZ_test_glob "${glob_prefix}*.tar.gz")
if (NOT DEFINED _${generator}_test_glob)
message(FATAL_ERROR
"No known glob to find packages created by the ${generator} CPack "
"generator.")
endif ()
add_test(
NAME "extract-${name}-${generator}"
COMMAND "${CMAKE_COMMAND}"
......
# Superbuild user variables
## Targets
- `download-all` This target causes the download steps of all projects to be
run. This essentially creates a cache of source files so that a build can
be run without network access. See `SUPERBUILD_OFFLINE_BUILD` for handling
VCS repositories in offline mode.
## Building
### `CMAKE_BUILD_TYPE_<PROJECT>`
Some projects may support having their build configuration chosen independently
of the overall superbuild. If so, this variable is exposed to change its value.
By default, the `<same>` value is used which uses the same build type as the
superbuild (`CMAKE_BUILD_TYPE`).
### `DEVELOPER_MODE_<PROJECT>`
If a project is enabled and supports developer mode, this variable controls
whether it uses the developer mode or not. When a project is in developer mode,
it is not built, but instead it is treated as "enabled" and an associated
`<PROJECT>-developer-config.cmake` file is written into the build directory of
the superbuild. This may be used with `-C` on a standalone build of the
associated project to have it use the superbuild dependencies. Note that
updating environment variables such as `PATH`, `LD_LIBRARY_PATH`,
`DYLD_LIBRARY_PATH`, or `PKG_CONFIG_PATH` to include the relevant paths in the
superbuild install prefix may be required in order to use the resulting build
tree.
### `ENABLE_<PROJECT>`
If set, the associated project will be built. All dependent required projects
are enabled as well.
### `SUPERBUILD_DEFAULT_INSTALL`
If the project creates an install target, it is installed as a specific package
layout. This variable allows for the selection of which package should be
installed.
### `SUPERBUILD_OFFLINE_BUILD`
If set, all implicit updates of direct VCS repositories will be disabled. This
means that if a project is watching the `master` branch of its source
repository, a reconfigure will not trigger a `git fetch` unless the source
directory does not exist at all. This is useful when performing builds on
machines with limited network access.
### `SUPERBUILD_PROJECT_PARALLELISM`
This defaults to the number of CPUs on the machine. It is used as the `-j`
argument for `Makefiles`-based CMake generators. If the number of CPUs cannot
be determined, a reasonably beefy machine is assumed (8 cores).
### `SUPPRESS_<PROJECT>_OUTPUT`
If set, output from the build and install steps of the given project will be
logged to a file instead of appearing in the main build output. This can be
used to hide project warnings and errors from CDash and interactive builds.
### `USE_SYSTEM_<PROJECT>`
Some projects may support finding an external ("system") copy of the project.
Those that do offer this variable which, if set, directs the project to find an
external copy of itself.
## Advanced variables
These variables are workarounds or control internal features. They should only
be used if needed. If these end up being necessary for your builds, please open
a report on the project's page so that we can better track down when these
workarounds are necessary.
### `PASS_LD_LIBRARY_PATH_FOR_BUILDS`
On Linux, there may be cases where errors of the form:
```
libz.so.1: no version information available
```
may appear. In this case, the `PASS_LD_LIBRARY_PATH_FOR_BUILDS` variable should
be turned off.
#[==[.md INTERNAL
# Apple utility functions
On Apple platforms (mainly macOS), some wrangling with version variables and
the link is required. These functions handle that. They are used internally to
the superbuild and do not need to be called manually.
#]==]
#[==[.md INTERNAL
## SDK support
CMake uses various `CMAKE_OSX_` variables to control the SDK in use. The
`superbuild_osx_add_version_flags` function extracts information from these
flags and adds them to the `superbuild_c_flags` and `superbuild_cxx_flags`
variables in the calling scope.
```
superbuild_osx_add_version_flags()
```
#]==]
function (superbuild_osx_add_version_flags)
if (NOT APPLE)
return ()
......@@ -13,7 +33,9 @@ function (superbuild_osx_add_version_flags)
"-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif ()
if (CMAKE_OSX_SYSROOT)
# The "sysroot" may be an SDK name. Get the path to the sysroot from it.
if (NOT IS_DIRECTORY "${CMAKE_OSX_SYSROOT}")
# Ask Xcode what the SDK path is.
execute_process(
COMMAND xcodebuild
-version
......@@ -39,6 +61,17 @@ function (superbuild_osx_add_version_flags)
endforeach ()
endfunction ()
#[==[.md INTERNAL
## Version flags
This `superbuild_osx_pass_version_flags` function sets the given variable to
contain a list of CMake `-D` command line flags to use the same Apple SDK,
architecture, and deployment target as the superbuild.
```
superbuild_osx_pass_version_flags(<VARIABLE>)
```
#]==]
function (superbuild_osx_pass_version_flags var)
if (NOT APPLE)
return ()
......
#[==[.md INTERNAL
# Unix utility functions
On Unix platforms (mainly Linux), some workarounds are sometimes necessary.
These functions implement these workarounds. They are used internally to the
superbuild and do not need to be called manually.
#]==]
include (CMakeDependentOption)
#[==[.md INTERNAL
Sometimes a build will conflict with a system library in use by an external
tool. Since the `LD_LIBRARY_PATH` environment variable is a global setting for
executables, this may cause interference. This function allows users to disable
the logic to continue a build.
The errors that show up if this needs to be disabled are usually due to
mismatches in sonames or version information.
#]==]
function (superbuild_unix_ld_library_path_hack var)
# XXX(Utkarsh): I am not exactly sure about the cause of these issues and how
# to cleanly overcome them, however, on some Linuxes when CMake is built
# shared, if we set LD_LIBRARY_PATH to the install/lib dir, we end up with
# errors due to conflicts with system libz. So for now, I am making this an
# option. By default we will let the superbuild scripts set LD_LIBRARY_PATH.
# However if users get errors like: libz.so.1: no version information
# available, then users should turn this flag off.
cmake_dependent_option(PASS_LD_LIBRARY_PATH_FOR_BUILDS "Pass LD_LIBRARY_PATH to build scripts" ON
"UNIX;NOT APPLE" OFF)
mark_as_advanced(PASS_LD_LIBRARY_PATH_FOR_BUILDS)
......
#[==[.md INTERNAL
# Utility functions
This module contains utility functions mostly used internally to the
superbuild. Some may be of use to corner-case project builds.
#]==]
include("SuperbuildUtils-apple")
include("SuperbuildUtils-unix")
# TODO: In 3.9.0, use the GENERATOR_IS_MULTI_CONFIG global property.
if (NOT CMAKE_CONFIGURATION_TYPES)
set(_superbuild_build_type_force)
if (NOT CMAKE_BUILD_TYPE)
set(_superbuild_build_type_force FORCE)
endif ()
# Default to a Release build.
set(CMAKE_BUILD_TYPE "Release"
CACHE STRING "The build mode" ${_superbuild_build_type_force})
mark_as_advanced(CMAKE_BUILD_TYPE)
......@@ -13,6 +22,10 @@ if (NOT CMAKE_CONFIGURATION_TYPES)
PROPERTY
STRINGS "Release;RelWithDebInfo")
if (NOT WIN32)
# Windows debug builds is not really supported at the moment. Getting all
# projects to agree on the C++ runtime library is not easy. Also, many
# projects hard-code library paths and on Windows, many projects change
# their names for debug builds.
set_property(CACHE CMAKE_BUILD_TYPE APPEND
PROPERTY
STRINGS "Debug")
......@@ -22,6 +35,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES)
message(FATAL_ERROR "A build type (CMAKE_BUILD_TYPE) must be set.")
endif ()
# Ensure that the chosen build type is valid.
get_property(build_type_options
CACHE CMAKE_BUILD_TYPE
PROPERTY STRINGS)
......@@ -47,6 +61,14 @@ if (NOT CMAKE_CONFIGURATION_TYPES)
endif ()
endif ()
#[==[.md INTERNAL
# 64-bit support
Some projects need to know if a build is 32-bit or 64-bit. This function sets
`superbuild_is_64bit`.
In the future, 32-bit support may be removed completely.
#]==]
function (superbuild_detect_64bit_target)
if (CMAKE_CROSSCOMPILING)
return ()
......@@ -61,6 +83,7 @@ function (superbuild_detect_64bit_target)
set(superbuild_is_64bit TRUE
PARENT_SCOPE)
elseif (void_ptr_size EQUAL 4)
# XXX: Error out here? Is there a reason to still support 32-bit?
set(superbuild_is_64bit FALSE
PARENT_SCOPE)
else ()
......@@ -74,25 +97,36 @@ function (superbuild_detect_64bit_target)
endif ()
endfunction ()
macro(superbuild_make_path_var var)
# A utility function to create a PATH-link environment variable value.
macro (_superbuild_make_path_var var)
set(${var} ${ARGN})
list(REMOVE_ITEM ${var} "")
if (UNIX)
string(REPLACE ";" ":" ${var} "${${var}}")
endif ()
endmacro()
endmacro ()
#[==[.md INTERNAL
# Compiler flag setup
Superbuild projects may set add additional language flags to be made available
to projects during their builds via the standard environment variables (more
detail is available in [their documentation](SuperbuildVariables.md#Language
flags)). The function handles the setup of the flags made available to projects
by integrating the environment at configure time, the superbuild's installation
directory for projects.
#]==]
function (superbuild_setup_flags)
if (WIN32)
return ()
endif ()
superbuild_make_path_var(superbuild_ld_library_path
_superbuild_make_path_var(superbuild_ld_library_path
"${superbuild_install_location}/lib"
"$ENV{LD_LIBRARY_PATH}")
set(superbuild_ld_library_path "${superbuild_ld_library_path}" PARENT_SCOPE)
superbuild_make_path_var(superbuild_pkg_config_path
_superbuild_make_path_var(superbuild_pkg_config_path
"${superbuild_install_location}/lib/pkgconfig"
"${superbuild_install_location}/share/pkgconfig"
"$ENV{PKG_CONFIG_PATH}")
......@@ -115,6 +149,12 @@ function (superbuild_setup_flags)
endforeach ()
endfunction ()
#[==[.md INTERNAL
# Preparing the build tree
The build tree needs some preparation for some features. These steps are done
here.
#]==]
macro (superbuild_prepare_build_tree)
if (WIN32)
# Windows doesn't like it if that directory does not exist even if it is
......@@ -128,37 +168,44 @@ macro (superbuild_prepare_build_tree)
"${_superbuild_module_gen_dir}")
endmacro ()
# Bridge an old, deprecated, setting to a new replacement setting.
#
# Use this function when a user-visible flag is being renamed or otherwise
# replaced. If the old value is set, it will be given as the default value,
# otherwise the given default value will be used. This returned value should
# then be used in the ``set(CACHE)`` or ``option()`` call for the new value.
#
# If the old value is set, it will warn that it is deprecated for the new name.
#
# If replacing the setting ``OLD_SETTING`` with ``NEW_SETTING``, its usage
# would look like:
#
# superbuild_deprecated_setting(default_setting NEW_SETTING OLD_SETTING "default value")
# set(NEW_SETTING "${default_setting}"
# CACHE STRING "Documentation for the setting.")
#[==[.md
# Handling deprecated variables
Use this function when a user-visible flag is being renamed or otherwise
replaced. If the old value is set, it will be given as the default value,
otherwise the given default value will be used. This returned value should then
be used in the `set(CACHE)` or `option()` call for the new value.
If the old value is set, it will warn that it is deprecated for the new name.
If replacing the setting `OLD_SETTING` with `NEW_SETTING`, its usage would look
like:
```cmake
superbuild_deprecated_setting(default_setting NEW_SETTING OLD_SETTING "default value")
set(NEW_SETTING "${default_setting}"
CACHE STRING "Documentation for the setting.")
```
#]==]
function (superbuild_deprecated_setting output_default new old intended_default)
set(default "${intended_default}")
if (DEFINED "${old}")
message(WARNING "The '${old}' variable is deprecated for '${new}'.")
message(DEPRECATION
"The `${old}` variable is deprecated for `${new}`.")
set(default "${${old}}")
endif ()
set("${output_default}" "${default}" PARENT_SCOPE)
endfunction ()
# Determine whether the common superbuild is up-to-date or not.
#
# The common superbuild is intended to be used as a submodule to projects.
# However, updating the submodule when updating the main superbuild is an easy
# step to forget. This function tries to determine whether the common
# superbuild is up-to-date or not and error out if it is not.
#[==[.md
# Catching a stale superbuild submodule
The common superbuild is intended to be used as a submodule to projects.
However, updating the submodule when updating the main superbuild is an easy
step to forget. This function tries to determine whether the common superbuild
is up-to-date or not and error out if it is not.
#]==]
function (_superbuild_check_up_to_date)
file(RELATIVE_PATH common_superbuild_path
"${CMAKE_SOURCE_DIR}"
......
# Superbuild variables
There are many variables that are used within the common superbuild
infrastructure to influence parts of the build that are project-controlled
rather than user-controlled. This documentation covers these variables.
## Projects
### `superbuild_build_phase`
This variable indicates whether the configure is in the "scan" phase where
dependencies are gathered or the "build" phase where the actual commands to be
used are created. During the "build" phase, the following variables are available:
- `<PROJECT>_enabled` If set, the project is enabled in the superbuild.
- `<PROJECT>_built_by_superbuild` If set, the project is also being built by
the superbuild (versus being externally provided).
The values of these variables may only be trusted if `superbuild_build_phase`
is set. Generally, this means that they should not be used in conditionals to
determine dependencies of a project. Instead, triangle dependencies ("`A`
depends on `B` because `C` is enabled") should be handled by having an optional
dependency from `A` on `B` and `C` and if `superbuild_build_phase` is set,
erroring out if `C_enabled` is set and `B_enabled` is not.
### `_superbuild_help_string_<PROJECT>`
Instead of the default help string for the `ENABLE_<PROJECT>` option, a more
descriptive name may be provided.
### `superbuild_install_location`
This variable contains the path that will be given as the installation prefix
to all projects when building and installing. It is also where packaging steps
will look for files to install. If not specified, it defaults to
`${CMAKE_BINARY_DIR}/install`.
### `_superbuild_<PROJECT>_selectable`
If set, the project `PROJECT` is treated as if it has a `SELECTABLE` keyword.
See the documentation for [`superbuild_add_project`][superbuild_add_project].
[superbuild_add_project]: SuperbuildMacros.md#Adding-a-project-to-the-build
### `_superbuild_list_separator`
If a project needs to pass `;` as a flag to a build command, instead, this
variable should be used.
## Building
### `_superbuild_<PROJECT>_default_selection`
For projects which use a source selection, the default selection may be
overriden from the top-level by specifying the selection with this variable.
### `_superbuild_suppress_<PROJECT>_output`
If defined, this is used as the default value for the
`SUPPRESS_<PROJECT>_OUTPUT` variable for the given project.
### `superbuild_is_64bit`
Whether the build is targeting a 32-bit build or 64-bit build. May be removed
in the future if 32-bit support is removed.
Not available during cross-compiling.
### Language flags
The following variables contain (as a string, not a list), the flags to pass to
projects using `CFLAGS`, `CXXFLAGS`, and `LDFLAGS` as environment variables or
through CMake's cache variables.
- `superbuild_c_flags`
- `superbuild_cpp_flags`
- `superbuild_cxx_flags`
- `superbuild_ld_flags`
Superbuild projects may add flags to these by using:
- `superbuild_extra_c_flags`
- `superbuild_extra_cpp_flags`
- `superbuild_extra_cxx_flags`
On Windows, these variables are not supported.
## Testing
### `superbuild_ctest_custom_files`
This is a list of paths to files which are included from the
`CTestCustom.cmake` file. It is read by CTest. Please see the
[CTest variable documentation][] for details (the `CTEST_CUSTOM_` variables).
[CTest variable documentation]: https://cmake.org/cmake/help/git-master/manual/cmake-variables.7.html#variables-for-ctest
## Packaging
These variables are used in packaging tests (mainly `.bundle.cmake` files).
### `superbuild_bundle_skip_system_libraries`
If set in a `bundle.cmake` file, it can be used to skip the
`InstallRequiredSystemLibraries` bit implicit in a packaging test.
### `superbuild_is_install_target`
If set, the package is being installed to the host system, not into a package.
Use of this is mostly internal, but it is available if necessary.
### Variables forwarded from the build
These variables are provided by the superbuild during the packaging step.
- `superbuild_install_location`
- `<PROJECT>_enabled`
- `<PROJECT>_built_by_superbuild`
- `USE_SYSTEM_<PROJECT>`
......@@ -14,6 +14,21 @@
find_package(Git)
#[==[.md
# Detect the version of a source tree
When creating packages, it can be useful to know the specific version of the
source that is being built. To that end, this module provides functions which
determine a version number for a source based on its source selection. It uses
the `<NAME>_SOURCE_DIR` (for a `source` selection) or the build tree location
(for a `git` selection) to query the version of the checked out code using `git
describe`.
If it turns out that Git is either not available or the source directory is not
a Git checkout, it reads a file in the source tree if available and if all else
fails, falls back to a static string.
#]==]
function (_superbuild_detect_version_git var source_dir default version_file)
set(major)
set(minor)
......@@ -46,6 +61,7 @@ function (_superbuild_detect_version_git var source_dir default version_file)
endif ()
endif ()
# If `git describe` failed, check for a version file.
if (result)
set(version_path "${source_dir}/${version_file}")
if (source_dir AND version_file AND EXISTS "${version_path}")
......@@ -57,6 +73,7 @@ function (_superbuild_detect_version_git var source_dir default version_file)
endif ()
endif ()
# Split the version number into fields.
if (output MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
message(STATUS "Determined source version for ${project}: ${CMAKE_MATCH_0}")
set(full "${CMAKE_MATCH_0}")
......@@ -69,6 +86,7 @@ function (_superbuild_detect_version_git var source_dir default version_file)
"Failed to determine the version for ${var}; got ${output}")
endif ()
# Set variables in the parent scope if they're available.
if (full)
set("${var}_VERSION" "${major}.${minor}" PARENT_SCOPE)
set("${var}_VERSION_MAJOR" "${major}" PARENT_SCOPE)
......@@ -84,38 +102,39 @@ function (_superbuild_detect_version_git var source_dir default version_file)
endif ()
endfunction ()
# Set a variable in the parent scope properly while still making it available
# in the current scope..
macro (_superbuild_set_up variable value)
set("${variable}" "${value}"
PARENT_SCOPE)
set("${variable}" "${value}")
endmacro ()
# Extracts the version for a project from its source information or falls back
# to a default.
#
# superbuild_set_version_variables(<project> <default> <include file> [version file])
#
# This will write out a file to ``<include file>`` which may be included to set
# variables related to the versions of the given ``<project>``. If the version
# cannot be determined (e.g., because the project will be cloned during the
# build), the default will be used.
#
# If there is a source directory to be used for the project, the ``<version
# file>`` will be used to get the version number. If it is empty or not
# provided, the default will be used instead.
#
# The variables set are:
#
# <project>_version (as ``<major>.<minor>``)
# <project>_version_major
# <project>_version_minor
# <project>_version_patch
# <project>_version_patch_extra (e.g., ``rc1``)
# <project>_version_suffix (equivalent to ``-<patch_extra>`` if
# ``patch_extra`` is non-empty)
# <project>_version_full
# <project>_version_is_release (``TRUE`` if the suffix is empty, ``FALSE``
# otherwise)
#[==[.md
```
superbuild_set_version_variables(<PROJECT> <DEFAULT> <INCLUDE FILE> [<VERSION FILE>])
```
This will write out a file to `<INCLUDE FILE>` which may be `include`'d after
this function to set variables related to the versions of the given
`<PROJECT>`. If the version cannot be determined (e.g., because the project
will be cloned during the build), the given `DEFAULT` version will be used.
If there is a source directory to be used for the project, the `<VERSION FILE>`
will be used to get the version number. If it is empty or not provided, the
default will be used instead.
The variables available after inclusion are:
`<PROJECT>_version` (as `<major>.<minor>`)
`<PROJECT>_version_major`
`<PROJECT>_version_minor`
`<PROJECT>_version_patch`
`<PROJECT>_version_patch_extra` (e.g., `rc1`)
`<PROJECT>_version_suffix` (equivalent to `-<patch_extra>` if `patch_extra` is non-empty)
`<PROJECT>_version_full`
`<PROJECT>_version_is_release` (`TRUE` if the suffix is empty, `FALSE` otherwise)
#]==]
function (superbuild_set_version_variables project default include_file)
set(source_dir "")
if ((NOT ${project}_FROM_GIT AND ${project}_FROM_SOURCE_DIR) OR ${project}_SOURCE_SELECTION STREQUAL "source")
......
# A wrapper around a process call which checks the command's result.
function (_extract_process input)
execute_process(${ARGN}
RESULT_VARIABLE res
......@@ -8,6 +9,7 @@ function (_extract_process input)
endif ()
endfunction ()
# Extract a package with CMake.
function (_extract_with_cmake output input)
_extract_process("${input}"
COMMAND "${CMAKE_COMMAND}" -E tar
......@@ -15,6 +17,7 @@ function (_extract_with_cmake output input)
WORKING_DIRECTORY "${output}")
endfunction ()
# Detect a tarbomb package.
function (_detect_tarbomb var dir)
file(GLOB contents "${dir}/*")
......@@ -27,6 +30,7 @@ function (_detect_tarbomb var dir)
PARENT_SCOPE)
endfunction ()
# Do the dance to mount and extract a .app from a .dmg file.
function (_extract_dmg output mount input)
_extract_process("${input}"
COMMAND /bin/sh -c
......@@ -45,6 +49,9 @@ function (_extract_dmg output mount input)
"${mount}")
endfunction ()
# Extract a binary from the given directory composed of the given glob into the
# output directory. For simple composition packages (tarballs, zip, etc.),
# non-tarbomb files have their intermediate directories removed.
function (extract_binary dir glob output)
file(REMOVE_RECURSE "${output}")
file(MAKE_DIRECTORY "${output}")
......
#!/usr/bin/env python2.7
'''
A tool to install Mach-O binaries into an ``.app`` bundle.
Other bundle types (particularly ``.framework`` and ``.plugin`` bundles) are
not supported yet.
'''
import json
import os
import os.path
......@@ -9,6 +17,11 @@ import subprocess
class Pipeline(object):
'''
A simple class to handle a list of shell commands which need to pass input
to each other.
'''
def __init__(self, *commands):
if not commands:
raise RuntimeError('Pipeline: at least one command must be given')
......@@ -16,7 +29,8 @@ class Pipeline(object):
self._commands = commands
def __call__(self):
last_input = open('/dev/null', 'r')
# Use /dev/null as the input for the first command.
last_input = open(os.devnull, 'r')
for command_args in self._commands:
command = subprocess.Popen(command_args, stdin=last_input, stdout=subprocess.PIPE)
......@@ -30,6 +44,31 @@ class Pipeline(object):
class Library(object):
'''
A representation of a library.
This class includes information that a runtime loader needs in order to
perform its job. It tries to implement the behavior of ``dyld(1)`` as
closely as possible.
Known Issues
------------
``@rpath/`` and ``DYLD_LIBRARY_PATH``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a library contains a reference to a library like
``@rpath/libname.dylib``, if ``DYLD_LIBRARY_PATH`` is set to contain a path
which has a ``libname.dylib``, ``dyld(1)`` will find it even if no
``LC_RPATH`` commands are present. This behavior is not documented and it
only seems to work if a library is directly underneath a
``DYLD_LIBRARY_PATH`` path. If the library reference is
``@rpath/dir/libname.dylib``, even if a ``dir/libname.dylib`` exists in a
``DYLD_LIBRARY_PATH`` path, it will still not be found. It is unknown
whether this behavior is expected or not due to the lack of documentation.
The logic in this script includes neither of these behaviors.
'''
def __init__(self, path, parent=None, search_paths=None):
# This is the actual path to a physical file
self._path = os.path.normpath(path)
......@@ -58,25 +97,44 @@ class Library(object):
@property
def path(self):
'''The absolute path to the library.'''
return self._path
@property
def parent(self):
'''The binary which loaded the library.'''
return self._parent
@property
def name(self):
'''The name of the library.'''
return os.path.basename(self.path)
@property
def installed_id(self):
'''
The ID of the library.
This is the string by which the library will be referenced by other
binaries in the installation.
'''
return self._installed_id
def set_installed_id(self, installed_id):
'''Set the ID of the library as it is installed as.'''
self._installed_id = installed_id
@property
def dependent_reference(self):
'''
The prefix to use for a library loaded by the library.
This is used as the prefix for IDs for libraries loaded by the library.
It is based on the initial binary which loaded the library. For
example, executables use ``@executable_path`` and plugins use
``@loader_path``. In a chain of loaded libraries, the loader (parent)
of a library determines the prefix.
'''
# Refer to libraries the same way that the library which is loading it
# references it.
if self.parent is None:
......@@ -85,6 +143,12 @@ class Library(object):
@property
def symlinks(self):
'''
A list of symlinks to the library.
Symlinks are looked for only beside the library and the names of these
files are returned, not their full paths.
'''
if self._symlinks is None:
realpath = os.path.realpath(self.path)
dirname = os.path.dirname(realpath)
......@@ -111,20 +175,34 @@ class Library(object):
@property
def executable_path(self):
'''The path to the loading executable (if available).'''
if self._parent is not None:
return self._parent.executable_path
return self._executable_path
@property
def loader_path(self):
'''The path to use for ``@loader_path`` references from the library.'''
return os.path.dirname(self.path)
@property
def is_framework(self):
'''Whether the library is a framework or not.'''
return self.path.count('.framework')
@property
def framework_info(self):
'''
Information for frameworks.
The return value is a tuple of path (where the framework is located),
name (the ``NAME.framework`` part of its path), and associated library
(the path under the ``.framework`` directory which contains the actual
library binary).
See the ``framework_path``, ``framework_name``, and
``framework_library`` properties.
'''
if self._framework_info is None:
if not self.is_framework:
self._framework_info = (None, None, None)
......@@ -152,18 +230,41 @@ class Library(object):
@property
def framework_path(self):
'''
The path which contains the ``.framework`` for the library.
``None`` if the library is not a framework.
'''
return self.framework_info[0]
@property